• 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/virtualconsole/vcspeeddial.cpp
1
/*
2
  Q Light Controller Plus
3
  vcspeeddial.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

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

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

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

21
#include <QXmlStreamReader>
22
#include <QXmlStreamWriter>
23
#include <QSettings>
24
#include <QLayout>
25
#include <QTimer>
26
#include <QDebug>
27

28
#include "vcspeeddialproperties.h"
29
#include "vcspeeddialfunction.h"
30
#include "vcpropertieseditor.h"
31
#include "vcspeeddialpreset.h"
32
#include "vcspeeddial.h"
33
#include "flowlayout.h"
34
#include "speeddial.h"
35
#include "qlcmacros.h"
36
#include "function.h"
37
#include "qlcfile.h"
38

39
#define UPDATE_TIMEOUT 50
40

41
const quint8 VCSpeedDial::absoluteInputSourceId = 0;
42
const quint8 VCSpeedDial::tapInputSourceId = 1;
43
const quint8 VCSpeedDial::multInputSourceId = 2;
44
const quint8 VCSpeedDial::divInputSourceId = 3;
45
const quint8 VCSpeedDial::multDivResetInputSourceId = 4;
46
const quint8 VCSpeedDial::applyInputSourceId = 5;
47
const QSize VCSpeedDial::defaultSize(QSize(200, 175));
48

49
static const QString presetBtnSS =
50
    "QPushButton { background-color: %1; height: 32px; border: 2px solid #6A6A6A; border-radius: 5px; }"
51
    "QPushButton:pressed { border: 2px solid #0000FF; }"
52
    "QPushButton:disabled { border: 2px solid #BBBBBB; color: #8f8f8f }";
53

54
static const QString dialSS =
55
    "QGroupBox { background-color: %1; border: 1px solid gray; border-radius: 5px; margin-top: 0; font-size: %2pt; }"
56
    "QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; padding: 0px 5px;"
57
    "                   background-color: transparent; color: %3; }";
58

59
/****************************************************************************
60
 * Initialization
61
 ****************************************************************************/
62

63
VCSpeedDial::VCSpeedDial(QWidget* parent, Doc* doc)
×
64
    : VCWidget(parent, doc)
65
    , m_currentFactor(1)
×
66
    , m_resetFactorOnDialChange(false)
×
67
    , m_absoluteValueMin(0)
×
68
    , m_absoluteValueMax(1000 * 10)
×
69
{
70
    setFrameStyle(KVCFrameStyleSunken);
×
71

72
    QVBoxLayout* vBox = new QVBoxLayout(this);
×
73
    vBox->setContentsMargins(0, 0, 0, 0);
×
74

75
    QHBoxLayout* speedDialHBox = new QHBoxLayout();
×
76
    vBox->addLayout(speedDialHBox);
×
77

78
    m_dial = new SpeedDial(this);
×
79
    speedDialHBox->addWidget(m_dial);
×
80
    connect(m_dial, SIGNAL(valueChanged(int)), this, SLOT(slotDialValueChanged()));
×
81
    connect(m_dial, SIGNAL(tapped()), this, SLOT(slotDialTapped()));
×
82
    connect(m_dial, SIGNAL(tapTimeout()), this, SLOT(slotTapTimeout()));
×
83

84
    m_factoredValue = m_dial->value();
×
85

86
    setType(VCWidget::SpeedDialWidget);
×
87
    setCaption(tr("Duration"));
×
88

89
    QSettings settings;
×
90
    QVariant var = settings.value(SETTINGS_SPEEDDIAL_SIZE);
×
91
    if (var.isValid() == true)
×
92
        resize(var.toSize());
×
93
    else
94
        resize(VCSpeedDial::defaultSize);
×
95

96
    var = settings.value(SETTINGS_SPEEDDIAL_VALUE);
×
97
    if (var.isValid() == true)
×
98
        m_dial->setValue(var.toUInt());
×
99

100
    // Multiplier, factor, divider and reset box
101
    QHBoxLayout* multFactorDivHBox = new QHBoxLayout();
×
102

103
    m_divButton = new QToolButton();
×
104
    m_divButton->setIconSize(QSize(32, 32));
×
105
    m_divButton->setIcon(QIcon(":/back.png"));
×
106
    m_divButton->setToolTip(tr("Divide the current time by 2"));
×
107
    connect(m_divButton, SIGNAL(clicked()),
×
108
            this, SLOT(slotDiv()));
109
    multFactorDivHBox->addWidget(m_divButton, Qt::AlignVCenter | Qt::AlignLeft);
×
110

111
    QVBoxLayout* labelsVboxBox = new QVBoxLayout();
×
112

113
    m_multDivLabel = new QLabel();
×
114
    m_multDivLabel->setAlignment(Qt::AlignCenter);
×
115
    m_multDivLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
×
116
    labelsVboxBox->addWidget(m_multDivLabel, Qt::AlignVCenter | Qt::AlignLeft);
×
117

118
    m_multDivResultLabel = new QLabel();
×
119
    m_multDivResultLabel->setAlignment(Qt::AlignCenter);
×
120
    m_multDivResultLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
×
121
    m_multDivResultLabel->setBackgroundRole(QPalette::BrightText);
×
122
    labelsVboxBox->addWidget(m_multDivResultLabel);
×
123

124
    multFactorDivHBox->addLayout(labelsVboxBox);
×
125

126
    m_multButton = new QToolButton();
×
127
    m_multButton->setIconSize(QSize(32, 32));
×
128
    m_multButton->setIcon(QIcon(":/forward.png"));
×
129
    m_multButton->setToolTip(tr("Multiply the current time by 2"));
×
130
    connect(m_multButton, SIGNAL(clicked()),
×
131
            this, SLOT(slotMult()));
132
    multFactorDivHBox->addWidget(m_multButton, Qt::AlignVCenter | Qt::AlignLeft);
×
133

134
    m_multDivResetButton = new QToolButton();
×
135
    m_multDivResetButton->setIconSize(QSize(32, 32));
×
136
    m_multDivResetButton->setIcon(QIcon(":/fileclose.png"));
×
137
    m_multDivResetButton->setToolTip(tr("Reset the current factor to 1x"));
×
138
    connect(m_multDivResetButton, SIGNAL(clicked()),
×
139
            this, SLOT(slotMultDivReset()));
140
    multFactorDivHBox->addWidget(m_multDivResetButton);
×
141

142
    vBox->addLayout(multFactorDivHBox);
×
143

144
    // Update labels
145
    slotMultDivChanged();
×
146

147
    // Apply button
148
    m_applyButton = new QPushButton();
×
149
    m_applyButton->setStyleSheet(presetBtnSS.arg("#DDDDDD"));
×
150
    m_applyButton->setText(tr("Apply"));
×
151
    m_applyButton->setToolTip(tr("Send the current value to the function now"));
×
152
    connect(m_applyButton, SIGNAL(clicked()),
×
153
            this, SLOT(slotFactoredValueChanged()));
154
    vBox->addWidget(m_applyButton);
×
155

156
    // Presets
157
    m_presetsLayout = new FlowLayout(3);
×
158
    vBox->addLayout(m_presetsLayout);
×
159

160
    // Don't show Infinite button: it's handled by presets
161
    setVisibilityMask(SpeedDial::defaultVisibilityMask() & ~SpeedDial::Infinite);
×
162

163
    /* Update timer */
164
    m_updateTimer = new QTimer(this);
×
165
    connect(m_updateTimer, SIGNAL(timeout()),
×
166
            this, SLOT(slotUpdate()));
167
    m_updateTimer->setSingleShot(true);
×
168

169
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
170
    // Background color has been moved to Base
171
    setBackgroundColor(palette().color(QPalette::Base));
172
#endif
173
    m_foregroundColor = palette().color(QPalette::WindowText);
×
174
    m_dial->setStyleSheet(dialSS.arg(palette().color(QPalette::Window).name())
×
175
                              .arg(font().pointSize())
×
176
                              .arg(m_foregroundColor.name()));
×
177

178
    slotModeChanged(m_doc->mode());
×
179
    setLiveEdit(m_liveEdit);
×
180
}
×
181

