Trainmode: Show textcues in WorkoutPlotWindow (#4710)

New option to show textcues and notifications (Connected.., New lap..,
...) /not only in the TrainBottoms message field but also in the
WorkoutPlotWindows title. This allows having the textcues while saving
the space for TrainBottom, especially useful for low resolutions.
This commit is contained in:
Joachim Kohlhammer
2025-10-10 23:13:41 +02:00
committed by GitHub
parent 45b366b68c
commit 20a0facd43
6 changed files with 107 additions and 54 deletions

View File

@@ -222,6 +222,9 @@ class Context : public QObject
void notifySeek(long x) { emit seek(x); }
void notifyIntensityChanged(int intensity) { emit intensityChanged(intensity); };
void notifySetNotification(const QString &msg, int timeout) { emit setNotification(msg, timeout); };
void notifyClearNotification() { emit clearNotification(); };
// date range selection
void notifyDateRangeChanged(DateRange x) { dr_=x; emit dateRangeSelected(x); }
void notifyWorkoutsChanged() { emit workoutsChanged(); }
@@ -354,6 +357,9 @@ class Context : public QObject
void stop();
void intensityChanged(int intensity);
void setNotification(const QString &msg, int timeout);
void clearNotification();
// R messages
void rMessage(QString);

View File

@@ -211,8 +211,8 @@ TrainBottom::TrainBottom(TrainSidebar *trainSidebar, QWidget *parent) :
connect(intensitySlider, SIGNAL(valueChanged(int)), m_trainSidebar, SLOT(adjustIntensity(int)));
connect(m_trainSidebar->context, SIGNAL(intensityChanged(int)), intensitySlider, SLOT(setValue(int)));
connect(m_trainSidebar, SIGNAL(setNotification(QString, int)), this, SLOT(setNotification(QString, int)));
connect(m_trainSidebar, SIGNAL(clearNotification(void)), this, SLOT(clearNotification(void)));
connect(m_trainSidebar->context, SIGNAL(setNotification(QString, int)), this, SLOT(setNotification(QString, int)));
connect(m_trainSidebar->context, SIGNAL(clearNotification(void)), this, SLOT(clearNotification(void)));
connect(m_trainSidebar->context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));

View File

