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

mcallegari / qlcplus / 23157810099

16 Mar 2026 05:44PM UTC coverage: 33.973% (-0.08%) from 34.05%
23157810099

push

github

mcallegari
Back to 5.2.2/4.14.5 debug

17651 of 51956 relevant lines covered (33.97%)

19863.28 hits per line

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

17.25
/ui/src/virtualconsole/vcslider.cpp
1
/*
2
  Q Light Controller Plus
3
  vcslider.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Stefan Krumm
7
                Massimo Callegari
8

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

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

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

22
#include <QXmlStreamReader>
23
#include <QXmlStreamWriter>
24
#include <QWidgetAction>
25
#include <QVBoxLayout>
26
#include <QHBoxLayout>
27
#include <QMessageBox>
28
#include <QPaintEvent>
29
#include <QSettings>
30
#include <QPainter>
31
#include <QString>
32
#include <QSlider>
33
#include <QTimer>
34
#include <QDebug>
35
#include <QLabel>
36
#include <math.h>
37
#include <QMenu>
38
#include <QSize>
39
#include <QPen>
40

41
#include "vcsliderproperties.h"
42
#include "vcpropertieseditor.h"
43
#include "genericfader.h"
44
#include "fadechannel.h"
45
#include "mastertimer.h"
46
#include "qlcmacros.h"
47
#include "universe.h"
48
#include "vcslider.h"
49
#include "apputil.h"
50
#include "doc.h"
51

52
/** Number of DMXSource cycles to wait to consider a
53
 *  playback value change stable */
54
#define PLAYBACK_CHANGE_THRESHOLD   5  // roughly this is 100ms
55

56
/** +/- value range to catch the slider for external
57
 *  controllers with no feedback support */
58
#define VALUE_CATCHING_THRESHOLD    4
59

60
const quint8 VCSlider::sliderInputSourceId = 0;
61
const quint8 VCSlider::overrideResetInputSourceId = 1;
62
const quint8 VCSlider::flashButtonInputSourceId = 2;
63

64
const QSize VCSlider::defaultSize(QSize(60, 200));
65

66
const QString submasterStyleSheet =
67
    SLIDER_SS_COMMON
68

69
    "QSlider::handle:vertical { "
70
    "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #4c4c4c, stop:0.45 #2c2c2c, stop:0.50 #000, stop:0.55 #111111, stop:1 #131313);"
71
    "border: 1px solid #5c5c5c;"
72
    "border-radius: 4px; margin: 0 -4px; height: 20px; }"
73

74
    "QSlider::handle:vertical:hover {"
75
    "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #6c6c6c, stop:0.45 #4c4c4c, stop:0.50 #ffff00, stop:0.55 #313131, stop:1 #333333);"
76
    "border: 1px solid #000; }"
77

78
    "QSlider::add-page:vertical { background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #77DD73, stop: 1 #A5EC98 );"
79
    "border: 1px solid #5288A7; margin: 0 9px; }";
80

81
/*****************************************************************************
82
 * Initialization
83
 *****************************************************************************/
84

85
VCSlider::VCSlider(QWidget *parent, Doc *doc)
1✔
86
    : VCWidget(parent, doc)
87
    , m_valueDisplayStyle(ExactValue)
1✔
88
    , m_catchValues(false)
1✔
89
    , m_levelLowLimit(0)
1✔
90
    , m_levelHighLimit(UCHAR_MAX)
1✔
91
    , m_levelValueChanged(false)
1✔
92
    , m_levelValue(0)
1✔
93
    , m_monitorEnabled(false)
1✔
94
    , m_monitorValue(0)
1✔
95
    , m_playbackFunction(Function::invalidId())
1✔
96
    , m_playbackValue(0)
1✔
97
    , m_playbackChangeCounter(0)
1✔
98
    , m_playbackFlashEnable(false)
1✔
99
    , m_playbackIsFlashing(false)
1✔
100
    , m_externalMovement(false)
1✔
101
    , m_widgetMode(WSlider)
1✔
102
    , m_cngType(ClickAndGoWidget::None)
1✔
103
    , m_isOverriding(false)
1✔
104
    , m_lastInputValue(-1)
2✔
105
{
106
    /* Set the class name "VCSlider" as the object name as well */
107
    setObjectName(VCSlider::staticMetaObject.className());
1✔
108

109
    m_hbox = NULL;
1✔
110
    m_topLabel = NULL;
1✔
111
    m_slider = NULL;
1✔
112
    m_bottomLabel = NULL;
1✔
113

114
    setType(VCWidget::SliderWidget);
1✔
115
    setCaption(QString());
1✔
116
    setFrameStyle(KVCFrameStyleSunken);
1✔
117

118
    /* Main VBox */
119
    new QVBoxLayout(this);
1✔
120

121
    /* Top label */
122
    m_topLabel = new QLabel(this);
1✔
123
    m_topLabel->setAlignment(Qt::AlignHCenter);
1✔
124

125
    layout()->addWidget(m_topLabel);
1✔
126

127
    /* Slider's HBox |stretch|slider|stretch| */
128
    m_hbox = new QHBoxLayout();
1✔
129

130
    /* Put stretchable space before the slider (to its left side) */
131
    m_hbox->addStretch();
1✔
132

133
    /* The slider */
134
    m_slider = new ClickAndGoSlider(this);
1✔
135

136
    m_hbox->addWidget(m_slider);
1✔
137
    m_slider->setRange(0, 255);
1✔
138
    m_slider->setPageStep(1);
1✔
139
    m_slider->setInvertedAppearance(false);
1✔
140
    m_slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
1✔
141
    m_slider->setMinimumWidth(32);
1✔
142
    m_slider->setMaximumWidth(80);
1✔
143
    m_slider->setStyleSheet(CNG_DEFAULT_STYLE);
1✔
144

145
    connect(m_slider, SIGNAL(valueChanged(int)),
1✔
146
            this, SLOT(slotSliderMoved(int)));
147
    connect(this, SIGNAL(requestSliderUpdate(int)),
2✔
148
            m_slider, SLOT(setValue(int)));
1✔
149

150
    /* Put stretchable space after the slider (to its right side) */
151
    m_hbox->addStretch();
1✔
152

153
    layout()->addItem(m_hbox);
1✔
154

155
    /* Click & Go button */
156
    m_cngButton = new QToolButton(this);
1✔
157
    m_cngButton->setFixedSize(48, 48);
1✔
158
    m_cngButton->setIconSize(QSize(42, 42));
1✔
159
    m_menu = new QMenu(this);
1✔
160
    QWidgetAction* action = new QWidgetAction(this);
1✔
161
    m_cngWidget = new ClickAndGoWidget();
1✔
162
    action->setDefaultWidget(m_cngWidget);
1✔
163
    m_menu->addAction(action);
1✔
164
    m_cngButton->setMenu(m_menu);
1✔
165
    m_cngButton->setPopupMode(QToolButton::InstantPopup);
1✔
166
    layout()->addWidget(m_cngButton);
1✔
167
    layout()->setAlignment(m_cngButton, Qt::AlignHCenter);
1✔
168
    m_cngButton->hide();
1✔
169

170
    connect(m_cngWidget, SIGNAL(levelChanged(uchar)),
1✔
171
            this, SLOT(slotClickAndGoLevelChanged(uchar)));
172
    connect(m_cngWidget, SIGNAL(colorChanged(QRgb)),
1✔
173
            this, SLOT(slotClickAndGoColorChanged(QRgb)));
174
    connect(m_cngWidget, SIGNAL(levelAndPresetChanged(uchar,QImage)),
1✔
175
            this, SLOT(slotClickAndGoLevelAndPresetChanged(uchar, QImage)));
176
    connect(this, SIGNAL(monitorDMXValueChanged(int)),
1✔
177
            this, SLOT(slotMonitorDMXValueChanged(int)));
178

179
    m_resetButton = NULL;
1✔
180
    m_flashButton = NULL;
1✔
181

182
    /* Bottom label */
183
    m_bottomLabel = new QLabel(this);
1✔
184
    layout()->addWidget(m_bottomLabel);
1✔
185
    m_bottomLabel->setAlignment(Qt::AlignCenter);
1✔
186
    m_bottomLabel->setWordWrap(true);
1✔
187
    m_bottomLabel->hide();
1✔
188

189
    setMinimumSize(20, 20);
1✔
190
    QSettings settings;
1✔
191
    QVariant var = settings.value(SETTINGS_SLIDER_SIZE);
1✔
192
    if (var.isValid() == true)
1✔
193
        resize(var.toSize());
×
194
    else
195
        resize(VCSlider::defaultSize);
1✔
196

197
    /* Initialize to playback mode by default */
198
    setInvertedAppearance(false);
1✔
199
    m_sliderMode = SliderMode(-1); // avoid use of uninitialized value
1✔
200
    setSliderMode(Playback);
1✔
201

202
    /* Update the slider according to current mode */
203
    slotModeChanged(m_doc->mode());
1✔
204
    setLiveEdit(m_liveEdit);
1✔
205

206
    /* Listen to fixture removals so that LevelChannels can be removed when
207
       they no longer point to an existing fixture->channel */
208
    connect(m_doc, SIGNAL(fixtureRemoved(quint32)),
1✔
209
            this, SLOT(slotFixtureRemoved(quint32)));
210
}
1✔
211

212
VCSlider::~VCSlider()
2✔
213
{
214
    /* When application exits these are already NULL and unregistration
215
       is no longer necessary. But a normal deletion of a VCSlider in
216
       design mode must unregister the slider. */
217
    m_doc->masterTimer()->unregisterDMXSource(this);
1✔
218

219
    // request to delete all the active faders
220
    foreach (QSharedPointer<GenericFader> fader, m_fadersMap)
1✔
221
    {
222
        if (!fader.isNull())
×
223
            fader->requestDelete();
×
224
    }
1✔
225
    m_fadersMap.clear();
1✔
226
}
2✔
227

