• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mcallegari / qlcplus / 19144422256

06 Nov 2025 05:33PM UTC coverage: 34.256% (-0.1%) from 34.358%
19144422256

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.66
/ui/src/speeddial.cpp
1
/*
2
  Q Light Controller
3
  speeddial.cpp
4

5
  Copyright (c) Heikki Junnila
6

7
  Licensed under the Apache License, Version 2.0 (the "License");
8
  you may not use this file except in compliance with the License.
9
  You may obtain a copy of the License at
10

11
      http://www.apache.org/licenses/LICENSE-2.0.txt
12

13
  Unless required by applicable law or agreed to in writing, software
14
  distributed under the License is distributed on an "AS IS" BASIS,
15
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
  See the License for the specific language governing permissions and
17
  limitations under the License.
18
*/
19

20
#include <QElapsedTimer>
21
#include <QHBoxLayout>
22
#include <QVBoxLayout>
23
#include <QFocusEvent>
24
#include <QPushButton>
25
#include <QToolButton>
26
#include <QCheckBox>
27
#include <QLabel>
28
#include <QTimer>
29
#include <QDebug>
30
#include <QDial>
31
#include <qmath.h>
32

33
#include "speeddial.h"
34
#include "qlcmacros.h"
35
#include "function.h"
36

37
#define THRESHOLD 10
38
#define HRS_MAX   (596 - 1) // INT_MAX can hold 596h 31m 23s 647ms
39
#define MIN_MAX   59
40
#define SEC_MAX   59
41
#define MS_MAX    999
42

43
#define TIMER_HOLD       250
44
#define TIMER_REPEAT     10
45
#define TAP_STOP_TIMEOUT 30000
46
#define MIN_FLASH_TIME   125
47

48
#define DEFAULT_VISIBILITY_MASK 0x00FF
49

50
const QString tapDefaultSS = "QPushButton { background-color: #DDDDDD; border: 2px solid #6A6A6A; border-radius: 5px; }"
51
                             "QPushButton:pressed { background-color: #AAAAAA; }"
52
                             "QPushButton:disabled { border: 2px solid #BBBBBB; }";
53

54
const QString tapTickSS = "QPushButton { background-color: #DDDDDD; border: 3px solid #2B2595; border-radius: 5px; }"
55
                          "QPushButton:pressed { background-color: #AAAAAA; }"
56
                          "QPushButton:disabled { border: 2px solid #BBBBBB; }";
57

58
/****************************************************************************
59
 * FocusSpinBox
60
 ****************************************************************************/
61

62
FocusSpinBox::FocusSpinBox(QWidget* parent)
8✔
63
    : QSpinBox(parent)
8✔
64
{
65
}
8✔
66

67
void FocusSpinBox::focusInEvent(QFocusEvent* event)
×
68
{
69
    if (event->gotFocus() == true)
×
70
        emit focusGained();
×
71
}
×
72

73
/****************************************************************************
74
 * SpeedDial
75
 ****************************************************************************/
76

77
SpeedDial::SpeedDial(QWidget* parent)
2✔
78
    : QGroupBox(parent)
79
    , m_timer(new QTimer(this))
2✔
80
    , m_dial(NULL)
2✔
81
    , m_hrs(NULL)
2✔
82
    , m_min(NULL)
2✔
83
    , m_sec(NULL)
2✔
84
    , m_ms(NULL)
2✔
85
    , m_focus(NULL)
2✔
86
    , m_previousDialValue(0)
2✔
87
    , m_preventSignals(false)
2✔
88
    , m_value(0)
2✔
89
    , m_tapTick(false)
2✔
90
    , m_tapTime(NULL)
2✔
91
    , m_tapTickTimer(NULL)
2✔
92
    , m_tapTickElapseTimer(NULL)
2✔
93
    , m_visibilityMask(DEFAULT_VISIBILITY_MASK)
