Skip to content

Commit 186c992

Browse files
committed
add progress indication to the tick textfield, improve appearance
1 parent 564906b commit 186c992

4 files changed

Lines changed: 164 additions & 7 deletions

File tree

QtSLiM/QtSLiMExtras.cpp

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <cmath>
4343

4444
#include "QtSLiMPreferences.h"
45+
#include "QtSLiMAppDelegate.h"
4546

4647
#include "eidos_value.h"
4748

@@ -208,8 +209,18 @@ void RGBForSelectionCoeff(double value, float *colorRed, float *colorGreen, floa
208209

209210
// A subclass of QLineEdit that selects all its text when it receives keyboard focus
210211
// thanks to https://stackoverflow.com/a/51807268/2752221
211-
QtSLiMGenerationLineEdit::QtSLiMGenerationLineEdit(const QString &contents, QWidget *p_parent) : QLineEdit(contents, p_parent) { }
212-
QtSLiMGenerationLineEdit::QtSLiMGenerationLineEdit(QWidget *p_parent) : QLineEdit(p_parent) { }
212+
QtSLiMGenerationLineEdit::QtSLiMGenerationLineEdit(const QString &contents, QWidget *p_parent) : QLineEdit(contents, p_parent)
213+
{
214+
connect(qtSLiMAppDelegate, &QtSLiMAppDelegate::applicationPaletteChanged, this, [this]() { _ReconfigureAppearance(); });
215+
_ReconfigureAppearance();
216+
}
217+
218+
QtSLiMGenerationLineEdit::QtSLiMGenerationLineEdit(QWidget *p_parent) : QLineEdit(p_parent)
219+
{
220+
connect(qtSLiMAppDelegate, &QtSLiMAppDelegate::applicationPaletteChanged, this, [this]() { _ReconfigureAppearance(); });
221+
_ReconfigureAppearance();
222+
}
223+
213224
QtSLiMGenerationLineEdit::~QtSLiMGenerationLineEdit() {}
214225

215226
void QtSLiMGenerationLineEdit::focusInEvent(QFocusEvent *p_event)
@@ -222,6 +233,103 @@ void QtSLiMGenerationLineEdit::focusInEvent(QFocusEvent *p_event)
222233
QTimer::singleShot(0, this, &QLineEdit::selectAll);
223234
}
224235