228
void VCSlider::setID(quint32 id)
×
229
{
230
    VCWidget::setID(id);
×
231

232
    if (caption().isEmpty())
×
233
        setCaption(tr("Slider %1").arg(id));
×
234
}
×
235

236
/*****************************************************************************
237
 * Clipboard
238
 *****************************************************************************/
239

240
VCWidget* VCSlider::createCopy(VCWidget* parent) const
×
241
{
242
    Q_ASSERT(parent != NULL);
×
243

244
    VCSlider* slider = new VCSlider(parent, m_doc);
×
245
    if (slider->copyFrom(this) == false)
×
246
    {
247
        delete slider;
×
248
        slider = NULL;
×
249
    }
250

251
    return slider;
×
252
}
253

254
bool VCSlider::copyFrom(const VCWidget* widget)
×
255
{
256
    const VCSlider* slider = qobject_cast<const VCSlider*> (widget);
×
257
    if (slider == NULL)
×
258
        return false;
×
259

260
    /* Copy widget style */
261
    setWidgetStyle(slider->widgetStyle());
×
262

263
    /* Copy level stuff */
264
    setLevelLowLimit(slider->levelLowLimit());
×
265
    setLevelHighLimit(slider->levelHighLimit());
×
266
    m_levelChannels = slider->m_levelChannels;
×
267

268
    /* Copy playback stuff */
269
    m_playbackFunction = slider->m_playbackFunction;
×
270

271
    /* Copy slider appearance */
272
    setValueDisplayStyle(slider->valueDisplayStyle());
×
273
    setInvertedAppearance(slider->invertedAppearance());
×
274

275
    /* Copy Click & Go feature */
276
    setClickAndGoType(slider->clickAndGoType());
×
277

278
    /* Copy mode & current value */
279
    setSliderMode(slider->sliderMode());
×
280
    setSliderValue(slider->sliderValue());
×
281

282
    /* Copy monitor mode */
283
    setChannelsMonitorEnabled(slider->channelsMonitorEnabled());
×
284

285
    /* Copy flash enabling */
286
    setPlaybackFlashEnable(slider->playbackFlashEnable());
×
287

288
    /* Copy common stuff */
289
    return VCWidget::copyFrom(widget);
×
290
}
291

292
/*****************************************************************************
293
 * GUI
294
 *****************************************************************************/
295

296
void VCSlider::setCaption(const QString& text)
1✔
297
{
298
    VCWidget::setCaption(text);
1✔
299

300
    if (m_bottomLabel != NULL)
1✔
301
        setBottomLabelText(text);
×
302
}
1✔
303

304
void VCSlider::enableWidgetUI(bool enable)
1✔
305
{
306
    m_topLabel->setEnabled(enable);
1✔
307
    if (m_slider)
1✔
308
        m_slider->setEnabled(enable);
1✔
309
    m_bottomLabel->setEnabled(enable);
1✔
310
    m_cngButton->setEnabled(enable);
1✔
311
    if (m_resetButton)
1✔
312
        m_resetButton->setEnabled(enable);
×
313
    if (m_flashButton)
1✔
314
        m_flashButton->setEnabled(enable);
×
315
    if (enable == false)
1✔
316
        m_lastInputValue = -1;
1✔
317
}
1✔
318

319
void VCSlider::hideEvent(QHideEvent *)
×
320
{
321
    m_lastInputValue = -1;
×
322
}
×
323

324
/*****************************************************************************
325
 * Properties
326
 *****************************************************************************/
327

328
void VCSlider::editProperties()
×
329
{
330
    VCSliderProperties prop(this, m_doc);
×
331
    if (prop.exec() == QDialog::Accepted)
×
332
    {
333
        m_doc->setModified();
×
334
        if (m_cngType == ClickAndGoWidget::None)
×
335
            m_cngButton->hide();
×
336
        else
337
            m_cngButton->show();
×
338
    }
339
}
×
340

341
/*****************************************************************************
342
 * QLC Mode
343
 *****************************************************************************/
344

345
void VCSlider::slotModeChanged(Doc::Mode mode)
1✔
346
{
347
    if (mode == Doc::Operate)
1✔
348
    {
349
        enableWidgetUI(true);
×
350
        if (m_sliderMode == Level || m_sliderMode == Playback)
×
351
        {
352
            m_doc->masterTimer()->registerDMXSource(this);
×
353
            if (m_sliderMode == Level)
×
354
                m_levelValueChanged = true;
×
355
        }
356
    }
357
    else
358
    {
359
        enableWidgetUI(false);
1✔
360
        if (m_sliderMode == Level || m_sliderMode == Playback)
1✔
361
        {
362
            m_doc->masterTimer()->unregisterDMXSource(this);
1✔
363
            // request to delete all the active faders
364
            foreach (QSharedPointer<GenericFader> fader, m_fadersMap)
1✔
365
            {
366
                if (!fader.isNull())
×
367
                    fader->requestDelete();
×
368
            }
1✔
369
            m_fadersMap.clear();
1✔
370
        }
371
    }
372

373
    VCWidget::slotModeChanged(mode);
1✔
374
}
1✔
375

376
/*****************************************************************************
377
 * Value display style
378
 *****************************************************************************/
379

380
QString VCSlider::valueDisplayStyleToString(VCSlider::ValueDisplayStyle style)
×
381
{
382
    switch (style)
×
383
    {
384
    case ExactValue:
×
385
        return KXMLQLCVCSliderValueDisplayStyleExact;
×
386
    case PercentageValue:
×
387
        return KXMLQLCVCSliderValueDisplayStylePercentage;
×
388
    default:
×
389
        return QString("Unknown");
×
390
    };
391
}
392

393
VCSlider::ValueDisplayStyle VCSlider::stringToValueDisplayStyle(QString style)
×
394
{
395
    if (style == KXMLQLCVCSliderValueDisplayStyleExact)
×
396
        return ExactValue;
×
397
    else if (style == KXMLQLCVCSliderValueDisplayStylePercentage)
×
398
        return PercentageValue;
×
399
    else
400
        return ExactValue;
×
401
}
402

403
void VCSlider::setValueDisplayStyle(VCSlider::ValueDisplayStyle style)
×
404
{
405
    m_valueDisplayStyle = style;
×
406
    if (m_slider)
×
407
        setTopLabelText(m_slider->value());
×
408
}
×
409

410
VCSlider::ValueDisplayStyle VCSlider::valueDisplayStyle() const
2✔
411
{
412
    return m_valueDisplayStyle;
2✔
413
}
414

415
/*****************************************************************************
416
 * Inverted appearance
417
 *****************************************************************************/
418

419
bool VCSlider::invertedAppearance() const
×
420
{
421
    if (m_slider)
×
422
        return m_slider->invertedAppearance();
×
423

424
    return false;
×
425
}
426

427
void VCSlider::setInvertedAppearance(bool invert)
2✔
428
{
429
    if (m_slider)
2✔
430
    {
431
        m_slider->setInvertedAppearance(invert);
2✔
432
        m_slider->setInvertedControls(invert);
2✔
433
    }
434
}
2✔
435

436
/*********************************************************************
437
 * Value catching feature
438
 *********************************************************************/
439

440
bool VCSlider::catchValues() const
×
441
{
442
    return m_catchValues;
×
443
}
444

445
void VCSlider::setCatchValues(bool enable)
×
446
{
447
    if (enable == m_catchValues)
×
448
        return;
×
449

450
    m_catchValues = enable;
×
451
}
452

453
/*****************************************************************************
454
 * Slider Mode
455
 *****************************************************************************/
456

457
QString VCSlider::sliderModeToString(SliderMode mode)
×
458
{
459
    switch (mode)
×
460
    {
461
        case Level: return QString("Level"); break;
×
462
        case Playback: return QString("Playback"); break;
×
463
        case Submaster: return QString("Submaster"); break;
×
464
        default: return QString("Unknown"); break;
×
465
    }
466
}
467

468
VCSlider::SliderMode VCSlider::stringToSliderMode(const QString& mode)
×
469
{
470
    if (mode == QString("Level"))
×
471
        return Level;
×
472
    else  if (mode == QString("Playback"))
×
473
       return Playback;
×
474
    else //if (mode == QString("Submaster"))
475
        return Submaster;
×
476
}
477

478
VCSlider::SliderMode VCSlider::sliderMode() const
×
479
{
480
    return m_sliderMode;
×
481
}
482