4✔
94
{
95
    new QVBoxLayout(this);
2✔
96
    layout()->setSpacing(0);
2✔
97
    layout()->setContentsMargins(2, 2, 2, 2);
2✔
98

99
    QHBoxLayout* topHBox = new QHBoxLayout();
2✔
100
    QVBoxLayout* pmVBox1 = new QVBoxLayout();
2✔
101
    QVBoxLayout* taVBox3 = new QVBoxLayout();
2✔
102
    layout()->addItem(topHBox);
2✔
103

104
    m_plus = new QToolButton(this);
2✔
105
    m_plus->setIconSize(QSize(32, 32));
2✔
106
    m_plus->setIcon(QIcon(":/edit_add.png"));
2✔
107
    pmVBox1->addWidget(m_plus, Qt::AlignVCenter | Qt::AlignLeft);
2✔
108
    connect(m_plus, SIGNAL(pressed()), this, SLOT(slotPlusMinus()));
2✔
109
    connect(m_plus, SIGNAL(released()), this, SLOT(slotPlusMinus()));
2✔
110

111
    m_minus = new QToolButton(this);
2✔
112
    m_minus->setIconSize(QSize(32, 32));
2✔
113
    m_minus->setIcon(QIcon(":/edit_remove.png"));
2✔
114
    pmVBox1->addWidget(m_minus, Qt::AlignVCenter | Qt::AlignLeft);
2✔
115
    connect(m_minus, SIGNAL(pressed()), this, SLOT(slotPlusMinus()));
2✔
116
    connect(m_minus, SIGNAL(released()), this, SLOT(slotPlusMinus()));
2✔
117
    topHBox->addItem(pmVBox1);
2✔
118

119
    m_dial = new QDial(this);
2✔
120
    m_dial->setWrapping(true);
2✔
121
    m_dial->setNotchesVisible(true);
2✔
122
    m_dial->setNotchTarget(15);
2✔
123
    m_dial->setTracking(true);
2✔
124
    topHBox->addWidget(m_dial);
2✔
125
    connect(m_dial, SIGNAL(valueChanged(int)), this, SLOT(slotDialChanged(int)));
2✔
126

127
    m_tap = new QPushButton(tr("Tap"), this);
2✔
128
    m_tap->setStyleSheet(tapDefaultSS);
2✔
129
    m_tap->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
2✔
130
    taVBox3->addWidget(m_tap);
2✔
131
    connect(m_tap, SIGNAL(clicked()), this, SLOT(slotTapClicked()));
2✔
132

133
    topHBox->addItem (taVBox3);
2✔
134

135
    QHBoxLayout* timeHBox = new QHBoxLayout();
2✔
136
    layout()->addItem(timeHBox);
2✔
137

138
    m_hrs = new FocusSpinBox(this);
2✔
139
    m_hrs->setRange(0, HRS_MAX);
2✔
140
    m_hrs->setSuffix("h");
2✔
141
    m_hrs->setButtonSymbols(QSpinBox::NoButtons);
2✔
142
    m_hrs->setToolTip(tr("Hours"));
2✔
143
    timeHBox->addWidget(m_hrs);
2✔
144
    connect(m_hrs, SIGNAL(valueChanged(int)), this, SLOT(slotHoursChanged()));
2✔
145
    connect(m_hrs, SIGNAL(focusGained()), this, SLOT(slotSpinFocusGained()));
2✔
146

147
    m_min = new FocusSpinBox(this);
2✔
148
    m_min->setRange(0, MIN_MAX);
2✔
149
    m_min->setSuffix("m");
2✔
150
    m_min->setButtonSymbols(QSpinBox::NoButtons);
2✔
151
    m_min->setToolTip(tr("Minutes"));
2✔
152
    timeHBox->addWidget(m_min);
2✔
153
    connect(m_min, SIGNAL(valueChanged(int)), this, SLOT(slotMinutesChanged()));
2✔
154
    connect(m_min, SIGNAL(focusGained()), this, SLOT(slotSpinFocusGained()));
2✔
155

156
    m_sec = new FocusSpinBox(this);
2✔
157
    m_sec->setRange(0, SEC_MAX);
2✔
158
    m_sec->setSuffix("s");
2✔
159
    m_sec->setButtonSymbols(QSpinBox::NoButtons);
2✔
160
    m_sec->setToolTip(tr("Seconds"));
2✔
161
    timeHBox->addWidget(m_sec);
2✔
162
    connect(m_sec, SIGNAL(valueChanged(int)), this, SLOT(slotSecondsChanged()));
2✔
163
    connect(m_sec, SIGNAL(focusGained()), this, SLOT(slotSpinFocusGained()));
2✔
164

165
    m_ms = new FocusSpinBox(this);
2✔
166
    m_ms->setRange(0, MS_MAX);
2✔
167
    m_ms->setSuffix("ms");
2✔
168
    m_ms->setButtonSymbols(QSpinBox::NoButtons);
2✔
169
    m_ms->setToolTip(tr("Milliseconds"));
2✔
170
    timeHBox->addWidget(m_ms);
2✔
171
    connect(m_ms, SIGNAL(valueChanged(int)), this, SLOT(slotMSChanged()));
2✔
172
    connect(m_ms, SIGNAL(focusGained()), this, SLOT(slotSpinFocusGained()));
2✔
173

174
    m_infiniteCheck = new QCheckBox(this);
2✔
175
    m_infiniteCheck->setText(tr("Infinite"));
2✔
176
    layout()->addWidget(m_infiniteCheck);
2✔
177
    connect(m_infiniteCheck, SIGNAL(toggled(bool)), this, SLOT(slotInfiniteChecked(bool)));
2✔
178

179
    m_focus = m_ms;
2✔
180
    m_dial->setRange(m_focus->minimum(), m_focus->maximum());
2✔
181
    m_dial->setSingleStep(m_focus->singleStep());
2✔
182

183
    m_timer->setInterval(TIMER_HOLD);
2✔
184
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotPlusMinusTimeout()));
2✔
185