182
VCSpeedDial::~VCSpeedDial()
×
183
{
184
    foreach (VCSpeedDialPreset* preset, m_presets)
×
185
    {
186
        delete preset;
×
187
    }
188
}
×
189

190
void VCSpeedDial::enableWidgetUI(bool enable)
×
191
{
192
    m_dial->setEnabled(enable);
×
193

194
    // Mult and div
195
    m_multButton->setEnabled(enable);
×
196
    m_divButton->setEnabled(enable);
×
197
    m_multDivResetButton->setEnabled(enable);
×
198

199
    // Apply
200
    m_applyButton->setEnabled(enable);
×
201

202
    // Presets enable
203
    foreach (QWidget *presetWidget, m_presets.keys())
×
204
        presetWidget->setEnabled(enable);
×
205

206
    // Presets: update state
207
    if (enable)
×
208
        slotUpdate();
×
209
}
×
210

211
/*****************************************************************************
212
 * Clipboard
213
 *****************************************************************************/
214

215
VCWidget* VCSpeedDial::createCopy(VCWidget* parent)
×
216
{
217
    Q_ASSERT(parent != NULL);
218

219
    VCSpeedDial* dial = new VCSpeedDial(parent, m_doc);
×
220
    if (dial->copyFrom(this) == false)
×
221
    {
222
        delete dial;
×
223
        dial = NULL;
224
    }
225

226
    return dial;
×
227
}
228

229
bool VCSpeedDial::copyFrom(const VCWidget* widget)
×
230
{
231
    const VCSpeedDial* dial = qobject_cast<const VCSpeedDial*> (widget);
232
    if (dial == NULL)
×
233
        return false;
234

235
    setFunctions(dial->functions());
×
236
    setAbsoluteValueRange(dial->absoluteValueMin(), dial->absoluteValueMax());
×
237
    setVisibilityMask(dial->visibilityMask());
×
238
    setResetFactorOnDialChange(dial->resetFactorOnDialChange());
×
239

240
    setTapKeySequence(dial->tapKeySequence());
×
241
    setMultKeySequence(dial->multKeySequence());
×
242
    setDivKeySequence(dial->divKeySequence());
×
243
    setMultDivResetKeySequence(dial->multDivResetKeySequence());
×
244
    setApplyKeySequence(dial->applyKeySequence());
×
245

246
    resetPresets();
×
247
    foreach (VCSpeedDialPreset const* preset, dial->presets())
×
248
    {
249
        addPreset(*preset);
×
250
    }
251

252
    /* Copy common stuff */
253
    return VCWidget::copyFrom(widget);
×
254
}
255

256
void VCSpeedDial::setFont(const QFont &font)
×
257
{
258
    VCWidget::setFont(font);
×
259
    m_dial->setStyleSheet(dialSS.arg(palette().color(QPalette::Window).name())
×
260
                              .arg(font.pointSize())
×
261
                              .arg(m_foregroundColor.name()));
×
262
}
×
263

264
/*********************************************************************
265
 * Background/Foreground color
266
 *********************************************************************/
267

268
void VCSpeedDial::setBackgroundColor(const QColor &color)
×
269
{
270
    VCWidget::setBackgroundColor(color);
×
271
    m_dial->setStyleSheet(dialSS.arg(palette().color(QPalette::Window).name())
×
272
                              .arg(font().pointSize())
×
273
                              .arg(m_foregroundColor.name()));
×
274
}
×
275