483
void VCSlider::setSliderMode(SliderMode mode)
2✔
484
{
485
    Q_ASSERT(mode >= Level && mode <= Submaster);
2✔
486

487
    m_sliderMode = mode;
2✔
488

489
    if (mode == Level)
2✔
490
    {
491
        /* Set the slider range */
492
        if (m_slider)
×
493
        {
494
            m_slider->setRange(levelLowLimit(), levelHighLimit());
×
495
            m_slider->setValue(levelValue());
×
496
            if (m_widgetMode == WSlider)
×
497
                m_slider->setStyleSheet(CNG_DEFAULT_STYLE);
×
498
        }
499

500
        m_bottomLabel->show();
×
501
        if (m_cngType != ClickAndGoWidget::None)
×
502
        {
503
            setClickAndGoType(m_cngType);
×
504
            setupClickAndGoWidget();
×
505
            m_cngButton->show();
×
506
            if (m_slider)
×
507
                setClickAndGoWidgetFromLevel(m_slider->value());
×
508
        }
509

510
        if (m_doc->mode() == Doc::Operate)
×
511
            m_doc->masterTimer()->registerDMXSource(this);
×
512
    }
513
    else if (mode == Playback)
2✔
514
    {
515
        m_bottomLabel->show();
2✔
516
        m_cngButton->hide();
2✔
517
        m_monitorEnabled = false;
2✔
518

519
        uchar level = playbackValue();
2✔
520
        if (m_slider)
2✔
521
        {
522
            m_slider->setRange(0, UCHAR_MAX);
2✔
523
            m_slider->setValue(level);
2✔
524
            if (m_widgetMode == WSlider)
2✔
525
                m_slider->setStyleSheet(CNG_DEFAULT_STYLE);
2✔
526
        }
527
        slotSliderMoved(level);
2✔
528

529
        if (m_doc->mode() == Doc::Operate)
2✔
530
            m_doc->masterTimer()->registerDMXSource(this);
×
531
        setPlaybackFunction(this->m_playbackFunction);
2✔
532
    }
533
    else if (mode == Submaster)
×
534
    {
535
        m_monitorEnabled = false;
×
536
        setPlaybackFunction(Function::invalidId());
×
537

538
        if (m_slider)
×
539
        {
540
            m_slider->setRange(0, UCHAR_MAX);
×
541
            m_slider->setValue(levelValue());
×
542
            if (m_widgetMode == WSlider)
×
543
                m_slider->setStyleSheet(submasterStyleSheet);
×
544
        }
545
        if (m_doc->mode() == Doc::Operate)
×
546
            m_doc->masterTimer()->unregisterDMXSource(this);
×
547
    }
548
}
2✔
549

550
/*****************************************************************************
551
 * Level
552
 *****************************************************************************/
553

554
void VCSlider::addLevelChannel(quint32 fixture, quint32 channel)
×
555
{
556
    LevelChannel lch(fixture, channel);
×
557

558
    if (m_levelChannels.contains(lch) == false)
×
559
    {
560
        m_levelChannels.append(lch);
×
561
        std::sort(m_levelChannels.begin(), m_levelChannels.end());
×
562
    }
563
}
×
564

565
void VCSlider::removeLevelChannel(quint32 fixture, quint32 channel)
×
566
{
567
    LevelChannel lch(fixture, channel);
×
568
    m_levelChannels.removeAll(lch);
×
569
}
×
570

571
void VCSlider::clearLevelChannels()
×
572
{
573
    m_levelChannels.clear();
×
574
}
×
575

576
QList <VCSlider::LevelChannel> VCSlider::levelChannels()
×
577
{
578
    return m_levelChannels;
×
579
}
580

581
void VCSlider::setLevelLowLimit(uchar value)
×
582
{
583
    m_levelLowLimit = value;
×
584
    if (m_cngWidget != NULL)
×
585
        m_cngWidget->setLevelLowLimit(value);
×
586
}
×
587

588
uchar VCSlider::levelLowLimit() const
×
589
{
590
    return m_levelLowLimit;
×
591
}
592

593
void VCSlider::setLevelHighLimit(uchar value)
×
594
{
595
    m_levelHighLimit = value;
×
596
    if (m_cngWidget != NULL)
×
597
        m_cngWidget->setLevelHighLimit(value);
×
598
}
×
599

600
uchar VCSlider::levelHighLimit() const
×
601
{
602
    return m_levelHighLimit;
×
603
}
604

605
void VCSlider::setChannelsMonitorEnabled(bool enable)
×
606
{
607
    m_monitorEnabled = enable;
×
608

609
    if (m_resetButton != NULL)
×
610
    {
611
        disconnect(m_resetButton, SIGNAL(clicked(bool)),
×
612
                this, SLOT(slotResetButtonClicked()));
613
        delete m_resetButton;
×
614
        m_resetButton = NULL;
×
615
    }
616

617
    if (enable)
×
618
    {
619
        m_resetButton = new QToolButton(this);
×
620
        m_resetButton->setFixedSize(32, 32);
×
621
        m_resetButton->setIconSize(QSize(32, 32));
×
622
        m_resetButton->setStyle(AppUtil::saneStyle());
×
623
        m_resetButton->setIcon(QIcon(":/fileclose.png"));
×
624
        m_resetButton->setToolTip(tr("Reset channels override"));
×
625
        layout()->addWidget(m_resetButton);
×
626
        layout()->setAlignment(m_resetButton, Qt::AlignHCenter);
×
627

628
        connect(m_resetButton, SIGNAL(clicked(bool)),
×
629
                this, SLOT(slotResetButtonClicked()));
630
        m_resetButton->show();
×
631
        setSliderShadowValue(m_monitorValue);
×
632
    }
633
    else
634
    {
635
        setSliderShadowValue(-1);
×
636
    }
637
}
×
638

639
bool VCSlider::channelsMonitorEnabled() const
×
640
{
641
    return m_monitorEnabled;
×
642
}
643

644
void VCSlider::setLevelValue(uchar value, bool external)
×
645
{
646
    QMutexLocker locker(&m_levelValueMutex);
×
647
    m_levelValue = CLAMP(value, levelLowLimit(), levelHighLimit());
×
648
    if (m_monitorEnabled == true)
×
649
        m_monitorValue = m_levelValue;
×
650
    if (m_slider->isSliderDown() || external)
×
651
        m_levelValueChanged = true;
×
652
}
×
653

654
uchar VCSlider::levelValue() const
×
655
{
656
    return m_levelValue;
×
657
}
658

659
void VCSlider::slotFixtureRemoved(quint32 fxi_id)
×
660
{
661
    QMutableListIterator <LevelChannel> it(m_levelChannels);
×
662
    while (it.hasNext() == true)
×
663
    {
664
        it.next();
×
665
        if (it.value().fixture == fxi_id)
×
666
            it.remove();
×
667
    }
668
}
×
669

670
void VCSlider::slotMonitorDMXValueChanged(int value)
×
671
{
672
    if (value == sliderValue())
×
673
        return;
×
674

675
    m_monitorValue = value;
×
676

677
    if (m_isOverriding == false)
×
678
    {
679
        {
680
            QMutexLocker locker(&m_levelValueMutex);
×
681
            m_levelValue = m_monitorValue;
×
682
        }
×
683

684
        if (m_slider)
×
685
            m_slider->blockSignals(true);
×
686
        setSliderValue(value, false);
×
687
        setTopLabelText(sliderValue());
×
688
        if (m_slider)
×
689
            m_slider->blockSignals(false);
×
690
    }
691
    setSliderShadowValue(value);
×
692
    updateFeedback();
×
693
}
694

695
void VCSlider::slotUniverseWritten(quint32 idx, const QByteArray &universeData)
×
696
{
697
    if (m_levelValueChanged)
×
698
        return;
×
699

700
    bool mixedDMXlevels = false;
×
701
    int monitorSliderValue = -1;
×
702
    QListIterator <LevelChannel> it(m_levelChannels);
×
703

704
    while (it.hasNext() == true)
×
705
    {
706
        LevelChannel lch(it.next());
×
707
        Fixture* fxi = m_doc->fixture(lch.fixture);
×
708
        if (fxi == NULL || fxi->universe() != idx)
×
709
            continue;
×
710

711
        if (lch.channel >= fxi->channels() ||
×
712
            fxi->address() + lch.channel >= (quint32)universeData.length())
×
713
            continue;
×
714

715
        quint32 dmx_ch = fxi->address() + lch.channel;
×
716
        uchar chValue = universeData.at(dmx_ch);
×
717
        if (monitorSliderValue == -1)
×
718
        {
719
            monitorSliderValue = chValue;
×
720
            //qDebug() << "Monitor DMX value:" << monitorSliderValue << "level value:" << m_levelValue;
721
        }
722
        else
723
        {
724
            if (chValue != (uchar)monitorSliderValue)
×
725
            {
726
                mixedDMXlevels = true;
×
727
                // no need to proceed further as mixed values cannot
728
                // be represented by one single slider
729
                break;
×
730
            }
731
        }
732
    }
733

734
    // check if all the DMX channels controlled by this slider
735
    // have the same value. If so, move the widget slider or knob
736
    // to the detected position
737
    if (mixedDMXlevels == false &&
×
738
        monitorSliderValue != m_monitorValue)
×
739
    {
740
        emit monitorDMXValueChanged(monitorSliderValue);
×
741

742
        if (m_isOverriding == false)
×
743
        {
744
            // return here. At the next call of this method,
745
            // the monitor level will kick in
746
            return;
×
747
        }
748
    }
749
}
×
750

751
/*********************************************************************
752
 * Click & Go
753
 *********************************************************************/
754

755
void VCSlider::setClickAndGoType(ClickAndGoWidget::ClickAndGo type)
×
756
{
757
    m_cngType = type;
×
758
}
×
759

760
ClickAndGoWidget::ClickAndGo VCSlider::clickAndGoType() const
×
761
{
762
    return m_cngType;
×
763
}
764

765
void VCSlider::setupClickAndGoWidget()
×
766
{
767
    if (m_cngWidget != NULL)
×
768
    {
769
        qDebug() << Q_FUNC_INFO << "Level channel: " << m_levelChannels.size() << "type: " << m_cngType;
×
770
        if (m_cngType == ClickAndGoWidget::Preset && m_levelChannels.size() > 0)
×
771
        {
772
            LevelChannel lChan = m_levelChannels.first();
×
773
            Fixture *fxi = m_doc->fixture(lChan.fixture);
×
774
            if (fxi != NULL)
×
775
            {
776
                const QLCChannel *chan = fxi->channel(lChan.channel);
×
777
                m_cngWidget->setType(m_cngType, chan);
×
778
                m_cngWidget->setLevelLowLimit(this->levelLowLimit());
×
779
                m_cngWidget->setLevelHighLimit(this->levelHighLimit());
×
780
            }
781
        }
782
        else
783
            m_cngWidget->setType(m_cngType, NULL);
×
784
    }
785
}
×
786