186
    m_tapTickElapseTimer = new QTimer();
2✔
187
    m_tapTickElapseTimer->setTimerType(Qt::PreciseTimer);
2✔
188
    m_tapTickElapseTimer->setSingleShot(true);
2✔
189
    connect(m_tapTickElapseTimer, SIGNAL(timeout()),
2✔
190
                this, SLOT(slotTapTimeout()));
191

192
    //Hide elements according to current visibility mask
193
    setVisibilityMask(m_visibilityMask);
2✔
194
}
2✔
195

196
SpeedDial::~SpeedDial()
2✔
197
{
198
    if (m_tapTickElapseTimer)
2✔
199
    {
200
        delete m_tapTickElapseTimer;
2✔
201
        m_tapTickElapseTimer = NULL;
2✔
202
    }
203
    stopTimers();
2✔
204
}
2✔
205

206
void SpeedDial::setValue(int ms, bool emitValue)
1✔
207
{
208
    if (emitValue == false)
1✔
209
        m_preventSignals = true;
1✔
210

211
    m_value = ms;
1✔
212
    setSpinValues(ms);
1✔
213

214
    if (ms == (int) Function::infiniteSpeed())
1✔
215
        m_infiniteCheck->setChecked(true);
×
216
    else
217
        m_infiniteCheck->setChecked(false);
1✔
218

219
    // time has changed - update tap button blinking
220
    updateTapTimer();
1✔
221

222
    m_preventSignals = false;
1✔
223
}
1✔
224

225
int SpeedDial::value() const
2✔
226
{
227
    return m_value;
2✔
228
}
229

230
void SpeedDial::tap()
1✔
231
{
232
    m_tap->click();
1✔
233
}
1✔
234

235
void SpeedDial::toggleInfinite()
1✔
236
{
237
    m_infiniteCheck->toggle();
1✔
238
}
1✔
239