276
void VCSpeedDial::setForegroundColor(const QColor &color)
×
277
{
278
    m_foregroundColor = color;
×
279
    m_hasCustomForegroundColor = true;
×
280

281
    m_dial->setStyleSheet(dialSS.arg(palette().color(QPalette::Window).name())
×
282
                              .arg(font().pointSize())
×
283
                              .arg(color.name()));
×
284
    VCWidget::setForegroundColor(color);
×
285
}
×
286

287
QColor VCSpeedDial::foregroundColor() const
×
288
{
289
    return m_foregroundColor;
×
290
}
291

292
/*****************************************************************************
293
 * Properties
294
 *****************************************************************************/
295

296
void VCSpeedDial::editProperties()
×
297
{
298
    VCSpeedDialProperties sdp(this, m_doc);
×
299
    sdp.exec();
×
300
}
×
301

302
/*****************************************************************************
303
 * Caption
304
 *****************************************************************************/
305

306
void VCSpeedDial::setCaption(const QString& text)
×
307
{
308
    VCWidget::setCaption(text);
×
309

310
    Q_ASSERT(m_dial != NULL);
311
    m_dial->setTitle(text);
×
312
}
×
313

314
/*****************************************************************************
315
 * QLC Mode
316
 *****************************************************************************/
317

318
void VCSpeedDial::slotModeChanged(Doc::Mode mode)
×
319
{
320
    if (mode == Doc::Operate && isDisabled() == false)
×
321
    {
322
        enableWidgetUI(true);
×
323
        updateFeedback();
×
324
    }
325
    else
326
    {
327
        m_dial->stopTimers();
×
328
        enableWidgetUI(false);
×
329
    }
330
    VCWidget::slotModeChanged(mode);
×
331
}
×
332

333
/****************************************************************************
334
 * Functions
335
 ****************************************************************************/
336

337
void VCSpeedDial::setFunctions(const QList <VCSpeedDialFunction> & functions)
×
338
{
339
    m_functions = functions;
×
340
}
×
341

342
QList <VCSpeedDialFunction> VCSpeedDial::functions() const
×
343
{
344
    return m_functions;
×
345
}
346

347
void VCSpeedDial::tap()
×
348
{
349
    m_dial->tap();
×
350
}
×
351

352
void VCSpeedDial::slotDialValueChanged()
×
353
{
354
    // The (m_currentFactor != 1) test ensures that we don't call
355
    // slotMultDivChanged() 2 times
356
    if (m_resetFactorOnDialChange && m_currentFactor != 1)
×
357
        slotMultDivReset();
×
358
    else
359
        slotMultDivChanged();
×
360

361
    m_updateTimer->start(UPDATE_TIMEOUT);
×
362
}
×
363

364
void VCSpeedDial::slotDialTapped()
×
365
{
366
    foreach (const VCSpeedDialFunction &speeddialfunction, m_functions)
×
367
    {
368
        Function* function = m_doc->function(speeddialfunction.functionId);
×
369
        if (function != NULL)
×
370
        {
371
            if (speeddialfunction.durationMultiplier != VCSpeedDialFunction::None)
×
372
                function->tap();
×
373
        }
374
    }
375
}
×
376

377
void VCSpeedDial::slotTapTimeout()
×
378
{
379
    updateFeedback();
×
380
}
×
381

382
void VCSpeedDial::slotUpdate()
×
383
{
384
    int currentValue = m_dial->value();
×
385

386
    for (QHash<QWidget*, VCSpeedDialPreset*>::iterator it = m_presets.begin();
×
387
            it != m_presets.end(); ++it)
×
388
    {
389
        QWidget* widget = it.key();
×
390
        VCSpeedDialPreset* preset = it.value();
×
391

392
        QPushButton* button = reinterpret_cast<QPushButton*>(widget);
393
        button->setDown(preset->m_value == currentValue);
×
394
    }
395
    updateFeedback();
×
396
}
×
397

398
/*********************************************************************
399
 * Presets
400
 *********************************************************************/
401

402
void VCSpeedDial::addPreset(VCSpeedDialPreset const& preset)
×
403
{
404
    QWidget *presetWidget = NULL;
×
405

406
    {
407
        QPushButton *presetButton = new QPushButton(this);
×
408
        presetWidget = presetButton;
×
409
        presetButton->setStyleSheet(presetBtnSS.arg("#BBBBBB"));
×
410
        presetButton->setMinimumWidth(36);
×
411
        presetButton->setMaximumWidth(80);
×
412
        presetButton->setFocusPolicy(Qt::TabFocus);
×
413
        QString btnLabel = preset.m_name;
414
        presetButton->setToolTip(btnLabel);
×
415
        presetButton->setText(fontMetrics().elidedText(btnLabel, Qt::ElideRight, 72));
×
416
    }
×
417

418
    Q_ASSERT(presetWidget != NULL);
419

420
    connect(reinterpret_cast<QPushButton*>(presetWidget), SIGNAL(clicked()),
×
421
            this, SLOT(slotPresetClicked()));
422

423
    if (mode() == Doc::Design)
×
424
        presetWidget->setEnabled(false);
×
425

426
    m_presets[presetWidget] = new VCSpeedDialPreset(preset);
×
427
    m_presetsLayout->addWidget(presetWidget);
×
428

429
    if (m_presets[presetWidget]->m_inputSource != NULL)
×
430
    {
431
        setInputSource(m_presets[presetWidget]->m_inputSource,
×
432
                       m_presets[presetWidget]->m_id);
×
433
    }
434

435
    m_updateTimer->start(UPDATE_TIMEOUT);
×
436
}
×
437