787
ClickAndGoWidget *VCSlider::getClickAndGoWidget()
×
788
{
789
    return m_cngWidget;
×
790
}
791

792
void VCSlider::setClickAndGoWidgetFromLevel(uchar level)
×
793
{
794
    if (m_cngType == ClickAndGoWidget::None || m_cngWidget == NULL)
×
795
        return;
×
796

797
    if (m_cngType == ClickAndGoWidget::RGB || m_cngType == ClickAndGoWidget::CMY)
×
798
    {
799
        QPixmap px(42, 42);
×
800
        float f = 0;
×
801
        if (m_slider)
×
802
            f = SCALE(float(level), float(m_slider->minimum()),
×
803
                      float(m_slider->maximum()), float(0), float(200));
804

805
        if ((uchar)f == 0)
×
806
        {
807
            px.fill(Qt::black);
×
808
        }
809
        else
810
        {
811
            QColor modColor = m_cngRGBvalue.lighter((uchar)f);
×
812
            px.fill(modColor);
×
813
        }
814
        m_cngButton->setIcon(px);
×
815
    }
×
816
    else
817
        m_cngButton->setIcon(QPixmap::fromImage(m_cngWidget->getImageFromValue(level)));
×
818
}
819

820
void VCSlider::slotClickAndGoLevelChanged(uchar level)
×
821
{
822
    setSliderValue(level, false, false);
×
823
    updateFeedback();
×
824

825
    QColor col = m_cngWidget->getColorAt(level);
×
826
    QPixmap px(42, 42);
×
827
    px.fill(col);
×
828
    m_cngButton->setIcon(px);
×
829
    m_levelValueChanged = true;
×
830
}
×
831

832
void VCSlider::slotClickAndGoColorChanged(QRgb color)
×
833
{
834
    QColor col(color);
×
835
    m_cngRGBvalue = col;
×
836
    QPixmap px(42, 42);
×
837
    px.fill(col);
×
838
    m_cngButton->setIcon(px);
×
839

840
    // place the slider half way to reach white@255 and black@0
841
    setSliderValue(128);
×
842
    updateFeedback();
×
843

844
    // let's force a value change to cover all the HTP/LTP cases
845
    m_levelValueChanged = true;
×
846
}
×
847

848
void VCSlider::slotClickAndGoLevelAndPresetChanged(uchar level, QImage img)
×
849
{
850
    setSliderValue(level, false, false);
×
851
    updateFeedback();
×
852

853
    QPixmap px = QPixmap::fromImage(img);
×
854
    m_cngButton->setIcon(px);
×
855
    m_levelValueChanged = true;
×
856
}
×
857

858
/*********************************************************************
859
 * Override reset button
860
 *********************************************************************/
861

862
void VCSlider::setOverrideResetKeySequence(const QKeySequence &keySequence)
×
863
{
864
    m_overrideResetKeySequence = QKeySequence(keySequence);
×
865
}
×
866

867
QKeySequence VCSlider::overrideResetKeySequence() const
×
868
{
869
    return m_overrideResetKeySequence;
×
870
}
871

872
void VCSlider::slotResetButtonClicked()
×
873
{
874
    m_isOverriding = false;
×
875
    if (m_resetButton != nullptr)
×
876
        m_resetButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
877
                                     .arg(m_slider->palette().window().color().name()));
×
878

879
    // request to delete all the active fader channels
880
    foreach (QSharedPointer<GenericFader> fader, m_fadersMap)
×
881
    {
882
        if (!fader.isNull())
×
883
            fader->removeAll();
×
884
    }
×
885
    updateOverrideFeedback(false);
×
886

887
    emit monitorDMXValueChanged(m_monitorValue);
×
888
}
×
889

890
void VCSlider::slotKeyPressed(const QKeySequence &keySequence)
×
891
{
892
    if (isEnabled() == false)
×
893
        return;
×
894

895
    if (m_overrideResetKeySequence == keySequence)
×
896
        slotResetButtonClicked();
×
897
    else if (m_playbackFlashKeySequence == keySequence)
×
898
        flashPlayback(true);
×
899
}
900

901
void VCSlider::slotKeyReleased(const QKeySequence &keySequence)
×
902
{
903
    if (m_playbackFlashKeySequence == keySequence && m_playbackIsFlashing)
×
904
        flashPlayback(false);
×
905
}
×
906

907
/*********************************************************************
908
 * Flash button
909
 *********************************************************************/
910

911
QKeySequence VCSlider::playbackFlashKeySequence() const
×
912
{
913
    return m_playbackFlashKeySequence;
×
914
}
915

916
void VCSlider::setPlaybackFlashKeySequence(const QKeySequence &keySequence)
×
917
{
918
    m_playbackFlashKeySequence = QKeySequence(keySequence);
×
919
}
×
920

921
void VCSlider::mousePressEvent(QMouseEvent *e)
×
922
{
923
    VCWidget::mousePressEvent(e);
×
924

925
    if (mode() != Doc::Design && e->button() == Qt::LeftButton &&
×
926
        m_flashButton && m_flashButton->isDown())
×
927
    {
928
        flashPlayback(true);
×
929
    }
930
}
×
931

932
void VCSlider::mouseReleaseEvent(QMouseEvent *e)
×
933
{
934
    if (mode() == Doc::Design)
×
935
    {
936
        VCWidget::mouseReleaseEvent(e);
×
937
    }
938
    else if (m_playbackIsFlashing)
×
939
    {
940
        flashPlayback(false);
×
941
    }
942
}
×
943

944
/*****************************************************************************
945
 * Playback
946
 *****************************************************************************/
947

948
void VCSlider::setPlaybackFunction(quint32 fid)
2✔
949
{
950
    Function* old = m_doc->function(m_playbackFunction);
2✔
951
    if (old != NULL)
2✔
952
    {
953
        /* Get rid of old function connections */
954
        disconnect(old, SIGNAL(running(quint32)),
×
955
                this, SLOT(slotPlaybackFunctionRunning(quint32)));
956
        disconnect(old, SIGNAL(stopped(quint32)),
×
957
                this, SLOT(slotPlaybackFunctionStopped(quint32)));
958
        disconnect(old, SIGNAL(attributeChanged(int, qreal)),
×
959
                this, SLOT(slotPlaybackFunctionIntensityChanged(int, qreal)));
960
        if (old->type() == Function::SceneType)
×
961
        {
962
            disconnect(old, SIGNAL(flashing(quint32,bool)),
×
963
                       this, SLOT(slotPlaybackFunctionFlashing(quint32,bool)));
964
        }
965
    }
966

967
    Function* function = m_doc->function(fid);
2✔
968
    if (function != NULL)
2✔
969
    {
970
        /* Connect to the new function */
971
        connect(function, SIGNAL(running(quint32)),
×
972
                this, SLOT(slotPlaybackFunctionRunning(quint32)));
973
        connect(function, SIGNAL(stopped(quint32)),
×
974
                this, SLOT(slotPlaybackFunctionStopped(quint32)));
975
        connect(function, SIGNAL(attributeChanged(int, qreal)),
×
976
                this, SLOT(slotPlaybackFunctionIntensityChanged(int, qreal)));
977
        if (function->type() == Function::SceneType)
×
978
        {
979
            connect(function, SIGNAL(flashing(quint32,bool)),
×
980
                    this, SLOT(slotPlaybackFunctionFlashing(quint32,bool)));
981
        }
982

983
        m_playbackFunction = fid;
×
984
    }
985
    else
986
    {
987
        /* No function attachment */
988
        m_playbackFunction = Function::invalidId();
2✔
989
    }
990
}
2✔
991

992
quint32 VCSlider::playbackFunction() const
×
993
{
994
    return m_playbackFunction;
×
995
}
996

997
void VCSlider::setPlaybackValue(uchar value)
×
998
{
999
    if (m_externalMovement == true || value == m_playbackValue)
×
1000
        return;
×
1001

1002
    QMutexLocker locker(&m_playbackValueMutex);
×
1003
    m_playbackValue = value;
×
1004
    m_playbackChangeCounter = 5;
×
1005
}
×
1006

1007
uchar VCSlider::playbackValue() const
2✔
1008
{
1009
    return m_playbackValue;
2✔
1010
}
1011

1012
void VCSlider::notifyFunctionStarting(quint32 fid, qreal functionIntensity, bool excludeMonitored)
×
1013
{
1014
    Q_UNUSED(excludeMonitored)
1015

1016
    if (mode() == Doc::Design || sliderMode() != Playback)
×
1017
        return;
×
1018

1019
    if (fid == playbackFunction())
×
1020
        return;
×
1021

1022
    if (m_slider != NULL)
×
1023
    {
1024
        int value = SCALE(1.0 - functionIntensity, 0, 1.0,
×
1025
                          m_slider->minimum(), m_slider->maximum());
1026
        if (m_slider->value() > value)
×
1027
        {
1028
            m_externalMovement = true;
×
1029
            m_slider->setValue(value);
×
1030
            m_externalMovement = false;
×
1031

1032
            Function* function = m_doc->function(m_playbackFunction);
×
1033
            if (function != NULL)
×
1034
            {
1035
                qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
1036
                adjustFunctionIntensity(function, pIntensity * intensity());
×
1037
                if (value == 0 && !function->stopped())
×
1038
                    function->stop(functionParent());
×
1039
            }
1040
        }
1041
    }
1042
}
1043