240
void SpeedDial::stopTimers(bool stopTime, bool stopTapTimer)
3✔
241
{
242
    if (stopTime && m_tapTime != NULL)
3✔
243
    {
244
        delete m_tapTime;
×
245
        m_tapTime = NULL;
×
246
    }
247
    if (stopTapTimer && m_tapTickTimer != NULL)
3✔
248
    {
249
        m_tapTickTimer->stop();
1✔
250
        delete m_tapTickTimer;
1✔
251
        m_tapTickTimer = NULL;
1✔
252
        m_tap->setStyleSheet(tapDefaultSS);
1✔
253
        m_tapTick = false;
1✔
254
    }
255
}
3✔
256

257
bool SpeedDial::isTapTick()
×
258
{
259
    return m_tapTick;
×
260
}
261

262
/*****************************************************************************
263
 * Private
264
 *****************************************************************************/
265

266
void SpeedDial::updateTapTimer()
1✔
267
{
268
    // Synchronize timer ticks
269
    if (m_tapTickTimer)
1✔
270
        m_tapTickTimer->stop();
×
271

272
    if (m_value != (int) Function::infiniteSpeed()
1✔
273
       && m_tapTickTimer == NULL)
1✔
274
    {
275
        m_tapTickTimer = new QTimer();
1✔
276
        m_tapTickTimer->setTimerType(Qt::PreciseTimer);
1✔
277

278
        connect(m_tapTickTimer, SIGNAL(timeout()), this, SLOT(slotTapTimeout()));
1✔
279
    }
280

281
    if (m_tapTickTimer)
1✔
282
    {
283
        m_tapTickTimer->setInterval(m_value);
1✔
284
        // Limit m_tapTickElapseTimer's interval to 20/200ms for nice effect
285
        if (m_value > 1000)
1✔
286
            m_tapTickElapseTimer->setInterval(200);
1✔
287
        else
288
            m_tapTickElapseTimer->setInterval(m_value / 3);
×
289

290
        if (m_tapTickTimer->interval() > 0)
1✔
291
            m_tapTickTimer->start();
1✔
292
    }
293
}
1✔
294

295
void SpeedDial::setSpinValues(int ms)
1✔
296
{
297
    // block signals to prevent each single SpinBox to send
298
    // a valueChanged signal. For example going from 1m0s to 59s
299
    // would send two signals: 0 and then 59000.
300
    // We want to avoid that non-sense 0
301
    // Just send one single signal when everything has changed
302
    m_hrs->blockSignals(true);
1✔
303
    m_min->blockSignals(true);
1✔
304
    m_sec->blockSignals(true);
1✔
305
    m_ms->blockSignals(true);
1✔
306

307
    if (ms == (int) Function::infiniteSpeed())
1✔
308
    {
309
        m_hrs->setValue(m_hrs->minimum());
×
310
        m_min->setValue(m_min->minimum());
×
311
        m_sec->setValue(m_sec->minimum());
×
312
        m_ms->setValue(m_ms->minimum());
×
313
    }
314
    else
315
    {
316
        ms = CLAMP(ms, 0, INT_MAX);
1✔
317

318
        m_hrs->setValue(ms / MS_PER_HOUR);
1✔
319
        ms -= (m_hrs->value() * MS_PER_HOUR);
1✔
320

321
        m_min->setValue(ms / MS_PER_MINUTE);
1✔
322
        ms -= (m_min->value() * MS_PER_MINUTE);
1✔
323

324
        m_sec->setValue(ms / MS_PER_SECOND);
1✔
325
        ms -= (m_sec->value() * MS_PER_SECOND);
1✔
326

327
        m_ms->setValue(ms);
1✔
328
    }
329
    m_hrs->blockSignals(false);
1✔
330
    m_min->blockSignals(false);
1✔
331
    m_sec->blockSignals(false);
1✔
332
    m_ms->blockSignals(false);
1✔
333
    if (m_preventSignals == false)
1✔
334
    {
335
        m_value = spinValues();
×
336
        emit valueChanged(m_value);
×
337
    }
338
}
1✔
339

