PeriodicUpdateWidget.cpp
Go to the documentation of this file.
2
3#include <cmath>
4
5#include <QCheckBox>
6#include <QDoubleSpinBox>
7#include <QHBoxLayout>
8#include <QPushButton>
9#include <QTimer>
10
12{
13 PeriodicUpdateWidget::PeriodicUpdateWidget(double frequency, double maxFrequency)
14 {
15 setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum);
16
17 QLayout* vlayout = new QVBoxLayout();
18 QLayout* hlayout = new QHBoxLayout();
19 this->setLayout(vlayout);
20
21 const int margin = 0;
22 hlayout->setContentsMargins(margin, margin, margin, margin);
23
24 _updateButton = new QPushButton("Update", this);
25 _autoCheckBox = new QCheckBox("Auto Update", this);
26 _frequencySpinBox = new QDoubleSpinBox(this);
27 _frequencySpinBox->setValue(frequency);
28 _frequencySpinBox->setMinimum(0);
29 _frequencySpinBox->setMaximum(maxFrequency);
30 _frequencySpinBox->setSingleStep(0.5);
31 _frequencySpinBox->setSuffix(" Hz");
32
33 hlayout->addWidget(_updateButton);
34 hlayout->addWidget(_autoCheckBox);
35 hlayout->addWidget(_frequencySpinBox);
36
37 vlayout->addItem(hlayout);
38
39
40 _timer = new QTimer(this);
41 _updateTimerFrequency();
42 _frequencySpinBox->setEnabled(_autoCheckBox->isChecked());
43
44
45 // Private connections.
46 connect(_autoCheckBox, &QCheckBox::toggled, this, &This::_toggleAutoUpdates);
47 connect(_frequencySpinBox,
48 &QDoubleSpinBox::editingFinished,
49 this,
50 &This::_updateTimerFrequency);
51
52 // Public connections.
53 connect(_updateButton, &QPushButton::pressed, this, &This::updateSingle);
54 connect(_timer, &QTimer::timeout, this, &This::updatePeriodic);
55
56 connect(this, &This::updateSingle, this, &This::update);
57 connect(this, &This::updatePeriodic, this, &This::update);
58
59 // See `startTimerIfEnabled` for the signal reasoning.
60 // qOverload is required because `QTimer::start()` is overloaded.
61 connect(this, &This::startTimerSignal, _timer, qOverload<>(&QTimer::start));
62 connect(this, &This::stopTimerSignal, _timer, &QTimer::stop);
63 }
64
65 QPushButton*
67 {
68 return _updateButton;
69 }
70
71 int
73 {
74 return static_cast<int>(std::round(1000 / _frequencySpinBox->value()));
75 }
76
77 void
79 {
80 /* A QTimer can only be started and stopped within its own thread (the thread for which
81 * it has the greatest affinity). Since this method can be called from any thread, we
82 * need to take a detour through these signals, which can be emitted from any thread and
83 * will always be caught in this object's (and thus the timer's) native thread.
84 */
85 if (_autoCheckBox->isChecked())
86 {
87 emit startTimerSignal();
88 }
89 else
90 {
91 emit stopTimerSignal();
92 }
93 }
94
95 void
97 {
98 // See `startTimerIfEnabled` for the signal reasoning.
99 emit stopTimerSignal();
100 }
101
102 void
104 {
105 if (isAutoEnabled())
106 {
107 _autoCheckBox->setChecked(false);
108 }
109 }
110
111 void
112 PeriodicUpdateWidget::_updateTimerFrequency()
113 {
114 _timer->setInterval(getUpdateIntervalMs());
115 }
116
117 void
118 PeriodicUpdateWidget::_toggleAutoUpdates(bool enabled)
119 {
120 // This method is already a slot, so it doesn't need to use the timer signals.
121 _frequencySpinBox->setEnabled(enabled);
122 if (enabled)
123 {
124 _timer->start();
125 }
126 else
127 {
128 _timer->stop();
129 }
130 }
131
132 QCheckBox*
134 {
135 return _autoCheckBox;
136 }
137
138 QDoubleSpinBox*
140 {
141 return _frequencySpinBox;
142 }
143
144 QTimer*
146 {
147 return _timer;
148 }
149
150 bool
152 {
153 return _autoCheckBox->isChecked();
154 }
155
156} // namespace armarx::skills::gui
PeriodicUpdateWidget(double frequency=2.0, double maxFrequency=60)