1044
bool VCSlider::playbackFlashEnable() const
×
1045
{
1046
    return m_playbackFlashEnable;
×
1047
}
1048

1049
void VCSlider::setPlaybackFlashEnable(bool enable)
×
1050
{
1051
    m_playbackFlashEnable = enable;
×
1052

1053
    if (enable == false && m_flashButton != NULL)
×
1054
    {
1055
        delete m_flashButton;
×
1056
        m_flashButton = NULL;
×
1057
    }
1058
    else if (enable == true && m_flashButton == NULL)
×
1059
    {
1060
        m_flashButton = new FlashButton(this);
×
1061
        m_flashButton->setIconSize(QSize(32, 32));
×
1062
        m_flashButton->setStyle(AppUtil::saneStyle());
×
1063
        m_flashButton->setIcon(QIcon(":/flash.png"));
×
1064
        m_flashButton->setToolTip(tr("Flash Function"));
×
1065
        layout()->addWidget(m_flashButton);
×
1066
        layout()->setAlignment(m_flashButton, Qt::AlignHCenter);
×
1067

1068
        m_flashButton->show();
×
1069
    }
1070
}
×
1071

1072
void VCSlider::flashPlayback(bool on)
×
1073
{
1074
    if (on)
×
1075
        m_playbackFlashPreviousValue = m_playbackValue;
×
1076
    m_playbackIsFlashing = on;
×
1077

1078
    setPlaybackValue(on ? UCHAR_MAX : m_playbackFlashPreviousValue);
×
1079
}
×
1080

1081
void VCSlider::slotPlaybackFunctionRunning(quint32 fid)
×
1082
{
1083
    Q_UNUSED(fid);
1084
}
×
1085

1086
void VCSlider::slotPlaybackFunctionStopped(quint32 fid)
×
1087
{
1088
    if (fid != playbackFunction())
×
1089
        return;
×
1090

1091
    m_externalMovement = true;
×
1092
    if (m_slider)
×
1093
        m_slider->setValue(0);
×
1094
    resetIntensityOverrideAttribute();
×
1095
    updateFeedback();
×
1096
    m_externalMovement = false;
×
1097
}
1098

1099
void VCSlider::slotPlaybackFunctionIntensityChanged(int attrIndex, qreal fraction)
×
1100
{
1101
    //qDebug() << "Function intensity changed" << attrIndex << fraction << m_playbackChangeCounter;
1102

1103
    if (attrIndex != Function::Intensity || m_playbackChangeCounter)
×
1104
        return;
×
1105

1106
    m_externalMovement = true;
×
1107
    if (m_slider)
×
1108
        m_slider->setValue(int(floor((qreal(m_slider->maximum()) * fraction) + 0.5)));
×
1109
    updateFeedback();
×
1110
    m_externalMovement = false;
×
1111
}
1112

1113
void VCSlider::slotPlaybackFunctionFlashing(quint32 fid, bool flashing)
×
1114
{
1115
    if (fid != playbackFunction())
×
1116
        return;
×
1117

1118
    m_externalMovement = true;
×
1119
    if (m_slider)
×
1120
        m_slider->setValue(flashing ? m_slider->maximum() : m_slider->minimum());
×
1121
    updateFeedback();
×
1122
    m_externalMovement = false;
×
1123
}
1124

1125
FunctionParent VCSlider::functionParent() const
×
1126
{
1127
    return FunctionParent(FunctionParent::ManualVCWidget, id());
×
1128
}
1129

1130
/*********************************************************************
1131
 * Submaster
1132
 *********************************************************************/
1133

1134
void VCSlider::emitSubmasterValue()
×
1135
{
1136
    Q_ASSERT(sliderMode() == Submaster);
×
1137

1138
    emit submasterValueChanged(SCALE(float(m_levelValue), float(0),
×
1139
                float(UCHAR_MAX), float(0), float(1)) * intensity());
×
1140
}
×
1141

1142
/*****************************************************************************
1143
 * DMXSource
1144
 *****************************************************************************/
1145

1146
void VCSlider::writeDMX(MasterTimer *timer, QList<Universe *> universes)
×
1147
{
1148
    if (sliderMode() == Level)
×
1149
        writeDMXLevel(timer, universes);
×
1150
    else if (sliderMode() == Playback)
×
1151
        writeDMXPlayback(timer, universes);
×
1152
}
×
1153

1154
void VCSlider::writeDMXLevel(MasterTimer *timer, QList<Universe *> universes)
×
1155
{
1156
    Q_UNUSED(timer);
1157

1158
    QMutexLocker locker(&m_levelValueMutex);
×
1159

1160
    uchar modLevel = m_levelValue;
×
1161
    int r = 0, g = 0, b = 0, c = 0, m = 0, y = 0;
×
1162

1163
    if (m_cngType == ClickAndGoWidget::RGB)
×
1164
    {
1165
        float f = 0;
×
1166
        if (m_slider)
×
1167
            f = SCALE(float(m_levelValue), float(m_slider->minimum()),
×
1168
                      float(m_slider->maximum()), float(0), float(200));
1169

1170
        if (uchar(f) != 0)
×
1171
        {
1172
            QColor modColor = m_cngRGBvalue.lighter(uchar(f));
×
1173
            r = modColor.red();
×
1174
            g = modColor.green();
×
1175
            b = modColor.blue();
×
1176
        }
1177
    }
1178
    else if (m_cngType == ClickAndGoWidget::CMY)
×
1179
    {
1180
        float f = 0;
×
1181
        if (m_slider)
×
1182
            f = SCALE(float(m_levelValue), float(m_slider->minimum()),
×
1183
                      float(m_slider->maximum()), float(0), float(200));
1184
        if (uchar(f) != 0)
×
1185
        {
1186
            QColor modColor = m_cngRGBvalue.lighter(uchar(f));
×
1187
            c = modColor.cyan();
×
1188
            m = modColor.magenta();
×
1189
            y = modColor.yellow();
×
1190
        }
1191
    }
1192

1193
    if (m_levelValueChanged)
×
1194
    {
1195
        QListIterator <LevelChannel> it(m_levelChannels);
×
1196
        while (it.hasNext() == true)
×
1197
        {
1198
            LevelChannel lch(it.next());
×
1199
            Fixture *fxi = m_doc->fixture(lch.fixture);
×
1200
            if (fxi == NULL)
×
1201
                continue;
×
1202

1203
            quint32 universe = fxi->universe();
×
1204

1205
            QSharedPointer<GenericFader> fader = m_fadersMap.value(universe, QSharedPointer<GenericFader>());
×
1206
            if (fader.isNull())
×
1207
            {
1208
                fader = universes[universe]->requestFader(m_monitorEnabled ? Universe::Override : Universe::Auto);
×
1209
                fader->adjustIntensity(intensity());
×
1210
                m_fadersMap[universe] = fader;
×
1211
                if (m_monitorEnabled)
×
1212
                {
1213
                    qDebug() << "VC slider monitor enabled";
×
1214
                    fader->setMonitoring(true);
×
1215
                    connect(fader.data(), SIGNAL(preWriteData(quint32,QByteArray)),
×
1216
                            this, SLOT(slotUniverseWritten(quint32,QByteArray)));
1217
                }
1218
            }
1219

1220
            FadeChannel *fc = fader->getChannelFader(m_doc, universes[universe], lch.fixture, lch.channel);
×
1221
            if (fc->universe() == Universe::invalid())
×
1222
            {
1223
                fader->remove(fc);
×
1224
                continue;
×
1225
            }
1226

1227
            int chType = fc->flags();
×
1228
            const QLCChannel *qlcch = fxi->channel(lch.channel);
×
1229
            if (qlcch == NULL)
×
1230
                continue;
×
1231

1232
            // set override flag if needed
1233
            if (m_isOverriding)
×
1234
                fc->addFlag(FadeChannel::Override);
×
1235

1236
            // request to autoremove LTP channels when set
1237
            if (qlcch->group() != QLCChannel::Intensity)
×
1238
                fc->addFlag(FadeChannel::AutoRemove);
×
1239

1240
            if (chType & FadeChannel::Intensity)
×
1241
            {
1242
                if (m_cngType == ClickAndGoWidget::RGB)
×
1243
                {
1244
                    if (qlcch->colour() == QLCChannel::Red)
×
1245
                        modLevel = uchar(r);
×
1246
                    else if (qlcch->colour() == QLCChannel::Green)
×
1247
                        modLevel = uchar(g);
×
1248
                    else if (qlcch->colour() == QLCChannel::Blue)
×
1249
                        modLevel = uchar(b);
×
1250
                }
1251
                else if (m_cngType == ClickAndGoWidget::CMY)
×
1252
                {
1253
                    if (qlcch->colour() == QLCChannel::Cyan)
×
1254
                        modLevel = uchar(c);
×
1255
                    else if (qlcch->colour() == QLCChannel::Magenta)
×
1256
                        modLevel = uchar(m);
×
1257
                    else if (qlcch->colour() == QLCChannel::Yellow)
×
1258
                        modLevel = uchar(y);
×
1259
                }
1260
            }
1261

1262
            fc->setStart(fc->current());
×
1263
            fc->setTarget(modLevel);
×
1264
            fc->setReady(false);
×
1265
            fc->setElapsed(0);
×
1266

1267
            //qDebug() << "VC Slider write channel" << fc->target();
1268
        }
×
1269
    }
×
1270
    m_levelValueChanged = false;
×
1271
}
×
1272