340
int SpeedDial::spinValues() const
×
341
{
342
    int value = 0;
×
343

344
    if (m_infiniteCheck->isChecked() == false)
×
345
    {
346
        value += m_hrs->value() * MS_PER_HOUR;
×
347
        value += m_min->value() * MS_PER_MINUTE;
×
348
        value += m_sec->value() * MS_PER_SECOND;
×
349
        value += m_ms->value();
×
350
    }
351
    else
352
    {
353
        value = Function::infiniteSpeed();
×
354
    }
355

356
    return CLAMP(value, 0, INT_MAX);
×
357
}
358

359
int SpeedDial::dialDiff(int value, int previous, int step)
×
360
{
361
    int diff = value - previous;
×
362
    if (diff > THRESHOLD)
×
363
        diff = -step;
×
364
    else if (diff < (-THRESHOLD))
×
365
        diff = step;
×
366
    return diff;
×
367
}
368

369
void SpeedDial::slotPlusMinus()
×
370
{
371
    if (m_minus->isDown() == true || m_plus->isDown() == true)
×
372
    {
373
        slotPlusMinusTimeout();
×
374
        m_timer->start(TIMER_HOLD);
×
375
    }
376
    else
377
    {
378
        m_timer->stop();
×
379
    }
380
}
×
381

382
void SpeedDial::slotPlusMinusTimeout()
×
383
{
384
    if (m_minus->isDown() == true)
×
385
    {
386
        if (m_dial->value() == m_dial->minimum())
×
387
            m_dial->setValue(m_dial->maximum()); // Wrap around
×
388
        else
389
            m_dial->setValue(m_dial->value() - m_dial->singleStep()); // Normal increment
×
390
        m_timer->start(TIMER_REPEAT);
×
391
    }
392
    else if (m_plus->isDown() == true)
×
393
    {
394
        if (m_dial->value() == m_dial->maximum())
×
395
            m_dial->setValue(m_dial->minimum()); // Wrap around
×
396
        else
397
            m_dial->setValue(m_dial->value() + m_dial->singleStep()); // Normal increment
×
398
        m_timer->start(TIMER_REPEAT);
×
399
    }
400
}
×
401

402
void SpeedDial::slotDialChanged(int value)
×
403
{
404
    Q_ASSERT(m_focus != NULL);
×
405

406
    int newValue = dialDiff(value, m_previousDialValue, m_dial->singleStep()) + m_focus->value();
×
407
    if (newValue > m_focus->maximum())
×
408
    {
409
        // Incremented value is above m_focus->maximum(). Spill the overflow to the
410
        // bigger number (unless already incrementing hours).
411
        if (m_focus == m_ms)
×
412
            m_value += m_ms->singleStep();
×
413
        else if (m_focus == m_sec)
×
414
            m_value += MS_PER_SECOND;
×
415
        else if (m_focus == m_min)
×
416
            m_value += MS_PER_MINUTE;
×
417

418
        m_value = CLAMP(m_value, 0, INT_MAX);
×
419
        setSpinValues(m_value);
×
420
    }
421
    else if (newValue < m_focus->minimum())
×
422
    {
423
        newValue = m_value;
×
424
        // Decremented value is below m_focus->minimum(). Spill the underflow to the
425
        // smaller number (unless already decrementing milliseconds).
426
        if (m_focus == m_ms)
×
427
            newValue -= m_ms->singleStep();
×
428
        else if (m_focus == m_sec)
×
429
            newValue -= MS_PER_SECOND;
×
430
        else if (m_focus == m_min)
×
431
            newValue -= MS_PER_MINUTE;
×
432

433
        if (newValue >= 0)
×
434
        {
435
            m_value = newValue;
×
436
            m_value = CLAMP(m_value, 0, INT_MAX);
×
437
            setSpinValues(m_value);
×
438
        }
439
    }
440
    else
441
    {
442
        // Normal value increment/decrement.
443
        m_value = newValue;
×
444
        m_value = CLAMP(m_value, 0, INT_MAX);
×
445
        m_focus->setValue(m_value);
×
446
    }
447

448
    // update tap button blinking
449
    updateTapTimer();
×
450

451
    // Store the current value so it can be compared on the next pass to determine the
452
    // dial's direction of rotation.
453
    m_previousDialValue = value;
×
454
}
×
455