236+
void QtSLiMGenerationLineEdit::setProgress(double p_progress)
237+
{
238+
double newProgress = std::min(std::max(p_progress, 0.0), 1.0);
239+
240+
if (newProgress != progress)
241+
{
242+
progress = newProgress;
243+
update();
244+
}
245+
}
246+
247+
void QtSLiMGenerationLineEdit::_ReconfigureAppearance()
248+
{
249+
// Eight states, based on three binary flags; but two states never happen in practice
250+
bool darkMode = QtSLiMInDarkMode();
251+
bool enabled = isEnabled();
252+
253+
if (darkMode)
254+
{
255+
if (enabled)
256+
{
257+
if (dimmed)
258+
setStyleSheet("color: red; background-color: black"); // doesn't happen
259+
else
260+
setStyleSheet("color: rgb(255, 255, 255); background-color: black"); // not playing
261+
}
262+
else
263+
{
264+
if (dimmed)
265+
setStyleSheet("color: rgb(40, 40, 40); background-color: black"); // error state (not normally visible)
266+
else
267+
setStyleSheet("color: rgb(170, 170, 170); background-color: black"); // playing
268+
}
269+
}
270+
else
271+
{
272+
if (enabled)
273+
{
274+
if (dimmed)
275+
setStyleSheet("color: red; background-color: white"); // doesn't happen
276+
else
277+
setStyleSheet("color: rgb(0, 0, 0); background-color: white"); // not playing
278+
}
279+
else
280+
{
281+
if (dimmed)
282+
setStyleSheet("color: rgb(192, 192, 192); background-color: white"); // error state (not normally visible)
283+
else
284+
setStyleSheet("color: rgb(120, 120, 120); background-color: white"); // playing
285+
}
286+
}
287+
288+
update();
289+
}
290+
291+
void QtSLiMGenerationLineEdit::setAppearance(bool p_enabled, bool p_dimmed)
292+
{
293+
if ((isEnabled() != p_enabled) || (dimmed != p_dimmed))
294+
{
295+
setEnabled(p_enabled);
296+
dimmed = p_dimmed;
297+
298+
_ReconfigureAppearance();
299+
}
300+
}
301+
302+
void QtSLiMGenerationLineEdit::paintEvent(QPaintEvent *p_paintEvent)
303+
{
304+
// first let super draw
305+
QLineEdit::paintEvent(p_paintEvent);
306+
307+
// then overlay a progress bar on top, if requested, and if we are not disabled & dimmed (error state)
308+
bool enabled = isEnabled();
309+
310+
if (!enabled && dimmed)
311+
return;
312+
313+
if (progress > 0.0)
314+
{
315+
bool darkMode = QtSLiMInDarkMode();
316+
QPainter painter(this);
317+
QRect bounds = rect().adjusted(2, 2, -2, -2);
318+
319+
bounds.setWidth(round(bounds.width() * progress));
320+
321+
if (darkMode) {
322+
// lighten the black background to a dark green; text is unaffected since it's light
323+
painter.setCompositionMode(QPainter::CompositionMode_Lighten);
324+
painter.fillRect(bounds, QColor(0, 120, 0));
325+
} else {
326+
// darken the white background to a light green; text is unaffected since it's dark
327+
painter.setCompositionMode(QPainter::CompositionMode_Darken);
328+
painter.fillRect(bounds, QColor(180, 255, 180));
329+
}
330+
}
331+
}
332+
225333
void ColorizePropertySignature(const EidosPropertySignature *property_signature, double pointSize, QTextCursor lineCursor)
226334
{
227335
//

QtSLiM/QtSLiMExtras.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ QString QtSLiMImagePath(QString baseName, bool highlighted);
6262

6363

6464
// A subclass of QLineEdit that selects all its text when it receives keyboard focus
65+
// It also supports showing a "progress bar" under its text, and it has a modified
66+
// appearance that can be disabled but still show fairly dark text for readability
6567
class QtSLiMGenerationLineEdit : public QLineEdit
6668
{
6769
Q_OBJECT
@@ -71,13 +73,25 @@ class QtSLiMGenerationLineEdit : public QLineEdit
7173
QtSLiMGenerationLineEdit(QWidget *p_parent = nullptr);
7274
virtual ~QtSLiMGenerationLineEdit() override;
7375

76+
// can optionally display "progress" in the background of the lineedit
77+
void setProgress(double p_progress);
78+
79+
// set its appearance/behavior; do not use setEnabled(), use this!
80+
void setAppearance(bool p_enabled, bool p_dimmed);
81+
7482
protected:
7583
virtual void focusInEvent(QFocusEvent *p_event) override;
84+
virtual void paintEvent(QPaintEvent *p_paintEvent) override;
7685

7786
private:
7887
QtSLiMGenerationLineEdit() = delete;
7988
QtSLiMGenerationLineEdit(const QtSLiMGenerationLineEdit&) = delete;
8089
QtSLiMGenerationLineEdit& operator=(const QtSLiMGenerationLineEdit&) = delete;
90+
91+
void _ReconfigureAppearance(void);
92+
93+
double progress = 0.0;
94+
bool dimmed = false;
8195
};
8296

8397
void ColorizePropertySignature(const EidosPropertySignature *property_signature, double pointSize, QTextCursor lineCursor);

QtSLiM/QtSLiMWindow.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,13 @@ void QtSLiMWindow::init(void)
298298
connect(this, &QtSLiMWindow::controllerChangeCountChanged, this, [this]() { updateRecycleButtonIcon(false); });
299299

300300
// Ensure that the tick lineedit does not have the initial keyboard focus and has no selection; hard to do!
301+
// BCH 5 August 2022: this code is no longer working, the tick lineedit still has initial focus, sigh; I added
302+
// the call to ui->scriptTextEdit->setFocus() and that seems to do it, not sure why I didn't do that before;
303+
// but since this seems to be fragile, I'm going to leave *both* approaches in the code here, maybe which
304+
// approach works depends on the Qt version or the platform or something. Forward in all directions!
301305
ui->tickLineEdit->setFocusPolicy(Qt::FocusPolicy::NoFocus);
302306
QTimer::singleShot(0, [this]() { ui->tickLineEdit->setFocusPolicy(Qt::FocusPolicy::StrongFocus); });
307+
ui->scriptTextEdit->setFocus();
303308

304309
// watch for a change to light mode / dark mode, to customize display of the play speed slider for example
305310
connect(qtSLiMAppDelegate, &QtSLiMAppDelegate::applicationPaletteChanged, this, &QtSLiMWindow::applicationPaletteChanged);
@@ -2040,11 +2045,25 @@ void QtSLiMWindow::updateTickCounter(void)
20402045
ui->cycleLineEdit->setText(QString::number(displaySpecies->Cycle()));
20412046

20422047
if (!community)
2048+
{
20432049
ui->tickLineEdit->setText("");
2050+
ui->tickLineEdit->setProgress(0.0);
2051+
}
20442052
else if (community->Tick() == 0)
2053+
{
20452054
ui->tickLineEdit->setText("initialize()");
2055+
ui->tickLineEdit->setProgress(0.0);
2056+
}
20462057
else
2047-
ui->tickLineEdit->setText(QString::number(community->Tick()));
2058+
{
2059+
slim_tick_t tick = community->Tick();
2060+
slim_tick_t lastTick = community->EstimatedLastTick();
2061+
2062+
double progress = (lastTick > 0) ? (tick / (double)lastTick) : 0.0;
2063+
2064+
ui->tickLineEdit->setText(QString::number(tick));
2065+
ui->tickLineEdit->setProgress(progress);
2066+
}
20482067
}
20492068