438
void VCSpeedDial::resetPresets()
×
439
{
440
    for (QHash<QWidget*, VCSpeedDialPreset*>::iterator it = m_presets.begin();
×
441
            it != m_presets.end(); ++it)
×
442
    {
443
        QWidget* widget = it.key();
×
444
        m_presetsLayout->removeWidget(widget);
×
445
        delete widget;
×
446

447
        VCSpeedDialPreset* preset = it.value();
×
448
        if (!preset->m_inputSource.isNull())
×
449
            setInputSource(QSharedPointer<QLCInputSource>(), preset->m_id);
×
450
        delete preset;
×
451
    }
452
    m_presets.clear();
×
453
}
×
454

455
QList<VCSpeedDialPreset*> VCSpeedDial::presets() const
×
456
{
457
    QList<VCSpeedDialPreset*> presetsList = m_presets.values();
×
458
    std::sort(presetsList.begin(), presetsList.end(), VCSpeedDialPreset::compare);
×
459
    return presetsList;
×
460
}
×
461

462
void VCSpeedDial::slotPresetClicked()
×
463
{
464
    QPushButton *btn = qobject_cast<QPushButton*>(sender());
×
465
    VCSpeedDialPreset *preset = m_presets[btn];
×
466

467
    Q_ASSERT(preset != NULL);
468

469
    {
470
        // Special case: infinite buttons should act as checkboxes
471
        // so the previous value can be restore when clicking 2 times on them
472
        if (preset->m_value == (int)Function::infiniteSpeed())
×
473
        {
474
            m_dial->toggleInfinite();
×
475
        }
476
        else // Normal case
477
        {
478
            m_dial->setValue(preset->m_value, true);
×
479
        }
480
    }
481
}
×
482

483
void VCSpeedDial::slotMult()
×
484
{
485
    if (m_currentFactor == -2)
×
486
    {
487
        m_currentFactor = 1;
×
488
        slotMultDivChanged();
×
489
    }
490
    else if (m_currentFactor > 0)
×
491
    {
492
        if (m_currentFactor < 2048)
×
493
        {
494
            m_currentFactor *= 2;
×
495
            slotMultDivChanged();
×
496
        }
497
    }
498
    else
499
    {
500
        m_currentFactor /= 2;
×
501
        slotMultDivChanged();
×
502
    }
503
}
×
504

505
void VCSpeedDial::slotDiv()
×
506
{
507
    if (m_currentFactor == 1)
×
508
    {
509
        m_currentFactor = -2;
×
510
        slotMultDivChanged();
×
511
    }
512
    else if (m_currentFactor > 0)
×
513
    {
514
        m_currentFactor /= 2;
×
515
        slotMultDivChanged();
×
516
    }
517
    else
518
    {
519
        if (m_currentFactor > -2048)
×
520
        {
521
            m_currentFactor *= 2;
×
522
            slotMultDivChanged();
×
523
        }
524
    }
525
}
×
526

527
void VCSpeedDial::slotMultDivReset()
×
528
{
529
    if (m_currentFactor != 1)
×
530
    {
531
        m_currentFactor = 1;
×
532
        slotMultDivChanged();
×
533
    }
534
}
×
535

536
void VCSpeedDial::slotMultDivChanged()
×
537
{
538
    if (m_currentFactor > 0)
×
539
    {
540
        m_factoredValue = m_dial->value() * m_currentFactor;
×
541
        m_multDivLabel->setText(QString("%1x").arg(m_currentFactor));
×
542
    }
543
    else
544
    {
545
        m_factoredValue = m_dial->value() / qAbs(m_currentFactor);
×
546
        m_multDivLabel->setText(QString("1/%1x").arg(qAbs(m_currentFactor)));
×
547
    }
548
    m_multDivResultLabel->setText("(" + Function::speedToString(m_factoredValue) + ")");
×
549

550
    slotFactoredValueChanged();
×
551
}
×
552

553
void VCSpeedDial::slotFactoredValueChanged()
×
554
{
555
    const QVector<quint32> multipliers = VCSpeedDialFunction::speedMultiplierValuesTimes1000();
×
556

557
    int ms = m_factoredValue;
×
558

559
    foreach (const VCSpeedDialFunction &speeddialfunction, m_functions)
×
560
    {
561
        Function* function = m_doc->function(speeddialfunction.functionId);
×
562
        if (function != NULL)
×
563
        {
564
            if (speeddialfunction.fadeInMultiplier != VCSpeedDialFunction::None)
×
565
            {
566
                if ((uint)ms != Function::infiniteSpeed())
×
567
                    function->setFadeInSpeed(ms * ((float)multipliers[speeddialfunction.fadeInMultiplier] / 1000.0));
×
568
                else
569
                    function->setFadeInSpeed(ms);
×
570
            }
571
            if (speeddialfunction.fadeOutMultiplier != VCSpeedDialFunction::None)
×
572
            {
573
                if ((uint)ms != Function::infiniteSpeed())
×
574
                    function->setFadeOutSpeed(ms * ((float)multipliers[speeddialfunction.fadeOutMultiplier] / 1000.0));
×
575
                else
576
                    function->setFadeOutSpeed(ms);
×
577
            }
578
            if (speeddialfunction.durationMultiplier != VCSpeedDialFunction::None)
×
579
            {
580
                if ((uint)ms != Function::infiniteSpeed())
×
581
                    function->setDuration(ms * ((float)multipliers[speeddialfunction.durationMultiplier] / 1000.0));
×
582
                else
583
                    function->setDuration(ms);
×
584
            }
585
        }
586
    }
587
}
×
588

589

590
void VCSpeedDial::setResetFactorOnDialChange(bool value)
×
591
{
592
    m_resetFactorOnDialChange = value;
×
593
}
×
594

595
bool VCSpeedDial::resetFactorOnDialChange() const
×
596
{
597
    return m_resetFactorOnDialChange;
×
598
}
599

600
/*****************************************************************************
601
 * External input
602
 *****************************************************************************/
603