@@ -1311,7 +1311,7 @@ void TrainSidebar::Start() // when start button is pressed
// tell the world
context->notifyUnPause();
emit setNotification(tr("Resuming.."), 2);
context->notifySetNotification(tr("Resuming.."), 2);
} else if (status&RT_RUNNING) {
@@ -1338,7 +1338,7 @@ void TrainSidebar::Start() // when start button is pressed
// tell the world
context->notifyPause();
emit setNotification(tr("Paused.."), 2);
context->notifySetNotification(tr("Paused.."), 2);
} else if (status&RT_CONNECTED) {
@@ -1349,7 +1349,7 @@ void TrainSidebar::Start() // when start button is pressed
secs_to_start--;
}
if (secs_to_start > 0) {
emit setNotification(tr("Starting in %1").arg(secs_to_start), 1);
context->notifySetNotification(tr("Starting in %1").arg(secs_to_start), 1);
start_timer->start(1000);
return;
}
@@ -1467,7 +1467,7 @@ void TrainSidebar::Start() // when start button is pressed
}
gui_timer->start(REFRESHRATE); // start recording
emit setNotification(tr("Starting.."), 2);
context->notifySetNotification(tr("Starting.."), 2);
}
}
@@ -1675,7 +1675,7 @@ void TrainSidebar::Stop(int deviceStatus) // when stop button is pressed
ergFileQueryAdapter.resetQueryState();
guiUpdate();
emit setNotification(tr("Stopped.."), 2);
context->notifySetNotification(tr("Stopped.."), 2);
return;
}
@@ -1762,12 +1762,12 @@ void TrainSidebar::Connect()
Devices[dev].controller->start();
Devices[dev].controller->resetCalibrationState();
connect(Devices[dev].controller, &RealtimeController::setNotification, this, &TrainSidebar::setNotification);
connect(Devices[dev].controller, &RealtimeController::setNotification, context, &Context::setNotification);
}
setStatusFlags(RT_CONNECTED);
gui_timer->start(REFRESHRATE);
emit setNotification(tr("Connected.."), 2);
context->notifySetNotification(tr("Connected.."), 2);
}
void TrainSidebar::Disconnect()
@@ -1784,14 +1784,14 @@ void TrainSidebar::Disconnect()
qDebug() << "disconnecting..";
foreach(int dev, activeDevices) {
disconnect(Devices[dev].controller, &RealtimeController::setNotification, this, &TrainSidebar::setNotification);
disconnect(Devices[dev].controller, &RealtimeController::setNotification, context, &Context::setNotification);
Devices[dev].controller->stop();
}
clearStatusFlags(RT_CONNECTED);
gui_timer->stop();
emit setNotification(tr("Disconnected.."), 2);
context->notifySetNotification(tr("Disconnected.."), 2);
}
//----------------------------------------------------------------------
@@ -2105,7 +2105,7 @@ void TrainSidebar::guiUpdate() // refreshes the telemetry
if (ergFileQueryAdapter.textsInRange(lapPosition, searchRange, rangeStart, rangeEnd)) {
for (int idx = rangeStart; idx <= rangeEnd; idx++) {
ErgFileText cue = ergFile->Texts.at(idx);
emit setNotification(cue.text, cue.duration);
context->notifySetNotification(cue.text, cue.duration);
}
textPositionEmitted = lapPosition + searchRange;
}
@@ -2212,8 +2212,7 @@ void TrainSidebar::newLap()
ergFileQueryAdapter.addNewLap(displayWorkoutDistance * 1000.) >= 0) {
context->notifyNewLap();
emit setNotification(tr("New lap.."), 2);
context->notifySetNotification(tr("New lap.."), 2);
}
}
@@ -2240,7 +2239,7 @@ void TrainSidebar::resetTextAudioEmitTracking()
void TrainSidebar::steerScroll(int scrollAmount)
{
if (scrollAmount == 0)
emit setNotification(tr("Recalibrating steering.."), 10);
context->notifySetNotification(tr("Recalibrating steering.."), 10);
else
context->notifySteerScroll(scrollAmount);
}
@@ -2496,7 +2495,7 @@ void TrainSidebar::updateCalibration()
// leaving calibration, clear any notification text
status = QString(tr("Exiting calibration.."));
emit setNotification(status,3);
context->notifySetNotification(status,3);
} else {
@@ -2761,7 +2760,7 @@ void TrainSidebar::updateCalibration()
lastState = calibrationState;
// set notification text, no timeout
emit setNotification(status, 0);
context->notifySetNotification(status, 0);
}
}
@@ -2792,7 +2791,7 @@ void TrainSidebar::FFwd()
maintainLapDistanceState();
emit setNotification(tr("Fast forward.."), 2);
context->notifySetNotification(tr("Fast forward.."), 2);
}
void TrainSidebar::Rewind()
@@ -2825,7 +2824,7 @@ void TrainSidebar::Rewind()
maintainLapDistanceState();
emit setNotification(tr("Rewind.."), 2);
context->notifySetNotification(tr("Rewind.."), 2);
}
@@ -2855,7 +2854,7 @@ void TrainSidebar::FFwdLap()
maintainLapDistanceState();
if (lapmarker >= 0) emit setNotification(tr("Next Lap.."), 2);
if (lapmarker >= 0) context->notifySetNotification(tr("Next Lap.."), 2);
}
// jump to next Lap marker (if there is one?)
@@ -2888,7 +2887,7 @@ void TrainSidebar::RewindLap()
maintainLapDistanceState();
if (lapmarker >= 0) emit setNotification(tr("Back Lap.."), 2);
if (lapmarker >= 0) context->notifySetNotification(tr("Back Lap.."), 2);
}
@@ -2914,7 +2913,7 @@ void TrainSidebar::Higher()
foreach(int dev, activeDevices) Devices[dev].controller->setGradient(slope);
}
emit setNotification(tr("Increasing intensity.."), 2);
context->notifySetNotification(tr("Increasing intensity.."), 2);
}
// lower load/gradient
@@ -2940,7 +2939,7 @@ void TrainSidebar::Lower()
foreach(int dev, activeDevices) Devices[dev].controller->setGradient(slope);
}
emit setNotification(tr("Decreasing intensity.."), 2);
context->notifySetNotification(tr("Decreasing intensity.."), 2);
}
void TrainSidebar::setLabels()