456
void SpeedDial::slotHoursChanged()
×
457
{
458
    if (m_preventSignals == false)
×
459
    {
460
        m_value = spinValues();
×
461
        emit valueChanged(m_value);
×
462
    }
463
    // update tap button blinking
464
    updateTapTimer();
×
465
}
×
466

467
void SpeedDial::slotMinutesChanged()
×
468
{
469
    if (m_preventSignals == false)
×
470
    {
471
        m_value = spinValues();
×
472
        emit valueChanged(m_value);
×
473
    }
474
    // update tap button blinking
475
    updateTapTimer();
×
476
}
×
477

478
void SpeedDial::slotSecondsChanged()
×
479
{
480
    if (m_preventSignals == false)
×
481
    {
482
        m_value = spinValues();
×
483
        emit valueChanged(m_value);
×
484
    }
485
    // update tap button blinking
486
    updateTapTimer();
×
487
}
×
488

489
void SpeedDial::slotMSChanged()
×
490
{
491
    if (m_preventSignals == false)
×
492
    {
493
        m_value = spinValues();
×
494
        emit valueChanged(m_value);
×
495
    }
496
    // update tap button blinking
497
    updateTapTimer();
×
498
}
×
499

500
void SpeedDial::slotInfiniteChecked(bool state)
1✔
501
{
502
    m_minus->setEnabled(!state);
1✔
503
    m_dial->setEnabled(!state);
1✔
504
    m_plus->setEnabled(!state);
1✔
505
    m_hrs->setEnabled(!state);
1✔
506
    m_min->setEnabled(!state);
1✔
507
    m_sec->setEnabled(!state);
1✔
508
    m_ms->setEnabled(!state);
1✔
509
    m_tap->setEnabled(!state);
1✔
510

511
    if (state == true)
1✔
512
    {
513
        m_value = Function::infiniteSpeed();
1✔
514
        if (m_preventSignals == false)
1✔
515
            emit valueChanged(Function::infiniteSpeed());
1✔
516

517
        // stop tap button blinking if it was
518
        stopTimers();
1✔
519
    }
520
    else
521
    {
522
        m_value = spinValues();
×
523
        if (m_preventSignals == false)
×
524
            emit valueChanged(m_value);
×
525

526

527
        // update tap button blinking
528
        updateTapTimer();
×
529
    }
530
}
1✔
531

532
void SpeedDial::slotSpinFocusGained()
×
533
{
534
    m_focus = qobject_cast <FocusSpinBox*> (QObject::sender());
×
535
    Q_ASSERT(m_focus != NULL);
×
536
    m_dial->setRange(m_focus->minimum(), m_focus->maximum());
×
537
    m_dial->setSingleStep(m_focus->singleStep());
×
538
}
×
539