1273
void VCSlider::writeDMXPlayback(MasterTimer* timer, QList<Universe *> ua)
×
1274
{
1275
    Q_UNUSED(ua);
1276

1277
    QMutexLocker locker(&m_playbackValueMutex);
×
1278

1279
    if (m_playbackChangeCounter == 0)
×
1280
        return;
×
1281

1282
    Function* function = m_doc->function(m_playbackFunction);
×
1283
    if (function == NULL || mode() == Doc::Design)
×
1284
        return;
×
1285

1286
    uchar value = m_playbackValue;
×
1287
    qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
1288

1289
    if (value == 0)
×
1290
    {
1291
        // Make sure we ignore the fade out time
1292
        if (function->stopped() == false)
×
1293
        {
1294
            function->stop(functionParent());
×
1295
            resetIntensityOverrideAttribute();
×
1296
        }
1297
    }
1298
    else
1299
    {
1300
        if (function->stopped() == true)
×
1301
        {
1302
#if 0 // temporarily revert #699 until a better solution is found
1303
            // Since this function is started by a fader, its fade in time
1304
            // is decided by the fader movement.
1305
            function->start(timer, functionParent(),
1306
                            0, 0, Function::defaultSpeed(), Function::defaultSpeed());
1307
#endif
1308
            function->start(timer, functionParent());
×
1309
        }
1310
        adjustFunctionIntensity(function, pIntensity * intensity());
×
1311
        emit functionStarting(m_playbackFunction, pIntensity);
×
1312
    }
1313
    m_playbackChangeCounter--;
×
1314
}
×
1315

1316
/*****************************************************************************
1317
 * Top label
1318
 *****************************************************************************/
1319

1320
void VCSlider::setTopLabelText(int value)
2✔
1321
{
1322
    QString text;
2✔
1323

1324
    if (valueDisplayStyle() == ExactValue)
2✔
1325
    {
1326
        text = text.asprintf("%.3d", value);
2✔
1327
    }
1328
    else
1329
    {
1330

1331
        float f = 0;
×
1332
        if (m_slider)
×
1333
            f = SCALE(float(value), float(m_slider->minimum()),
×
1334
                      float(m_slider->maximum()), float(0), float(100));
1335
        text = text.asprintf("%.3d%%", static_cast<int> (f));
×
1336
    }
1337
    m_topLabel->setText(text);
2✔
1338
    emit valueChanged(text);
2✔
1339
}
2✔
1340

1341
QString VCSlider::topLabelText() const
×
1342
{
1343
    return m_topLabel->text();
×
1344
}
1345

1346
/*****************************************************************************
1347
 * Slider
1348
 *****************************************************************************/
1349

1350
void VCSlider::setSliderValue(uchar value, bool scale, bool external)
×
1351
{
1352
    if (m_slider == NULL)
×
1353
        return;
×
1354

1355
    float val = value;
×
1356

1357
    /* Scale from input value range to this slider's range */
1358
    if (scale)
×
1359
    {
1360
        val = SCALE(float(value), float(0), float(UCHAR_MAX),
×
1361
                float(m_slider->minimum()),
1362
                float(m_slider->maximum()));
1363
    }
1364

1365
    /* Request the UI to update */
1366
    if (m_slider->isSliderDown() == false && val != m_slider->value())
×
1367
       emit requestSliderUpdate(val);
×
1368

1369
    switch (sliderMode())
×
1370
    {
1371
        case Level:
×
1372
        {
1373
            if (m_monitorEnabled == true && m_isOverriding == false && m_slider->isSliderDown())
×
1374
            {
1375
                if (m_resetButton != nullptr)
×
1376
                    m_resetButton->setStyleSheet(QString("QToolButton{ background: red; }"));
×
1377
                m_isOverriding = true;
×
1378
                updateOverrideFeedback(true);
×
1379
            }
1380
            setLevelValue(val, external);
×
1381
            setClickAndGoWidgetFromLevel(val);
×
1382
        }
1383
        break;
×
1384

1385
        case Playback:
×
1386
        {
1387
            setPlaybackValue(value);
×
1388
        }
1389
        break;
×
1390

1391
        case Submaster:
×
1392
        {
1393
            setLevelValue(val);
×
1394
            emitSubmasterValue();
×
1395
        }
1396
        break;
×
1397
    }
1398
}
1399

1400
void VCSlider::setSliderShadowValue(int value)
×
1401
{
1402
    if (m_widgetMode == WSlider)
×
1403
    {
1404
        ClickAndGoSlider *sl = qobject_cast<ClickAndGoSlider*> (m_slider);
×
1405
        if (sl != nullptr)
×
1406
            sl->setShadowLevel(value);
×
1407
    }
1408
}
×
1409

1410
int VCSlider::sliderValue() const
×
1411
{
1412
    if (m_slider)
×
1413
        return m_slider->value();
×
1414

1415
    return 0;
×
1416
}
1417

1418
void VCSlider::setWidgetStyle(SliderWidgetStyle mode)
×
1419
{
1420
    if (mode == m_widgetMode)
×
1421
        return;
×
1422

1423
    if (mode == WKnob)
×
1424
    {
1425
        qDebug() << "Switching to knob widget";
×
1426
        disconnect(m_slider, SIGNAL(valueChanged(int)),
×
1427
                this, SLOT(slotSliderMoved(int)));
1428

1429
        QLayoutItem* item;
1430
        while ((item = m_hbox->takeAt(0)) != NULL)
×
1431
        {
1432
            delete item->widget();
×
1433
            delete item;
×
1434
        }
1435

1436
        m_slider = NULL;
×
1437

1438
        m_slider = new KnobWidget(this);
×
1439
        m_slider->setEnabled(false);
×
1440
        m_slider->setRange(levelLowLimit(), levelHighLimit());
×
1441
        m_hbox->addWidget(m_slider);
×
1442
        m_slider->show();
×
1443
        connect(m_slider, SIGNAL(valueChanged(int)),
×
1444
                this, SLOT(slotSliderMoved(int)));
1445
    }
1446
    else if (mode == WSlider)
×
1447
    {
1448
        qDebug() << "Switching to slider widget";
×
1449
        disconnect(m_slider, SIGNAL(valueChanged(int)),
×
1450
                this, SLOT(slotSliderMoved(int)));
1451

1452
        QLayoutItem* item;
1453
        while ((item = m_hbox->takeAt(0)) != NULL)
×
1454
        {
1455
            delete item->widget();
×
1456
            delete item;
×
1457
        }
1458

1459
        m_slider = NULL;
×
1460
        m_hbox->addStretch();
×
1461
        m_slider = new ClickAndGoSlider(this);
×
1462
        m_slider->setEnabled(false);
×
1463
        m_slider->setRange(levelLowLimit(), levelHighLimit());
×
1464
        m_hbox->addWidget(m_slider);
×
1465
        m_slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
×
1466
        m_slider->setMinimumWidth(32);
×
1467
        m_slider->setMaximumWidth(80);
×
1468
        m_slider->setStyleSheet(CNG_DEFAULT_STYLE);
×
1469
        m_hbox->addStretch();
×
1470
        m_slider->show();
×
1471
        connect(m_slider, SIGNAL(valueChanged(int)),
×
1472
                this, SLOT(slotSliderMoved(int)));
1473
    }
1474
    connect(this, SIGNAL(requestSliderUpdate(int)),
×
1475
            m_slider, SLOT(setValue(int)));
×
1476
    m_widgetMode = mode;
×
1477
    update();
×
1478
}
1479

1480
VCSlider::SliderWidgetStyle VCSlider::widgetStyle() const
×
1481
{
1482
    return m_widgetMode;
×
1483
}
1484

1485
QString VCSlider::widgetStyleToString(VCSlider::SliderWidgetStyle style)
×
1486
{
1487
    if (style == VCSlider::WSlider)
×
1488
        return QString("Slider");
×
1489
    else if (style == VCSlider::WKnob)
×
1490
        return QString("Knob");
×
1491

1492
    return QString();
×
1493
}
1494

1495
VCSlider::SliderWidgetStyle VCSlider::stringToWidgetStyle(QString style)
×
1496
{
1497
    if (style == "Slider")
×
1498
        return VCSlider::WSlider;
×
1499
    else if (style == "Knob")
×
1500
        return VCSlider::WKnob;
×
1501

1502
    return VCSlider::WSlider;
×
1503
}
1504

1505
void VCSlider::updateFeedback()
×
1506
{
1507
    int fbv = 0;
×
1508
    if (m_slider)
×
1509
    {
1510
        if (invertedAppearance() == true)
×
1511
            fbv = m_slider->maximum() - m_slider->value() + m_slider->minimum();
×
1512
        else
1513
            fbv = m_slider->value();
×
1514
        fbv = int(SCALE(float(fbv), float(m_slider->minimum()),
×
1515
                        float(m_slider->maximum()), float(0), float(UCHAR_MAX)));
1516
    }
1517
    sendFeedback(fbv);
×
1518
}
×
1519

1520
void VCSlider::updateOverrideFeedback(bool on)
×
1521
{
1522
    QSharedPointer<QLCInputSource> src = inputSource(overrideResetInputSourceId);
×
1523
    if (!src.isNull() && src->isValid() == true)
×
1524
        sendFeedback(src->feedbackValue(on ? QLCInputFeedback::UpperValue : QLCInputFeedback::LowerValue), overrideResetInputSourceId);
×
1525
}
×
1526

1527
void VCSlider::slotSliderMoved(int value)
2✔
1528
{
1529
    /* Set text for the top label */
1530
    setTopLabelText(value);
2✔
1531

1532
    /* Do the rest only if the slider is being moved by the user */
1533
    if (m_slider->isSliderDown() == false)
2✔
1534
        return;
2✔
1535

1536
    setSliderValue(value, false);
×
1537

1538
    updateFeedback();
×
1539
}
1540

1541
/*****************************************************************************
1542
 * Bottom label
1543
 *****************************************************************************/
1544
void VCSlider::setBottomLabelText(const QString& text)
×
1545
{
1546
    m_bottomLabel->setText(text);
×
1547
}
×
1548

1549
QString VCSlider::bottomLabelText() const
×
1550
{
1551
    return m_bottomLabel->text();
×
1552
}
1553

1554
/*****************************************************************************
1555
 * External input
1556
 *****************************************************************************/
1557

1558
void VCSlider::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
1559
{
1560
    /* Don't let input data through in design mode or if disabled */
1561
    if (acceptsInput() == false)
×
1562
        return;
×
1563

1564
    quint32 pagedCh = (page() << 16) | channel;
×
1565

1566
    if (checkInputSource(universe, pagedCh, value, sender(), sliderInputSourceId))
×
1567
    {
1568
        if (m_slider)
×
1569
        {
1570
            /* When 'values catching" is enabled, controllers that do not have motorized faders
1571
             * can catch up with the current slider value by entering a certain threshold
1572
             * or by 'surpassing' the current value */
1573
            if (catchValues())
×
1574
            {
1575
                uchar currentValue = sliderValue();
×
1576

1577
                // filter 'out of threshold' cases
1578
                if (m_lastInputValue == -1 ||
×
1579
                    (m_lastInputValue < currentValue - VALUE_CATCHING_THRESHOLD && value < currentValue - VALUE_CATCHING_THRESHOLD) ||
×
1580
                    (m_lastInputValue > currentValue + VALUE_CATCHING_THRESHOLD && value > currentValue + VALUE_CATCHING_THRESHOLD))
×
1581
                {
1582
                    m_lastInputValue = value;
×
1583
                    return;
×
1584
                }
1585
            }
1586

1587
            if (m_monitorEnabled == true && m_isOverriding == false)
×
1588
            {
1589
                m_resetButton->setStyleSheet(QString("QToolButton{ background: red; }"));
×
1590
                m_isOverriding = true;
×
1591
                updateOverrideFeedback(true);
×
1592
            }
1593

1594
            if (invertedAppearance())
×
1595
                value = UCHAR_MAX - value;
×
1596

1597
            setSliderValue(value, true, true);
×
1598
            m_lastInputValue = value;
×
1599
        }
1600
    }
1601
    else if (checkInputSource(universe, pagedCh, value, sender(), overrideResetInputSourceId))
×
1602
    {
1603
        if (value > 0)
×
1604
            slotResetButtonClicked();
×
1605
    }
1606
    else if (checkInputSource(universe, pagedCh, value, sender(), flashButtonInputSourceId))
×
1607
    {
1608
        flashPlayback(value ? true : false);
×
1609
    }
1610
}
1611

1612
void VCSlider::adjustIntensity(qreal val)
×
1613
{
1614
    VCWidget::adjustIntensity(val);
×
1615

1616
    if (sliderMode() == Playback)
×
1617
    {
1618
        Function* function = m_doc->function(m_playbackFunction);
×
1619
        if (function == NULL || mode() == Doc::Design)
×
1620
            return;
×
1621

1622
        qreal pIntensity = qreal(m_playbackValue) / qreal(UCHAR_MAX);
×
1623
        adjustFunctionIntensity(function, pIntensity * intensity());
×
1624
    }
1625
    else if (sliderMode() == Level)
×
1626
    {
1627
        foreach (QSharedPointer<GenericFader> fader, m_fadersMap)
×
1628
        {
1629
            if (!fader.isNull())
×
1630
                fader->adjustIntensity(val);
×
1631
        }
×
1632
    }
1633
}
1634

1635
/*****************************************************************************
1636
 * Load & Save
1637
 *****************************************************************************/
1638

1639
bool VCSlider::loadXML(QXmlStreamReader &root)
1✔
1640
{
1641
    bool visible = false;
1✔
1642
    int x = 0;
1✔
1643
    int y = 0;
1✔
1644
    int w = 0;
1✔
1645
    int h = 0;
1✔
1646

1647
    SliderMode sliderMode = Playback;
1✔
1648
    QString str;
1✔
1649

1650
    if (root.name() != KXMLQLCVCSlider)
1✔
1651
    {
1652
        qWarning() << Q_FUNC_INFO << "Slider node not found";
×
1653
        return false;
×
1654
    }
1655

1656
    /* Widget commons */
1657
    loadXMLCommon(root);
1✔
1658

1659
    QXmlStreamAttributes attrs = root.attributes();
1✔
1660

1661
    /* Widget style */
1662
    if (attrs.hasAttribute(KXMLQLCVCSliderWidgetStyle))
1✔
1663
        setWidgetStyle(stringToWidgetStyle(attrs.value(KXMLQLCVCSliderWidgetStyle).toString()));
×
1664

1665
    if (attrs.value(KXMLQLCVCSliderInvertedAppearance).toString() == "false")
2✔
1666
        setInvertedAppearance(false);
×
1667
    else
1668
        setInvertedAppearance(true);
1✔
1669

1670
    /* Values catching */
1671
    if (attrs.hasAttribute(KXMLQLCVCSliderCatchValues))
1✔
1672
        setCatchValues(true);
×
1673

1674
    /* Children */
1675
    while (root.readNextStartElement())
1✔
1676
    {
1677
        //qDebug() << "VC Slider tag:" << root.name();
1678
        if (root.name() == KXMLQLCWindowState)
×
1679
        {
1680
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
1681
            setGeometry(x, y, w, h);
×
1682
        }
1683
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
1684
        {
1685
            loadXMLAppearance(root);
×
1686
        }
1687
        else if (root.name() == KXMLQLCVCSliderMode)
×
1688
        {
1689
            QXmlStreamAttributes mAttrs = root.attributes();
×
1690
            sliderMode = stringToSliderMode(root.readElementText());
×
1691

1692
            str = mAttrs.value(KXMLQLCVCSliderValueDisplayStyle).toString();
×
1693
            setValueDisplayStyle(stringToValueDisplayStyle(str));
×
1694

1695
            if (mAttrs.hasAttribute(KXMLQLCVCSliderClickAndGoType))
×
1696
            {
1697
                str = mAttrs.value(KXMLQLCVCSliderClickAndGoType).toString();
×
1698
                setClickAndGoType(ClickAndGoWidget::stringToClickAndGoType(str));
×
1699
            }
1700

1701
            if (mAttrs.hasAttribute(KXMLQLCVCSliderLevelMonitor))
×
1702
            {
1703
                if (mAttrs.value(KXMLQLCVCSliderLevelMonitor).toString() == "false")
×
1704
                    setChannelsMonitorEnabled(false);
×
1705
                else
1706
                    setChannelsMonitorEnabled(true);
×
1707
            }
1708
        }
×
1709
        else if (root.name() == KXMLQLCVCSliderOverrideReset)
×
1710
        {
1711
            QString str = loadXMLSources(root, overrideResetInputSourceId);
×
1712
            if (str.isEmpty() == false)
×
1713
                m_overrideResetKeySequence = stripKeySequence(QKeySequence(str));
×
1714
        }
×
1715
        else if (root.name() == KXMLQLCVCSliderLevel)
×
1716
        {
1717
            loadXMLLevel(root);
×
1718
        }
1719
        else if (root.name() == KXMLQLCVCWidgetInput)
×
1720
        {
1721
            loadXMLInput(root);
×
1722
        }
1723
        else if (root.name() == KXMLQLCVCSliderPlayback)
×
1724
        {
1725
            loadXMLPlayback(root);
×
1726
        }
1727
        else
1728
        {
1729
            qWarning() << Q_FUNC_INFO << "Unknown slider tag:" << root.name().toString();
×
1730
            root.skipCurrentElement();
×
1731
        }
1732
    }
1733

1734
    /* Set the mode last, after everything else has been set */
1735
    setSliderMode(sliderMode);
1✔
1736

1737
    return true;
1✔
1738
}
1✔
1739

1740
bool VCSlider::loadXMLLevel(QXmlStreamReader &level_root)
×
1741
{
1742
    QString str;
×
1743

1744
    if (level_root.name() != KXMLQLCVCSliderLevel)
×
1745
    {
1746
        qWarning() << Q_FUNC_INFO << "Slider level node not found";
×
1747
        return false;
×
1748
    }
1749

1750
    QXmlStreamAttributes attrs = level_root.attributes();
×
1751

1752
    /* Level low limit */
1753
    str = attrs.value(KXMLQLCVCSliderLevelLowLimit).toString();
×
1754
    setLevelLowLimit(str.toInt());
×
1755

1756
    /* Level high limit */
1757
    str = attrs.value(KXMLQLCVCSliderLevelHighLimit).toString();
×
1758
    setLevelHighLimit(str.toInt());
×
1759

1760
    /* Level value */
1761
    str = attrs.value(KXMLQLCVCSliderLevelValue).toString();
×
1762
    setLevelValue(str.toInt());
×
1763

1764
    QXmlStreamReader::TokenType tType = level_root.readNext();
×
1765

1766
    if (tType == QXmlStreamReader::EndElement)
×
1767
    {
1768
        level_root.readNext();
×
1769
        return true;
×
1770
    }
1771

1772
    if (tType == QXmlStreamReader::Characters)
×
1773
        tType = level_root.readNext();
×
1774

1775
    // check if there is a Channel tag defined
1776
    if (tType == QXmlStreamReader::StartElement)
×
1777
    {
1778
        /* Children */
1779
        do
1780
        {
1781
            if (level_root.name() == KXMLQLCVCSliderChannel)
×
1782
            {
1783
                /* Fixture & channel */
1784
                str = level_root.attributes().value(KXMLQLCVCSliderChannelFixture).toString();
×
1785
                addLevelChannel(
×
1786
                    static_cast<quint32>(str.toInt()),
×
1787
                    static_cast<quint32> (level_root.readElementText().toInt()));
×
1788
            }
1789
            else
1790
            {
1791
                qWarning() << Q_FUNC_INFO << "Unknown slider level tag:" << level_root.name().toString();
×
1792
                level_root.skipCurrentElement();
×
1793
            }
1794
        } while (level_root.readNextStartElement());
×
1795
    }
1796

1797
    return true;
×
1798
}
×
1799