View File

@@ -138,8 +138,6 @@ class TrainSidebar : public GcWindow
void pause();
void stop();
void statusChanged(int status);
void setNotification(QString msg, int timeout);
void clearNotification(void);
private slots:
void deviceTreeWidgetSelectionChanged();

View File

@@ -21,9 +21,6 @@
#include "Context.h"
#include "HelpWhatsThis.h"
#include <QFormLayout>
#include <QGroupBox>
WorkoutPlotWindow::WorkoutPlotWindow(Context *context) :
GcChartWindow(context), context(context)
@@ -31,35 +28,35 @@ WorkoutPlotWindow::WorkoutPlotWindow(Context *context) :
HelpWhatsThis *helpContents = new HelpWhatsThis(this);
this->setWhatsThis(helpContents->getWhatsThisText(HelpWhatsThis::ChartTrain_Workout));
// Chart settings
QWidget *settingsWidget = new QWidget(this);
settingsWidget->setContentsMargins(0, 0, 0, 0);
ctrlsShowNotification = new QCheckBox();
connect(ctrlsShowNotification, &QCheckBox::toggled, this, &WorkoutPlotWindow::setShowNotifications);
QVBoxLayout *commonLayout = new QVBoxLayout(settingsWidget);
ctrlsCommonLabel = new QLabel();
ctrlsErgmodeLabel = new QLabel();
ctrlsGroupBox = new QGroupBox(tr("Ergmode specific settings"));
commonLayout->addWidget(ctrlsGroupBox);
commonLayout->addStretch();
QFormLayout *ergmodeLayout = new QFormLayout(ctrlsGroupBox);
ctrlsSituationLabel = new QLabel(tr("Color power zones"));
ctrlsSituationLabel = new QLabel();
ctrlsSituation = new QComboBox();
ctrlsSituation->addItem(tr("Never"));
ctrlsSituation->addItem(tr("Always"));
ctrlsSituation->addItem(tr("When stopped"));
ctrlsSituation->addItem("");
ctrlsSituation->addItem("");
ctrlsSituation->addItem("");
connect(ctrlsSituation, SIGNAL(currentIndexChanged(int)), this, SLOT(setShowColorZones(int)));
ergmodeLayout->addRow(ctrlsSituationLabel, ctrlsSituation);
ctrlsShowTooltipLabel = new QLabel(tr("Show tooltip"));
ctrlsShowTooltipLabel = new QLabel();
ctrlsShowTooltip = new QComboBox();
ctrlsShowTooltip->addItem(tr("Never"));
ctrlsShowTooltip->addItem(tr("When stopped"));
ctrlsShowTooltip->addItem("");
ctrlsShowTooltip->addItem("");
connect(ctrlsShowTooltip, SIGNAL(currentIndexChanged(int)), this, SLOT(setShowTooltip(int)));
ergmodeLayout->addRow(ctrlsShowTooltipLabel, ctrlsShowTooltip);
QFormLayout *settingsLayout = newQFormLayout();
settingsLayout->addRow(ctrlsCommonLabel);
settingsLayout->addRow("", ctrlsShowNotification);
settingsLayout->addItem(new QSpacerItem(0, 15 * dpiYFactor));
settingsLayout->addRow(ctrlsErgmodeLabel);
settingsLayout->addRow(ctrlsSituationLabel, ctrlsSituation);
settingsLayout->addRow(ctrlsShowTooltipLabel, ctrlsShowTooltip);
setContentsMargins(0,0,0,0);
setControls(settingsWidget);
setControls(centerLayoutInWidget(settingsLayout, false));
setProperty("color", GColor(CTRAINPLOTBACKGROUND));
QVBoxLayout *layout = new QVBoxLayout;
@@ -69,12 +66,37 @@ WorkoutPlotWindow::WorkoutPlotWindow(Context *context) :
ergPlot = new ErgFilePlot(context);
layout->addWidget(ergPlot);
QTimer *notificationTimer = new QTimer(this);
connect(context, SIGNAL(setNow(long)), this, SLOT(setNow(long)));
connect(context, SIGNAL(ergFileSelected(ErgFile*)), this, SLOT(ergFileSelected(ErgFile*)));
connect(context, SIGNAL(telemetryUpdate(RealtimeData)), ergPlot, SLOT(performancePlot(RealtimeData)));
connect(context, SIGNAL(start()), ergPlot, SLOT(start()));
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
connect(notificationTimer, &QTimer::timeout, this, [=]() {
setProperty("subtitle", title);
});
connect(context, &Context::setNotification, this, [=](QString notification, int timeout) {
if (! showNotifications()) {
return;
}
if (timeout > 0) {
notificationTimer->setInterval(timeout * 1000);
notificationTimer->setSingleShot(true);
notificationTimer->start();
} else {
notificationTimer->stop();
}
setProperty("subtitle", notification);
});
connect(context, &Context::clearNotification, this, [=]() {
setProperty("subtitle", title);
});
configChanged(0);
// Initil setup based on currently selected workout
ergFileSelected(context->currentErgFile());
}
@@ -83,8 +105,9 @@ void
WorkoutPlotWindow::ergFileSelected(ErgFile *f)
{
// rename window to workout name
if (f && f->name() != "") setProperty("subtitle", f->name());
else setProperty("subtitle", "");
if (f && f->name() != "") title = f->name();
else title = "";
setProperty("subtitle", title);
ergPlot->setData(f);
ergPlot->replot();
@@ -102,7 +125,11 @@ WorkoutPlotWindow::configChanged(qint32)
{
setProperty("color", GColor(CTRAINPLOTBACKGROUND));
ctrlsGroupBox->setTitle(tr("Ergmode specific settings"));
ctrlsCommonLabel->setText("<b>" + tr("Common settings") + "</b>");
ctrlsShowNotification->setText(tr("Show notifications and textcues in title"));
ctrlsErgmodeLabel->setText("<b>" + tr("Ergmode specific settings") + "</b>");
ctrlsSituationLabel->setText(tr("Color power zones"));
ctrlsSituation->setItemText(0, tr("Never"));
ctrlsSituation->setItemText(1, tr("Always"));
@@ -116,6 +143,25 @@ WorkoutPlotWindow::configChanged(qint32)
}
bool
WorkoutPlotWindow::showNotifications
() const
{
return ctrlsShowNotification->isChecked();
}
void
WorkoutPlotWindow::setShowNotifications
(bool show)
{
if (! show) {
setProperty("subtitle", title);
}
ctrlsShowNotification->setChecked(show);
}
int
WorkoutPlotWindow::showColorZones
() const

View File

@@ -32,15 +32,14 @@
#include "Settings.h"
#include "Colors.h"
#include <QGroupBox>
#include <QLabel>
#include <QComboBox>
class WorkoutPlotWindow : public GcChartWindow
{
Q_OBJECT
G_OBJECT
Q_PROPERTY(int showNotifications READ showNotifications WRITE setShowNotifications USER true)
Q_PROPERTY(int showColorZones READ showColorZones WRITE setShowColorZones USER true)
Q_PROPERTY(int showTooltip READ showTooltip WRITE setShowTooltip USER true)
@@ -55,17 +54,22 @@ class WorkoutPlotWindow : public GcChartWindow
void ergFileSelected(ErgFile *);
void configChanged(qint32);
bool showNotifications() const;
void setShowNotifications(bool show);
int showColorZones() const;
void setShowColorZones(int index);
int showTooltip() const;
void setShowTooltip(int index);
private:
QString title;
Context *context;
ErgFilePlot *ergPlot;
QGroupBox *ctrlsGroupBox;
QLabel *ctrlsCommonLabel;
QCheckBox *ctrlsShowNotification;
QLabel *ctrlsErgmodeLabel;
QLabel *ctrlsSituationLabel;
QComboBox *ctrlsSituation;
QLabel *ctrlsShowTooltipLabel;