20502069
void QtSLiMWindow::updateSpeciesBar(void)
@@ -2480,9 +2499,25 @@ void QtSLiMWindow::updateUIEnabling(void)
24802499
ui->recycleButton->setEnabled(!continuousPlayOn_);
24812500

24822501
ui->playSpeedSlider->setEnabled(!invalidSimulation_);
2483-
ui->tickLineEdit->setEnabled(!reachedSimulationEnd_ && !continuousPlayOn_);
2484-
ui->cycleLineEdit->setEnabled(!reachedSimulationEnd_ && !continuousPlayOn_);
2485-
2502+
2503+
if (invalidSimulation_)
2504+
{
2505+
// when an error occurs, we want these textfields to have a dimmed/disabled appearance
2506+
ui->tickLineEdit->setAppearance(/* enabled */ false, /* dimmed */ true);
2507+
ui->cycleLineEdit->setAppearance(/* enabled */ false, /* dimmed */ true);
2508+
}
2509+
else
2510+
{
2511+
// otherwise, we want an enabled _appearance_ at all times, but we have to disable them
2512+
// to prevent editing during play; so we set the text color to prevent it from dimming
2513+
// note that the cycle lineedit is always disabled, but follows the appearance of the tick lineedit;
2514+
// the "editable but dimmed" visual appearance is actually a little different so hopefully this is clear
2515+
bool editingAllowed = (!reachedSimulationEnd_ && !continuousPlayOn_);
2516+
2517+
ui->tickLineEdit->setAppearance(/* enabled */ editingAllowed, /* dimmed */ false);
2518+
ui->cycleLineEdit->setAppearance(/* enabled */ false, /* dimmed */ false);
2519+
}
2520+
24862521
ui->toggleDrawerButton->setEnabled(true);
24872522

24882523
ui->clearDebugButton->setEnabled(true);

QtSLiM/QtSLiMWindow.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ QSlider::handle:horizontal:disabled {
517517
</widget>
518518
</item>
519519
<item>
520-
<widget class="QLineEdit" name="cycleLineEdit">
520+
<widget class="QtSLiMGenerationLineEdit" name="cycleLineEdit">
521521
<property name="maximumSize">
522522
<size>
523523
<width>100</width>

0 commit comments

Comments
 (0)