1800
bool VCSlider::loadXMLPlayback(QXmlStreamReader &pb_root)
×
1801
{
1802
    if (pb_root.name() != KXMLQLCVCSliderPlayback)
×
1803
    {
1804
        qWarning() << Q_FUNC_INFO << "Slider playback node not found";
×
1805
        return false;
×
1806
    }
1807

1808
    /* Children */
1809
    while (pb_root.readNextStartElement())
×
1810
    {
1811
        if (pb_root.name() == KXMLQLCVCSliderPlaybackFunction)
×
1812
        {
1813
            /* Function */
1814
            setPlaybackFunction(pb_root.readElementText().toUInt());
×
1815
        }
1816
        else if (pb_root.name() == KXMLQLCVCSliderPlaybackFlash)
×
1817
        {
1818
            setPlaybackFlashEnable(true);
×
1819
            QString str = loadXMLSources(pb_root, flashButtonInputSourceId);
×
1820
            if (str.isEmpty() == false)
×
1821
                m_playbackFlashKeySequence = stripKeySequence(QKeySequence(str));
×
1822
        }
×
1823
        else
1824
        {
1825
            qWarning() << Q_FUNC_INFO << "Unknown slider playback tag:" << pb_root.name().toString();
×
1826
            pb_root.skipCurrentElement();
×
1827
        }
1828
    }
1829

1830
    return true;
×
1831
}
1832

1833
bool VCSlider::saveXML(QXmlStreamWriter *doc)
×
1834
{
1835
    QString str;
×
1836

1837
    Q_ASSERT(doc != NULL);
×
1838

1839
    /* VC Slider entry */
1840
    doc->writeStartElement(KXMLQLCVCSlider);
×
1841

1842
    saveXMLCommon(doc);
×
1843

1844
    /* Widget style */
1845
    doc->writeAttribute(KXMLQLCVCSliderWidgetStyle, widgetStyleToString(widgetStyle()));
×
1846

1847
    /* Inverted appearance */
1848
    if (invertedAppearance() == true)
×
1849
        doc->writeAttribute(KXMLQLCVCSliderInvertedAppearance, "true");
×
1850
    else
1851
        doc->writeAttribute(KXMLQLCVCSliderInvertedAppearance, "false");
×
1852

1853
    /* Values catching */
1854
    if (catchValues() == true)
×
1855
        doc->writeAttribute(KXMLQLCVCSliderCatchValues, "true");
×
1856

1857
    /* Window state */
1858
    saveXMLWindowState(doc);
×
1859

1860
    /* Appearance */
1861
    saveXMLAppearance(doc);
×
1862

1863
    /* External input */
1864
    saveXMLInput(doc, inputSource(sliderInputSourceId));
×
1865

1866
    /* SliderMode */
1867
    doc->writeStartElement(KXMLQLCVCSliderMode);
×
1868

1869
    /* Value display style */
1870
    str = valueDisplayStyleToString(valueDisplayStyle());
×
1871
    doc->writeAttribute(KXMLQLCVCSliderValueDisplayStyle, str);
×
1872

1873
    /* Click And Go type */
1874
    str = ClickAndGoWidget::clickAndGoTypeToString(m_cngType);
×
1875
    doc->writeAttribute(KXMLQLCVCSliderClickAndGoType, str);
×
1876

1877
    /* Monitor channels */
1878
    if (sliderMode() == Level)
×
1879
    {
1880
        if (channelsMonitorEnabled() == true)
×
1881
            doc->writeAttribute(KXMLQLCVCSliderLevelMonitor, "true");
×
1882
        else
1883
            doc->writeAttribute(KXMLQLCVCSliderLevelMonitor, "false");
×
1884
    }
1885

1886
    doc->writeCharacters(sliderModeToString(m_sliderMode));
×
1887

1888
    /* End the <SliderMode> tag */
1889
    doc->writeEndElement();
×
1890

1891
    if (sliderMode() == Level && channelsMonitorEnabled() == true)
×
1892
    {
1893
        doc->writeStartElement(KXMLQLCVCSliderOverrideReset);
×
1894
        if (m_overrideResetKeySequence.toString().isEmpty() == false)
×
1895
            doc->writeTextElement(KXMLQLCVCWidgetKey, m_overrideResetKeySequence.toString());
×
1896
        saveXMLInput(doc, inputSource(overrideResetInputSourceId));
×
1897
        doc->writeEndElement();
×
1898
    }
1899

1900
    /* Level */
1901
    doc->writeStartElement(KXMLQLCVCSliderLevel);
×
1902
    /* Level low limit */
1903
    doc->writeAttribute(KXMLQLCVCSliderLevelLowLimit, QString::number(levelLowLimit()));
×
1904
    /* Level high limit */
1905
    doc->writeAttribute(KXMLQLCVCSliderLevelHighLimit, QString::number(levelHighLimit()));
×
1906
    /* Level value */
1907
    doc->writeAttribute(KXMLQLCVCSliderLevelValue, QString::number(levelValue()));
×
1908

1909
    /* Level channels */
1910
    QListIterator <LevelChannel> it(m_levelChannels);
×
1911
    while (it.hasNext() == true)
×
1912
    {
1913
        LevelChannel lch(it.next());
×
1914
        lch.saveXML(doc);
×
1915
    }
1916

1917
    /* End the <Level> tag */
1918
    doc->writeEndElement();
×
1919

1920
    /* Playback */
1921
    doc->writeStartElement(KXMLQLCVCSliderPlayback);
×
1922
    /* Playback function */
1923
    doc->writeTextElement(KXMLQLCVCSliderPlaybackFunction, QString::number(playbackFunction()));
×
1924

1925
    if (sliderMode() == Playback && playbackFlashEnable() == true)
×
1926
    {
1927
        doc->writeStartElement(KXMLQLCVCSliderPlaybackFlash);
×
1928
        if (m_playbackFlashKeySequence.toString().isEmpty() == false)
×
1929
            doc->writeTextElement(KXMLQLCVCWidgetKey, m_playbackFlashKeySequence.toString());
×
1930
        saveXMLInput(doc, inputSource(flashButtonInputSourceId));
×
1931
        doc->writeEndElement();
×
1932
    }
1933

1934
    /* End the <Playback> tag */
1935
    doc->writeEndElement();
×
1936

1937
    /* End the <Slider> tag */
1938
    doc->writeEndElement();
×
1939

1940
    return true;
×
1941
}
×
1942

1943
/****************************************************************************
1944
 * LevelChannel implementation
1945
 ****************************************************************************/
1946

1947
VCSlider::LevelChannel::LevelChannel(quint32 fid, quint32 ch)
×
1948
{
1949
    this->fixture = fid;
×
1950
    this->channel = ch;
×
1951
}
×
1952

1953
VCSlider::LevelChannel::LevelChannel(const LevelChannel& lc)
×
1954
{
1955
    *this = lc;
×
1956
}
×
1957

1958
VCSlider::LevelChannel &VCSlider::LevelChannel::operator=(const VCSlider::LevelChannel &lc)
×
1959
{
1960
    if (this != &lc)
×
1961
    {
1962
        this->fixture = lc.fixture;
×
1963
        this->channel = lc.channel;
×
1964
    }
1965

1966
    return *this;
×
1967
}
1968

1969
bool VCSlider::LevelChannel::operator==(const LevelChannel& lc) const
×
1970
{
1971
    return (this->fixture == lc.fixture && this->channel == lc.channel);
×
1972
}
1973

1974
bool VCSlider::LevelChannel::operator<(const LevelChannel& lc) const
×
1975
{
1976
    if (this->fixture < lc.fixture)
×
1977
        return true;
×
1978
    else if (this->fixture == lc.fixture && this->channel < lc.channel)
×
1979
        return true;
×
1980
    else
1981
        return false;
×
1982
}
1983

1984
void VCSlider::LevelChannel::saveXML(QXmlStreamWriter *doc) const
×
1985
{
1986
    Q_ASSERT(doc != NULL);
×
1987

1988
    doc->writeStartElement(KXMLQLCVCSliderChannel);
×
1989

1990
    doc->writeAttribute(KXMLQLCVCSliderChannelFixture,
×
1991
                       QString::number(this->fixture));
×
1992

1993
    doc->writeCharacters(QString::number(this->channel));
×
1994
    doc->writeEndElement();
×
1995
}
×
1996

1997
void VCSlider::FlashButton::mousePressEvent(QMouseEvent *e)
×
1998
{
1999
    QToolButton::mousePressEvent(e);
×
2000
    // ignore event so that it can be
2001
    // forwarded to parent widget
2002
    e->ignore();
×
2003
}
×
2004

2005
void VCSlider::FlashButton::mouseReleaseEvent(QMouseEvent *e)
×
2006
{
2007
    QToolButton::mouseReleaseEvent(e);
×
2008
    // ignore event so that it can be
2009
    // forwarded to parent widget
2010
    e->ignore();
×
2011
}
×
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