diff --git a/ground/gcs/src/libs/utils/logfile.cpp b/ground/gcs/src/libs/utils/logfile.cpp
index cc70f1198..ffb0d97c8 100644
--- a/ground/gcs/src/libs/utils/logfile.cpp
+++ b/ground/gcs/src/libs/utils/logfile.cpp
@@ -165,7 +165,7 @@ void LogFile::timerFired()
/*
This code generates an advancing playback window. All samples that fit the window
are replayed. The window is about the size of the timer interval: 10 ms.
-
+
Description of used variables:
time : real-time interval since start of playback (in ms) - now()
@@ -176,8 +176,7 @@ void LogFile::timerFired()
*/
- while ( m_nextTimeStamp < (m_lastPlayed + (double)(time - m_timeOffset) * m_playbackSpeed) ) {
-
+ while (m_nextTimeStamp < (m_lastPlayed + (double)(time - m_timeOffset) * m_playbackSpeed)) {
// advance the replay window for the next time period
m_lastPlayed += ((double)(time - m_timeOffset) * m_playbackSpeed);
@@ -344,12 +343,11 @@ bool LogFile::resumeReplay(quint32 desiredPosition)
Looking for the next log timestamp after the desired position
has the advantage that it skips over parts of the log
where data might be missing.
- */
+ */
for (int i = 0; i < m_timeStamps.size(); i++) {
if (m_timeStamps.at(i) >= desiredPosition) {
-
int bytesToSkip = m_timeStampPositions.at(i);
- bool seek_ok = m_file.seek(bytesToSkip);
+ bool seek_ok = m_file.seek(bytesToSkip);
if (!seek_ok) {
qWarning() << "LogFile resumeReplay - an error occurred while seeking through the logfile.";
}
@@ -365,7 +363,7 @@ bool LogFile::resumeReplay(quint32 desiredPosition)
// Set the real-time interval to 0 to start with:
m_myTime.restart();
- m_timeOffset = 0;
+ m_timeOffset = 0;
m_replayStatus = PLAYING;
@@ -409,7 +407,7 @@ bool LogFile::pauseAndResetPosition()
}
qDebug() << "LogFile - pauseAndResetPosition";
m_timer.stop();
- m_replayStatus = STOPPED;
+ m_replayStatus = STOPPED;
m_timeOffset = 0;
m_lastPlayed = m_timeStamps.at(0);
@@ -467,10 +465,10 @@ bool LogFile::buildIndex()
}
m_timeStamps.append(timeStamp);
m_timeStampPositions.append(readPointer);
- readPointer += TIMESTAMP_SIZE_BYTES;
+ readPointer += TIMESTAMP_SIZE_BYTES;
index++;
m_beginTimeStamp = timeStamp;
- m_endTimeStamp = timeStamp;
+ m_endTimeStamp = timeStamp;
}
while (true) {
@@ -511,7 +509,7 @@ bool LogFile::buildIndex()
if (bytesRead != TIMESTAMP_SIZE_BYTES) {
qWarning() << "LogFile buildIndex - read timeStamp, readRawData returned unexpected number of bytes:" << bytesRead << "at position" << readPointer << "\n";
return false;
- }
+ }
// some validity checks
if (timeStamp < m_endTimeStamp // logfile goes back in time
@@ -522,7 +520,7 @@ bool LogFile::buildIndex()
m_timeStamps.append(timeStamp);
m_timeStampPositions.append(readPointer);
- readPointer += TIMESTAMP_SIZE_BYTES;
+ readPointer += TIMESTAMP_SIZE_BYTES;
index++;
m_endTimeStamp = timeStamp;
} else {
diff --git a/ground/gcs/src/plugins/logging/logging.ui b/ground/gcs/src/plugins/logging/logging.ui
index ed7dbbe6f..421ecb2cd 100644
--- a/ground/gcs/src/plugins/logging/logging.ui
+++ b/ground/gcs/src/plugins/logging/logging.ui
@@ -36,8 +36,8 @@
-
-
- 0
+
+ 80
0
@@ -47,11 +47,17 @@
0
+
+
+ 80
+ 16777215
+
+
Play
-
+
:/logging/images/play.png:/logging/images/play.png
@@ -65,8 +71,8 @@
-
-
- 0
+
+ 80
0
@@ -76,11 +82,17 @@
0
+
+
+ 80
+ 16777215
+
+
Stop
-
+
:/logging/images/stop.png:/logging/images/stop.png
@@ -113,6 +125,12 @@
-
+
+
+ 0
+ 0
+
+
1
@@ -203,6 +221,12 @@
0
+
+
+ 40
+ 0
+
+
@@ -229,6 +253,12 @@
0
+
+
+ 40
+ 0
+
+
@@ -255,6 +285,12 @@
0
+
+
+ 40
+ 0
+
+
@@ -283,7 +319,7 @@
-
+
diff --git a/ground/gcs/src/plugins/logging/logginggadgetwidget.cpp b/ground/gcs/src/plugins/logging/logginggadgetwidget.cpp
index 5fdc2773f..945c8f3f2 100644
--- a/ground/gcs/src/plugins/logging/logginggadgetwidget.cpp
+++ b/ground/gcs/src/plugins/logging/logginggadgetwidget.cpp
@@ -41,6 +41,9 @@ LoggingGadgetWidget::LoggingGadgetWidget(QWidget *parent) : QWidget(parent), log
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
scpPlugin = pm->getObject();
+ // Store preferred button width before manipulating the button appearance
+ m_preferredButtonWidth = m_logging->playPauseButton->sizeHint().width();
+
disableButtons();
// Configure timer to delay application of slider position action for 200ms
@@ -60,65 +63,92 @@ void LoggingGadgetWidget::setPlugin(LoggingPlugin *p)
loggingPlugin = p;
LogFile *logFile = loggingPlugin->getLogfile();
- // GUI elements to gadgetwidget functions
+ // GUI elements to gadgetwidget functions
connect(m_logging->playPauseButton, &QPushButton::clicked, this, &LoggingGadgetWidget::playPauseButtonAction);
connect(m_logging->stopButton, &QPushButton::clicked, this, &LoggingGadgetWidget::stopButtonAction);
connect(m_logging->playBackPosition, &QSlider::valueChanged, this, &LoggingGadgetWidget::sliderMoved);
connect(m_logging->playbackSpeed, static_cast(&QDoubleSpinBox::valueChanged), logFile, &LogFile::setReplaySpeed);
- // gadgetwidget functions to logfile actions
+ // gadgetwidget functions to logfile actions
connect(this, &LoggingGadgetWidget::resumeReplay, logFile, &LogFile::resumeReplay);
connect(this, &LoggingGadgetWidget::pauseReplay, logFile, &LogFile::pauseReplay);
connect(this, &LoggingGadgetWidget::pauseAndResetPosition, logFile, &LogFile::pauseAndResetPosition);
- // gadgetwidget functions to scope actions
+ // gadgetwidget functions to scope actions
connect(this, &LoggingGadgetWidget::resumeReplay, scpPlugin, &ScopeGadgetFactory::startPlotting);
connect(this, &LoggingGadgetWidget::pauseReplay, scpPlugin, &ScopeGadgetFactory::stopPlotting);
connect(this, &LoggingGadgetWidget::pauseAndResetPosition, scpPlugin, &ScopeGadgetFactory::stopPlotting);
- // Feedback from logfile to GUI
+ // Feedback from logfile to GUI
connect(loggingPlugin, &LoggingPlugin::stateChanged, this, &LoggingGadgetWidget::stateChanged);
connect(logFile, &LogFile::updateBeginAndEndTimes, this, &LoggingGadgetWidget::updateBeginAndEndTimes);
connect(logFile, &LogFile::playbackPosition, this, &LoggingGadgetWidget::playbackPosition);
connect(logFile, &LogFile::replayStarted, this, &LoggingGadgetWidget::enableButtons);
connect(logFile, &LogFile::replayFinished, this, &LoggingGadgetWidget::disableButtons);
- // Feedback from logfile to scope
+ // Feedback from logfile to scope
connect(logFile, &LogFile::replayFinished, scpPlugin, &ScopeGadgetFactory::stopPlotting);
-
+ // Perform actions as if the plugin state has been changed
stateChanged(loggingPlugin->getState());
}
+/*
+ resizeEvent()
+
+ Determine button content policy based on button size.
+
+ */
+void LoggingGadgetWidget::resizeEvent(QResizeEvent *event)
+{
+ int width = m_logging->playPauseButton->size().width();
+
+ if (width < m_preferredButtonWidth) {
+ m_iconOnlyButtons = true;
+ } else {
+ m_iconOnlyButtons = false;
+ }
+ updateButtonAppearance();
+
+ QWidget::resizeEvent(event);
+}
/*
setPlayPauseButtonToPlay()
Changes the appearance of the playPause button to the PLAY appearance.
-*/
+ */
void LoggingGadgetWidget::setPlayPauseButtonToPlay()
{
m_logging->playPauseButton->setIcon(QIcon(":/logging/images/play.png"));
- m_logging->playPauseButton->setText(tr(" Play"));
+ if (m_iconOnlyButtons) {
+ m_logging->playPauseButton->setText(QString());
+ } else {
+ m_logging->playPauseButton->setText(tr(" Play"));
+ }
}
/*
- setPlayPauseButtonToPlay()
+ setPlayPauseButtonToPause()
Changes the appearance of the playPause button to the PAUSE appearance.
-*/
+ */
void LoggingGadgetWidget::setPlayPauseButtonToPause()
{
m_logging->playPauseButton->setIcon(QIcon(":/logging/images/pause.png"));
- m_logging->playPauseButton->setText(tr(" Pause"));
+ if (m_iconOnlyButtons) {
+ m_logging->playPauseButton->setText(QString());
+ } else {
+ m_logging->playPauseButton->setText(tr(" Pause"));
+ }
}
void LoggingGadgetWidget::playPauseButtonAction()
{
ReplayState replayState = (loggingPlugin->getLogfile())->getReplayStatus();
- if (replayState == PLAYING){
+ if (replayState == PLAYING) {
emit pauseReplay();
setPlayPauseButtonToPlay();
} else {
@@ -151,7 +181,7 @@ void LoggingGadgetWidget::stateChanged(LoggingPlugin::State state)
switch (state) {
case LoggingPlugin::IDLE:
- status = tr("Idle");
+ status = tr("Idle");
playbackPosition(0);
break;
case LoggingPlugin::LOGGING:
@@ -167,7 +197,7 @@ void LoggingGadgetWidget::stateChanged(LoggingPlugin::State state)
bool playing = loggingPlugin->getLogfile()->isPlaying();
m_logging->stopButton->setEnabled(enabled && playing);
m_logging->playPauseButton->setEnabled(enabled);
- if (playing){
+ if (playing) {
setPlayPauseButtonToPause();
} else {
setPlayPauseButtonToPlay();
@@ -181,8 +211,8 @@ void LoggingGadgetWidget::updateBeginAndEndTimes(quint32 startTimeStamp, quint32
startSec = (startTimeStamp / 1000) % 60;
startMin = startTimeStamp / (60 * 1000);
- endSec = (endTimeStamp / 1000) % 60;
- endMin = endTimeStamp / (60 * 1000);
+ endSec = (endTimeStamp / 1000) % 60;
+ endMin = endTimeStamp / (60 * 1000);
// update start and end labels
m_logging->startTimeLabel->setText(QString("%1:%2").arg(startMin, 2, 10, QChar('0')).arg(startSec, 2, 10, QChar('0')));
@@ -202,7 +232,6 @@ void LoggingGadgetWidget::playbackPosition(quint32 positionTimeStamp)
{
// Update position bar, but only if the user is not updating the slider position
if (!m_logging->playBackPosition->isSliderDown() && !sliderActionDelay.isActive()) {
-
// Block signals during slider position update:
m_logging->playBackPosition->blockSignals(true);
m_logging->playBackPosition->setValue(positionTimeStamp);
@@ -217,8 +246,7 @@ void LoggingGadgetWidget::enableButtons()
{
ReplayState replayState = (loggingPlugin->getLogfile())->getReplayStatus();
- switch (replayState)
- {
+ switch (replayState) {
case STOPPED:
m_logging->stopButton->setEnabled(false);
setPlayPauseButtonToPlay();
@@ -240,7 +268,6 @@ void LoggingGadgetWidget::enableButtons()
void LoggingGadgetWidget::disableButtons()
{
-
m_logging->playPauseButton->setEnabled(false);
setPlayPauseButtonToPlay();
m_logging->stopButton->setEnabled(false);
@@ -248,11 +275,40 @@ void LoggingGadgetWidget::disableButtons()
m_logging->playBackPosition->setEnabled(false);
}
+void LoggingGadgetWidget::updateButtonAppearance()
+{
+ ReplayState replayState;
+
+ if (!loggingPlugin || !loggingPlugin->getLogfile()) {
+ // loggingPlugin has not been completely initialized: set to STOPPED state
+ replayState = STOPPED;
+ } else {
+ replayState = (loggingPlugin->getLogfile())->getReplayStatus();
+ }
+
+ // Update playPause button appearance
+ if (replayState == PLAYING) {
+ // Playing: playPause button must appear as a pause button
+ setPlayPauseButtonToPause();
+ } else {
+ // Stopped or Paused: playPause button must appear as a play button
+ setPlayPauseButtonToPlay();
+ }
+
+ // Update stop button appearance
+ if (m_iconOnlyButtons) {
+ m_logging->stopButton->setText(QString());
+ } else {
+ m_logging->stopButton->setText(tr(" Stop"));
+ }
+}
+
void LoggingGadgetWidget::updatePositionLabel(quint32 positionTimeStamp)
{
// update position label -> MM:SS
int sec = (positionTimeStamp / 1000) % 60;
int min = positionTimeStamp / (60 * 1000);
+
m_logging->positionTimestampLabel->setText(QString("%1:%2").arg(min, 2, 10, QChar('0')).arg(sec, 2, 10, QChar('0')));
}
@@ -273,7 +329,6 @@ void LoggingGadgetWidget::sliderAction()
}
-
/**
* @}
* @}
diff --git a/ground/gcs/src/plugins/logging/logginggadgetwidget.h b/ground/gcs/src/plugins/logging/logginggadgetwidget.h
index 34491936e..d2603472e 100644
--- a/ground/gcs/src/plugins/logging/logginggadgetwidget.h
+++ b/ground/gcs/src/plugins/logging/logginggadgetwidget.h
@@ -68,10 +68,14 @@ private:
LoggingPlugin *loggingPlugin;
ScopeGadgetFactory *scpPlugin;
QTimer sliderActionDelay;
+ bool m_iconOnlyButtons;
+ int m_preferredButtonWidth;
void updatePositionLabel(quint32 positionTimeStamp);
void setPlayPauseButtonToPlay();
void setPlayPauseButtonToPause();
+ void updateButtonAppearance();
+ void resizeEvent(QResizeEvent *event);
};
#endif /* LoggingGADGETWIDGET_H_ */