604
void VCSpeedDial::updateFeedback()
×
605
{
606
    // Feedback to absolute input source
607
    int fbv = (int)SCALE(float(m_dial->value()), float(m_absoluteValueMin),
×
608
                     float(m_absoluteValueMax), float(0), float(UCHAR_MAX));
609

610
    sendFeedback(fbv, absoluteInputSourceId);
×
611

612
    // Feedback to tap button
613
    sendFeedback(m_dial->isTapTick() ? 255 : 0, tapInputSourceId);
×
614

615
    // Feedback to preset buttons
616
    for (QHash<QWidget*, VCSpeedDialPreset*>::iterator it = m_presets.begin();
×
617
            it != m_presets.end(); ++it)
×
618
    {
619
        VCSpeedDialPreset* preset = it.value();
×
620
        if (preset->m_inputSource != NULL)
×
621
        {
622
            QPushButton* button = reinterpret_cast<QPushButton*>(it.key());
×
623
            if (preset->m_inputSource.isNull() == false)
624
                sendFeedback(button->isDown() ?
×
625
                             preset->m_inputSource->feedbackValue(QLCInputFeedback::UpperValue) :
×
626
                             preset->m_inputSource->feedbackValue(QLCInputFeedback::LowerValue),
×
627
                             preset->m_inputSource);
628
        }
629
    }
630
}
×
631

632
void VCSpeedDial::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
633
{
634
    /* Don't let input data through in design mode or if disabled */
635
    if (acceptsInput() == false)
×
636
        return;
637

638
    quint32 pagedCh = (page() << 16) | channel;
×
639

640
    if (checkInputSource(universe, pagedCh, value, sender(), tapInputSourceId))
×
641
    {
642
        if (value != 0)
×
643
            m_dial->tap();
×
644
    }
645
    else if (checkInputSource(universe, pagedCh, value, sender(), absoluteInputSourceId))
×
646
    {
647
        int ms = static_cast<int> (SCALE(qreal(value), qreal(0), qreal(255),
×
648
                                         qreal(absoluteValueMin()),
649
                                         qreal(absoluteValueMax())));
×
650
        m_dial->setValue(ms, true);
×
651
    }
652
    else if (checkInputSource(universe, pagedCh, value, sender(), multInputSourceId))
×
653
    {
654
        if (value != 0)
×
655
            slotMult();
×
656
    }
657
    else if (checkInputSource(universe, pagedCh, value, sender(), divInputSourceId))
×
658
    {
659
        if (value != 0)
×
660
            slotDiv();
×
661
    }
662
    else if (checkInputSource(universe, pagedCh, value, sender(), multDivResetInputSourceId))
×
663
    {
664
        if (value != 0)
×
665
            slotMultDivReset();
×
666
    }
667
    else if (checkInputSource(universe, pagedCh, value, sender(), applyInputSourceId))
×
668
    {
669
        if (value != 0)
×
670
            slotFactoredValueChanged();
×
671
    }
672
    else
673
    {
674
        for (QHash<QWidget*, VCSpeedDialPreset*>::iterator it = m_presets.begin();
×
675
                it != m_presets.end(); ++it)
×
676
        {
677
            VCSpeedDialPreset *preset = it.value();
×
678
            if (preset->m_inputSource != NULL &&
×
679
                    preset->m_inputSource->universe() == universe &&
×
680
                    preset->m_inputSource->channel() == pagedCh)
×
681
            {
682
                {
683
                    QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
684
                    button->click();
×
685
                }
686
            }
687
        }
688
    }
689
}
690

691
/*********************************************************************
692
 * Tap key sequence handler
693
 *********************************************************************/
694

695
void VCSpeedDial::setTapKeySequence(const QKeySequence& keySequence)
×
696
{
697
    m_tapKeySequence = QKeySequence(keySequence);
×
698
}
×
699

700
QKeySequence VCSpeedDial::tapKeySequence() const
×
701
{
702
    return m_tapKeySequence;
×
703
}
704

705
void VCSpeedDial::setMultKeySequence(const QKeySequence& keySequence)
×
706
{
707
    m_multKeySequence = QKeySequence(keySequence);
×
708
}
×
709

710
QKeySequence VCSpeedDial::multKeySequence() const
×
711
{
712
    return m_multKeySequence;
×
713
}
714

715
void VCSpeedDial::setDivKeySequence(const QKeySequence& keySequence)
×
716
{
717
    m_divKeySequence = QKeySequence(keySequence);
×
718
}
×
719

720
QKeySequence VCSpeedDial::divKeySequence() const
×
721
{
722
    return m_divKeySequence;
×
723
}
724

725
void VCSpeedDial::setMultDivResetKeySequence(const QKeySequence& keySequence)
×
726
{
727
    m_multDivResetKeySequence = QKeySequence(keySequence);
×
728
}
×
729

730
QKeySequence VCSpeedDial::multDivResetKeySequence() const
×
731
{
732
    return m_multDivResetKeySequence;
×
733
}
734

735
void VCSpeedDial::setApplyKeySequence(const QKeySequence& keySequence)
×
736
{
737
    m_applyKeySequence = QKeySequence(keySequence);
×
738
}
×
739

740
QKeySequence VCSpeedDial::applyKeySequence() const
×
741
{
742
    return m_applyKeySequence;
×
743
}
744

745
void VCSpeedDial::slotKeyPressed(const QKeySequence& keySequence)
×
746
{
747
    if (acceptsInput() == false)
×
748
        return;
749

750
    if (m_tapKeySequence == keySequence)
×
751
        m_dial->tap();
×
752

753
    if (m_multKeySequence == keySequence)
×
754
        slotMult();
×
755
    if (m_divKeySequence == keySequence)
×
756
        slotDiv();
×
757
    if (m_multDivResetKeySequence == keySequence)
×
758
        slotMultDivReset();
×
759
    if (m_applyKeySequence == keySequence)
×
760
        slotFactoredValueChanged();
×
761

762
    for (QHash<QWidget*, VCSpeedDialPreset*>::iterator it = m_presets.begin();
×
763
            it != m_presets.end(); ++it)
×
764
    {
765
        VCSpeedDialPreset *preset = it.value();
×
766
        if (preset->m_keySequence == keySequence)
×
767
        {
768
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
769
            button->click();
×
770
        }
771
    }
772
}
773