540
void SpeedDial::slotTapClicked()
×
541
{
542
    if (m_tapTime == NULL)
×
543
    {
544
        m_tapTime = new QElapsedTimer();
×
545
        m_tapTime->start();
×
546
        return;
×
547
    }
548
    // Round the elapsed time to the nearest full 10th ms.
549
    m_value = m_tapTime->elapsed();
×
550
    m_tapTime->restart();
×
551

552
    // If it's been a while since the last tap, reset the history and just use the time since the last tap
553
    if (m_value > 1500)
×
554
    {
555
        // TODO: shift the tempo slightly upward or downward and re-phase the tempo
556
        m_tapHistory.clear();
×
557
        // TODO: If m_value is above the widget's maximum, then ignore this tap altogether
558
        setSpinValues(m_value);
×
559
        updateTapTimer();
×
560
        emit tapped();
×
561
        return;
×
562
    }
563

564
    // If multiple taps have been input recently,
565
    // find the tempo that best passes through all of them.
566
    m_tapHistory.append(m_value);
×
567
    // This algorithm stabilizes around a tempo very quickly,
568
    // so keeping more than a few taps in the history merely complicates tempo changes.
569
    while (m_tapHistory.count() > 16)
×
570
        m_tapHistory.removeFirst();
×
571

572
    // Find the median time between taps, assume that the tempo is +-40% of this
573
    QList<int> tapHistorySorted(m_tapHistory);
×
574
    std::sort(tapHistorySorted.begin(), tapHistorySorted.end());
×
575
    int tapHistoryMedian = tapHistorySorted[tapHistorySorted.length()/2];
×
576

577
    // Tempo detection is not as easy as averaging together the durations,
578
    // which causes all but the first and last taps to cancel each other out.
579
    // Instead, plot each tap as time since first tap over the beat number,
580
    // and the tempo will be the slope of a linear regression through the points.
581
    // Initialize the data with the first tap at (0, 0).
582
    // Use a float, otherwise (n * sum_xy) will overflow very quickly.
583
    float n = 1, x = 0, y = 0, sum_x = 0, sum_y = 0, sum_xx = 0, sum_xy = 0;
×
584
    foreach (int interval_ms, m_tapHistory)
×
585
    {
586
        n += 1;
×
587
        // Divide by tapHistoryMedian to determine if a tap was skipped during input
588
        x += (tapHistoryMedian/2 + interval_ms) / tapHistoryMedian;
×
589
        y += interval_ms;
×
590
        sum_x += x;
×
591
        sum_y += y;
×
592
        sum_xx += x * x;
×
593
        sum_xy += x * y;
×
594
    }
×
595
    int slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x);
×
596
    setSpinValues(slope);
×
597

598
    // time has changed - update tap button blinking
599
    updateTapTimer();
×
600

601
    emit tapped();
×
602
}
×
603

604
void SpeedDial::slotTapTimeout()
×
605
{
606
    if (m_value <= MIN_FLASH_TIME)
×
607
        return;
×
608

609
    if (m_tapTick == false)
×
610
    {
611
        m_tapTickElapseTimer->start(); // turn off tap light after some time
×
612
        m_tap->setStyleSheet(tapTickSS);
×
613
    }
614
    else
615
    {
616
        m_tap->setStyleSheet(tapDefaultSS);
×
617
    }
618
    m_tapTick = !m_tapTick;
×
619

620
    if (m_tapTime && m_tapTime->elapsed() >= TAP_STOP_TIMEOUT)
×
621
    {
622
        stopTimers(true, false);
×
623
    }
624
    emit tapTimeout();
×
625
}
626

627
quint16 SpeedDial::defaultVisibilityMask()
1✔
628
{
629
    return DEFAULT_VISIBILITY_MASK;
1✔
630
}
631

632
quint16 SpeedDial::visibilityMask()
×
633
{
634
    return m_visibilityMask;
×
635
}
636

637
void SpeedDial::setVisibilityMask(quint16 mask)
2✔
638
{
639
    if (mask & PlusMinus)
2✔
640
    {
641
        m_plus->show();
2✔
642
        m_minus->show();
2✔
643
    }
644
    else
645
    {
646
        m_plus->hide();
×
647
        m_minus->hide();
×
648
    }
649

650
    if (mask & Dial) m_dial->show();
2✔
651
    else m_dial->hide();
×
652

653
    if (mask & Tap) m_tap->show();
2✔
654
    else m_tap->hide();
×
655

656
    if (mask & Hours) m_hrs->show();
2✔
657
    else m_hrs->hide();
×
658

659
    if (mask & Minutes) m_min->show();
2✔
660
    else m_min->hide();
×
661

662
    if (mask & Seconds) m_sec->show();
2✔
663
    else m_sec->hide();
×
664

665
    if (mask & Milliseconds) m_ms->show();
2✔
666
    else m_ms->hide();
×
667

668
    if (mask & Infinite) m_infiniteCheck->show();
2✔
669
    else m_infiniteCheck->hide();
×
670

671
    m_visibilityMask = mask;
2✔
672
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc