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

mcallegari / qlcplus / 13633248611

03 Mar 2025 02:31PM UTC coverage: 31.871% (+0.4%) from 31.5%
13633248611

push

github

web-flow
actions: add chrpath to profile

14689 of 46089 relevant lines covered (31.87%)

26426.11 hits per line

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

0.0
/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)
×
63
    : QSpinBox(parent)
×
64
{
65
}
×
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)
×
78
    : QGroupBox(parent)
79
    , m_timer(new QTimer(this))
×
80
    , m_dial(NULL)
×
81
    , m_hrs(NULL)
×
82
    , m_min(NULL)
×
83
    , m_sec(NULL)
×
84
    , m_ms(NULL)
×
85
    , m_focus(NULL)
×
86
    , m_previousDialValue(0)
×
87
    , m_preventSignals(false)
×
88
    , m_value(0)
×
89
    , m_tapTick(false)
×
90
    , m_tapTime(NULL)
×
91
    , m_tapTickTimer(NULL)
×
92
    , m_tapTickElapseTimer(NULL)
×
93
    , m_visibilityMask(DEFAULT_VISIBILITY_MASK)
×
94
{
95
    new QVBoxLayout(this);
×
96
    layout()->setSpacing(0);
×
97
    layout()->setContentsMargins(2, 2, 2, 2);
×
98

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

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

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

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

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

133
    topHBox->addItem (taVBox3);
×
134

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

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

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

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

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

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

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

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

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

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

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

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

211
    m_value = ms;
×
212
    setSpinValues(ms);
×
213

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

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

222
    m_preventSignals = false;
×
223
}
×
224

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

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

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

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

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

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

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

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

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

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

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

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

316
        m_hrs->setValue(ms / MS_PER_HOUR);
×
317
        ms -= (m_hrs->value() * MS_PER_HOUR);
×
318

319
        m_min->setValue(ms / MS_PER_MINUTE);
×
320
        ms -= (m_min->value() * MS_PER_MINUTE);
×
321

322
        m_sec->setValue(ms / MS_PER_SECOND);
×
323
        ms -= (m_sec->value() * MS_PER_SECOND);
×
324

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

338
int SpeedDial::spinValues() const
×
339
{
340
    int value = 0;
341

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

354
    return CLAMP(value, 0, INT_MAX);
×
355
}
356

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

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

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

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

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

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

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

446
    // update tap button blinking
447
    updateTapTimer();
×
448

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

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

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

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

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

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

509
    if (state == true)
×
510
    {
511
        m_value = Function::infiniteSpeed();
×
512
        if (m_preventSignals == false)
×
513
            emit valueChanged(Function::infiniteSpeed());
×
514

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

524

525
        // update tap button blinking
526
        updateTapTimer();
×
527
    }
528
}
×
529

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

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

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

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

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

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

596
    // time has changed - update tap button blinking
597
    updateTapTimer();
×
598

599
    emit tapped();
×
600
}
×
601

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

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

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

625
quint16 SpeedDial::defaultVisibilityMask()
×
626
{
627
    return DEFAULT_VISIBILITY_MASK;
×
628
}
629

630
quint16 SpeedDial::visibilityMask()
×
631
{
632
    return m_visibilityMask;
×
633
}
634

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

648
    if (mask & Dial) m_dial->show();
×
649
    else m_dial->hide();
×
650

651
    if (mask & Tap) m_tap->show();
×
652
    else m_tap->hide();
×
653

654
    if (mask & Hours) m_hrs->show();
×
655
    else m_hrs->hide();
×
656

657
    if (mask & Minutes) m_min->show();
×
658
    else m_min->hide();
×
659

660
    if (mask & Seconds) m_sec->show();
×
661
    else m_sec->hide();
×
662

663
    if (mask & Milliseconds) m_ms->show();
×
664
    else m_ms->hide();
×
665

666
    if (mask & Infinite) m_infiniteCheck->show();
×
667
    else m_infiniteCheck->hide();
×
668

669
    m_visibilityMask = mask;
×
670
}
×
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

© 2025 Coveralls, Inc