774

775
/****************************************************************************
776
 * Absolute value range
777
 ****************************************************************************/
778

779
void VCSpeedDial::setAbsoluteValueRange(uint min, uint max)
×
780
{
781
    m_absoluteValueMin = min;
×
782
    m_absoluteValueMax = max;
×
783
}
×
784

785
uint VCSpeedDial::absoluteValueMin() const
×
786
{
787
    return m_absoluteValueMin;
×
788
}
789

790
uint VCSpeedDial::absoluteValueMax() const
×
791
{
792
    return m_absoluteValueMax;
×
793
}
794

795
quint32 VCSpeedDial::visibilityMask() const
×
796
{
797
    return m_visibilityMask;
×
798
}
799

800
void VCSpeedDial::setVisibilityMask(quint32 mask)
×
801
{
802
    if (m_dial != NULL)
×
803
        m_dial->setVisibilityMask(mask);
×
804

805
    if (mask & MultDiv)
×
806
    {
807
        m_multButton->show();
×
808
        m_multDivLabel->show();
×
809
        m_divButton->show();
×
810
        m_multDivResetButton->show();
×
811
        m_multDivResultLabel->show();
×
812
    }
813
    else
814
    {
815
        m_multButton->hide();
×
816
        m_multDivLabel->hide();
×
817
        m_divButton->hide();
×
818
        m_multDivResetButton->hide();
×
819
        m_multDivResultLabel->hide();
×
820
    }
821

822
    if (mask & Apply)
×
823
        m_applyButton->show();
×
824
    else
825
        m_applyButton->hide();
×
826

827
    m_visibilityMask = mask;
×
828
}
×
829

830
/*****************************************************************************
831
 * Load & Save
832
 *****************************************************************************/
833

834
static QSharedPointer<VCSpeedDialPreset> createInfinitePreset()
×
835
{
836
    QSharedPointer<VCSpeedDialPreset> infinitePreset(new VCSpeedDialPreset(16));
×
837
    infinitePreset->m_value = Function::infiniteSpeed();
×
838
    infinitePreset->m_name = Function::speedToString(Function::infiniteSpeed());
×
839
    return infinitePreset;
×
840
}
841

842
bool VCSpeedDial::loadXML(QXmlStreamReader &root)
×
843
{
844
    if (root.name() != KXMLQLCVCSpeedDial)
×
845
    {
846
        qWarning() << Q_FUNC_INFO << "SpeedDial node not found";
×
847
        return false;
×
848
    }
849

850
    /* Widget commons */
851
    loadXMLCommon(root);
×
852

853
    // Compatibility with old workspace files:
854
    // Get old style speedtype selection
855
    VCSpeedDialFunction::SpeedMultiplier defaultFadeInMultiplier = VCSpeedDialFunction::None;
856
    VCSpeedDialFunction::SpeedMultiplier defaultFadeOutMultiplier = VCSpeedDialFunction::None;
857
    VCSpeedDialFunction::SpeedMultiplier defaultDurationMultiplier = VCSpeedDialFunction::One;
858
    if (root.attributes().hasAttribute(KXMLQLCVCSpeedDialSpeedTypes))
×
859
    {
860
        SpeedTypes speedTypes = SpeedTypes(root.attributes().value(KXMLQLCVCSpeedDialSpeedTypes).toString().toInt());
×
861
        defaultFadeInMultiplier = (speedTypes & FadeIn) ? VCSpeedDialFunction::One : VCSpeedDialFunction::None;
×
862
        defaultFadeOutMultiplier = (speedTypes & FadeOut) ? VCSpeedDialFunction::One : VCSpeedDialFunction::None;
×
863
        defaultDurationMultiplier = (speedTypes & Duration) ? VCSpeedDialFunction::One : VCSpeedDialFunction::None;
×
864
    }
865

866
    // Sorted list for new presets
867
    QList<VCSpeedDialPreset> newPresets;
868
    // legacy: transform the infinite checkbox into an infinite preset
869
    QSharedPointer<VCSpeedDialPreset> infinitePreset(NULL);
870

871
    /* Children */
872
    while (root.readNextStartElement())
×
873
    {
874
        //qDebug() << "VC Speed Dial tag:" << root.name();
875
        if (root.name() == KXMLQLCFunction)
×
876
        {
877
            // Function
878
            VCSpeedDialFunction speeddialfunction;
×
879
            if (speeddialfunction.loadXML(root, defaultFadeInMultiplier,
×
880
                                          defaultFadeOutMultiplier,
881
                                          defaultDurationMultiplier))
882
            {
883
                m_functions.append(speeddialfunction);
×
884
            }
885
        }
886
        else if (root.name() == KXMLQLCWindowState)
×
887
        {
888
            int x = 0, y = 0, w = 0, h = 0;
×
889
            bool visible = true;
×
890
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
891
            setGeometry(x, y, w, h);
×
892
        }
893
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
894
        {
895
            loadXMLAppearance(root);
×
896
        }
897
        else if (root.name() == KXMLQLCVCSpeedDialAbsoluteValue)
×
898
        {
899
            // Value range
900
            QXmlStreamAttributes vAttrs = root.attributes();
×
901
            if (vAttrs.hasAttribute(KXMLQLCVCSpeedDialAbsoluteValueMin) &&
×
902
                vAttrs.hasAttribute(KXMLQLCVCSpeedDialAbsoluteValueMax))
×
903
            {
904
                uint min = vAttrs.value(KXMLQLCVCSpeedDialAbsoluteValueMin).toString().toUInt();
×
905
                uint max = vAttrs.value(KXMLQLCVCSpeedDialAbsoluteValueMax).toString().toUInt();
×
906
                setAbsoluteValueRange(min, max);
×
907
            }
908
            loadXMLSources(root, absoluteInputSourceId);
×
909
        }
910
        else if (root.name() == KXMLQLCVCSpeedDialTap)
×
911
        {
912
            loadXMLSources(root, tapInputSourceId);
×
913
        }
914
        else if (root.name() == KXMLQLCVCSpeedDialResetFactorOnDialChange)
×
915
        {
916
            // Reset factor on dial change
917
            setResetFactorOnDialChange(root.readElementText() == KXMLQLCTrue);
×
918
        }
919
        else if (root.name() == KXMLQLCVCSpeedDialMult)
×
920
        {
921
            loadXMLSources(root, multInputSourceId);
×
922
        }
923
        else if (root.name() == KXMLQLCVCSpeedDialDiv)
×
924
        {
925
            loadXMLSources(root, divInputSourceId);
×
926
        }
927
        else if (root.name() == KXMLQLCVCSpeedDialMultDivReset)
×
928
        {
929
            loadXMLSources(root, multDivResetInputSourceId);
×
930
        }
931
        else if (root.name() == KXMLQLCVCSpeedDialApply)
×
932
        {
933
            loadXMLSources(root, applyInputSourceId);
×
934
        }
935
        else if (root.name() == KXMLQLCVCSpeedDialTapKey)
×
936
        {
937
            setTapKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
938
        }
939
        else if (root.name() == KXMLQLCVCSpeedDialMultKey)
×
940
        {
941
            setMultKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
942
        }
943
        else if (root.name() == KXMLQLCVCSpeedDialDivKey)
×
944
        {
945
            setDivKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
946
        }
947
        else if (root.name() == KXMLQLCVCSpeedDialMultDivResetKey)
×
948
        {
949
            setMultDivResetKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
950
        }
951
        else if (root.name() == KXMLQLCVCSpeedDialApplyKey)
×
952
        {
953
            setApplyKeySequence(stripKeySequence(QKeySequence(root.readElementText())));
×
954
        }
955
        else if (root.name() == KXMLQLCVCSpeedDialInfinite)
×
956
        {
957
            // Legacy: infinite checkbox input
958
            if (!infinitePreset)
×
959
                infinitePreset = createInfinitePreset();
×
960

961
            loadXMLInfiniteLegacy(root, infinitePreset);
×
962
        }
963
        else if (root.name() == KXMLQLCVCSpeedDialInfiniteKey)
×
964
        {
965
            // Legacy: infinite checkbox key sequence
966
            if (!infinitePreset)
×
967
                infinitePreset = createInfinitePreset();
×
968

969
            infinitePreset->m_keySequence = stripKeySequence(QKeySequence(root.readElementText()));
×
970
        }
971
        else if (root.name() == KXMLQLCVCSpeedDialPreset)
×
972
        {
973
            VCSpeedDialPreset preset(0xff);
×
974
            if (preset.loadXML(root))
×
975
                newPresets.insert(std::lower_bound(newPresets.begin(), newPresets.end(), preset), preset);
×
976
        }
×
977
        else if (root.name() == KXMLQLCVCSpeedDialVisibilityMask)
×
978
        {
979
            quint32 mask = root.readElementText().toUInt();
×
980

981
            // legacy: infinite checkbox
982
            if (mask & SpeedDial::Infinite)
×
983
            {
984
                mask &= ~SpeedDial::Infinite;
×
985
                if (!infinitePreset)
×
986
                    infinitePreset = createInfinitePreset();
×
987
            }
988

989
            setVisibilityMask(mask);
×
990
        }
991
        else if (root.name() == KXMLQLCVCSpeedDialTime)
×
992
        {
993
            m_dial->setValue(root.readElementText().toUInt());
×
994
        }
995
        else
996
        {
997
            qWarning() << Q_FUNC_INFO << "Unknown speed dial tag:" << root.name().toString();
×
998
            root.skipCurrentElement();
×
999
        }
1000
    }
1001

1002
    if (infinitePreset && newPresets.size() > 0)
×
1003
    {
1004
        qWarning() << Q_FUNC_INFO << "Can't have an infinite checkbox + presets";
×
1005
        return false;
×
1006
    }
1007

1008
    if (infinitePreset)
×
1009
        addPreset(*infinitePreset);
×
1010
    else
1011
    {
1012
        foreach (VCSpeedDialPreset const& preset, newPresets)
×
1013
            addPreset(preset);
×
1014
    }
1015

1016
    return true;
1017
}
×
1018

1019
bool VCSpeedDial::loadXMLInfiniteLegacy(QXmlStreamReader &root, QSharedPointer<VCSpeedDialPreset> preset)
×
1020
{
1021
    while (root.readNextStartElement())
×
1022
    {
1023
        if (root.name() == KXMLQLCVCWidgetInput)
×
1024
        {
1025
            quint32 uni = QLCInputSource::invalidUniverse;
×
1026
            quint32 ch = QLCInputSource::invalidChannel;
×
1027
            if (loadXMLInput(root, &uni, &ch) == true)
×
1028
            {
1029
                preset->m_inputSource = QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch));
×
1030
            }
1031
        }
1032
        else
1033
        {
1034
            qWarning() << Q_FUNC_INFO << "Unknown Frame Source tag" << root.name().toString();
×
1035
            root.skipCurrentElement();
×
1036
        }
1037
    }
1038
    return true;
×
1039
}
1040

1041
bool VCSpeedDial::saveXML(QXmlStreamWriter *doc)
×
1042
{
1043
    Q_ASSERT(doc != NULL);
1044

1045
    doc->writeStartElement(KXMLQLCVCSpeedDial);
×
1046

1047
    saveXMLCommon(doc);
×
1048

1049
    /* Window state */
1050
    saveXMLWindowState(doc);
×
1051

1052
    /* Appearance */
1053
    saveXMLAppearance(doc);
×
1054

1055
    if (m_visibilityMask != SpeedDial::defaultVisibilityMask())
×
1056
    {
1057
        doc->writeTextElement(KXMLQLCVCSpeedDialVisibilityMask, QString::number(m_visibilityMask));
×
1058
    }
1059

1060
    /* Absolute input */
1061
    doc->writeStartElement(KXMLQLCVCSpeedDialAbsoluteValue);
×
1062
    doc->writeAttribute(KXMLQLCVCSpeedDialAbsoluteValueMin, QString::number(absoluteValueMin()));
×
1063
    doc->writeAttribute(KXMLQLCVCSpeedDialAbsoluteValueMax, QString::number(absoluteValueMax()));
×
1064
    saveXMLInput(doc, inputSource(absoluteInputSourceId));
×
1065
    doc->writeEndElement();
×
1066

1067
    /* Tap input */
1068
    QSharedPointer<QLCInputSource> tapSrc = inputSource(tapInputSourceId);
×
1069
    if (!tapSrc.isNull() && tapSrc->isValid())
×
1070
    {
1071
        doc->writeStartElement(KXMLQLCVCSpeedDialTap);
×
1072
        saveXMLInput(doc, tapSrc);
×
1073
        doc->writeEndElement();
×
1074
    }
1075

1076
    // MultDiv options
1077
    if (m_resetFactorOnDialChange)
×
1078
        doc->writeTextElement(KXMLQLCVCSpeedDialResetFactorOnDialChange, KXMLQLCTrue);
×
1079

1080
    /* Mult input */
1081
    QSharedPointer<QLCInputSource> multSrc = inputSource(multInputSourceId);
×
1082
    if (!multSrc.isNull() && multSrc->isValid())
×
1083
    {
1084
        doc->writeStartElement(KXMLQLCVCSpeedDialMult);
×
1085
        saveXMLInput(doc, multSrc);
×
1086
        doc->writeEndElement();
×
1087
    }
1088

1089
    /* Div input */
1090
    QSharedPointer<QLCInputSource> divSrc = inputSource(divInputSourceId);
×
1091
    if (!divSrc.isNull() && divSrc->isValid())
×
1092
    {
1093
        doc->writeStartElement(KXMLQLCVCSpeedDialDiv);
×
1094
        saveXMLInput(doc, divSrc);
×
1095
        doc->writeEndElement();
×
1096
    }
1097

1098
    /* MultDiv Reset input */
1099
    QSharedPointer<QLCInputSource> resetSrc = inputSource(multDivResetInputSourceId);
×
1100
    if (!resetSrc.isNull() && resetSrc->isValid())
×
1101
    {
1102
        doc->writeStartElement(KXMLQLCVCSpeedDialMultDivReset);
×
1103
        saveXMLInput(doc, resetSrc);
×
1104
        doc->writeEndElement();
×
1105
    }
1106

1107
    /* Apply input */
1108
    QSharedPointer<QLCInputSource> applySrc = inputSource(applyInputSourceId);
×
1109
    if (!applySrc.isNull() && applySrc->isValid())
×
1110
    {
1111
        doc->writeStartElement(KXMLQLCVCSpeedDialApply);
×
1112
        saveXMLInput(doc, applySrc);
×
1113
        doc->writeEndElement();
×
1114
    }
1115

1116
    /* Save time */
1117
    doc->writeTextElement(KXMLQLCVCSpeedDialTime, QString::number(m_dial->value()));
×
1118

1119
    /* Tap key sequence */
1120
    if (m_tapKeySequence.isEmpty() == false)
×
1121
        doc->writeTextElement(KXMLQLCVCSpeedDialTapKey, m_tapKeySequence.toString());
×
1122

1123
    /* Mult key sequence */
1124
    if (m_multKeySequence.isEmpty() == false)
×
1125
        doc->writeTextElement(KXMLQLCVCSpeedDialMultKey, m_multKeySequence.toString());
×
1126

1127
    /* Div key sequence */
1128
    if (m_divKeySequence.isEmpty() == false)
×
1129
        doc->writeTextElement(KXMLQLCVCSpeedDialDivKey, m_divKeySequence.toString());
×
1130

1131
    /* MultDiv Reset key sequence */
1132
    if (m_multDivResetKeySequence.isEmpty() == false)
×
1133
        doc->writeTextElement(KXMLQLCVCSpeedDialMultDivResetKey, m_multDivResetKeySequence.toString());
×
1134

1135
    /* MultDiv Reset key sequence */
1136
    if (m_applyKeySequence.isEmpty() == false)
×
1137
        doc->writeTextElement(KXMLQLCVCSpeedDialApplyKey, m_applyKeySequence.toString());
×
1138

1139
    /* Functions */
1140
    foreach (const VCSpeedDialFunction &speeddialfunction, m_functions)
×
1141
        speeddialfunction.saveXML(doc);
×
1142

1143
    // Presets
1144
    foreach (VCSpeedDialPreset *preset, presets())
×
1145
        preset->saveXML(doc);
×
1146

1147
    /* End the <SpeedDial> tag */
1148
    doc->writeEndElement();
×
1149

1150
    return true;
×
1151
}
1152

1153
void VCSpeedDial::postLoad()
×
1154
{
1155
    /* Remove such function IDs that don't exist */
1156
    QMutableListIterator <VCSpeedDialFunction> it(m_functions);
×
1157
    while (it.hasNext() == true)
×
1158
    {
1159
        it.next();
1160
        Function* function = m_doc->function(it.value().functionId);
×
1161
        if (function == NULL)
×
1162
            it.remove();
×
1163
    }
1164
}
×
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