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

mcallegari / qlcplus / 19409821768

16 Nov 2025 06:06PM UTC coverage: 34.233% (-0.01%) from 34.243%
19409821768

push

github

mcallegari
vc/soloframe: add an option to exclude functions monitored by buttons to be stopped

3 of 38 new or added lines in 9 files covered. (7.89%)

2 existing lines in 2 files now uncovered.

17724 of 51774 relevant lines covered (34.23%)

19630.45 hits per line

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

17.3
/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)
×
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_cngButton->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
    m_resetButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
876
                                 .arg(m_slider->palette().window().color().name()));
×
877

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

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

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

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

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

906
/*********************************************************************
907
 * Flash button
908
 *********************************************************************/
909

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

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

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

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

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

943
/*****************************************************************************
944
 * Playback
945
 *****************************************************************************/
946

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1129
/*********************************************************************
1130
 * Submaster
1131
 *********************************************************************/
1132

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

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

1141
/*****************************************************************************
1142
 * DMXSource
1143
 *****************************************************************************/
1144

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

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

1157
    QMutexLocker locker(&m_levelValueMutex);
×
1158

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1276
    QMutexLocker locker(&m_playbackValueMutex);
×
1277

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

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

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

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

1315
/*****************************************************************************
1316
 * Top label
1317
 *****************************************************************************/
1318

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

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

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

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

1345
/*****************************************************************************
1346
 * Slider
1347
 *****************************************************************************/
1348

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

1354
    float val = value;
×
1355

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

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

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

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

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

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

1407
int VCSlider::sliderValue() const
×
1408
{
1409
    if (m_slider)
×
1410
        return m_slider->value();
×
1411

1412
    return 0;
×
1413
}
1414

1415
void VCSlider::setWidgetStyle(SliderWidgetStyle mode)
×
1416
{
1417
    if (mode == m_widgetMode)
×
1418
        return;
×
1419

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

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

1433
        m_slider = NULL;
×
1434

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

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

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

1477
VCSlider::SliderWidgetStyle VCSlider::widgetStyle() const
×
1478
{
1479
    return m_widgetMode;
×
1480
}
1481

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

1489
    return QString();
×
1490
}
1491

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

1499
    return VCSlider::WSlider;
×
1500
}
1501

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

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

1524
void VCSlider::slotSliderMoved(int value)
2✔
1525
{
1526
    /* Set text for the top label */
1527
    setTopLabelText(value);
2✔
1528

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

1533
    setSliderValue(value, false);
×
1534

1535
    updateFeedback();
×
1536
}
1537

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

1546
QString VCSlider::bottomLabelText()
×
1547
{
1548
    return m_bottomLabel->text();
×
1549
}
1550

1551
/*****************************************************************************
1552
 * External input
1553
 *****************************************************************************/
1554

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

1561
    quint32 pagedCh = (page() << 16) | channel;
×
1562

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

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

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

1591
            if (invertedAppearance())
×
1592
                value = UCHAR_MAX - value;
×
1593

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

1609
void VCSlider::adjustIntensity(qreal val)
×
1610
{
1611
    VCWidget::adjustIntensity(val);
×
1612

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

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

1632
/*****************************************************************************
1633
 * Load & Save
1634
 *****************************************************************************/
1635

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

1644
    SliderMode sliderMode = Playback;
1✔
1645
    QString str;
1✔
1646

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

1653
    /* Widget commons */
1654
    loadXMLCommon(root);
1✔
1655

1656
    QXmlStreamAttributes attrs = root.attributes();
1✔
1657

1658
    /* Widget style */
1659
    if (attrs.hasAttribute(KXMLQLCVCSliderWidgetStyle))
1✔
1660
        setWidgetStyle(stringToWidgetStyle(attrs.value(KXMLQLCVCSliderWidgetStyle).toString()));
×
1661

1662
    if (attrs.value(KXMLQLCVCSliderInvertedAppearance).toString() == "false")
2✔
1663
        setInvertedAppearance(false);
×
1664
    else
1665
        setInvertedAppearance(true);
1✔
1666

1667
    /* Values catching */
1668
    if (attrs.hasAttribute(KXMLQLCVCSliderCatchValues))
1✔
1669
        setCatchValues(true);
×
1670

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

1689
            str = mAttrs.value(KXMLQLCVCSliderValueDisplayStyle).toString();
×
1690
            setValueDisplayStyle(stringToValueDisplayStyle(str));
×
1691

1692
            if (mAttrs.hasAttribute(KXMLQLCVCSliderClickAndGoType))
×
1693
            {
1694
                str = mAttrs.value(KXMLQLCVCSliderClickAndGoType).toString();
×
1695
                setClickAndGoType(ClickAndGoWidget::stringToClickAndGoType(str));
×
1696
            }
1697

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

1731
    /* Set the mode last, after everything else has been set */
1732
    setSliderMode(sliderMode);
1✔
1733

1734
    return true;
1✔
1735
}
1✔
1736

1737
bool VCSlider::loadXMLLevel(QXmlStreamReader &level_root)
×
1738
{
1739
    QString str;
×
1740

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

1747
    QXmlStreamAttributes attrs = level_root.attributes();
×
1748

1749
    /* Level low limit */
1750
    str = attrs.value(KXMLQLCVCSliderLevelLowLimit).toString();
×
1751
    setLevelLowLimit(str.toInt());
×
1752

1753
    /* Level high limit */
1754
    str = attrs.value(KXMLQLCVCSliderLevelHighLimit).toString();
×
1755
    setLevelHighLimit(str.toInt());
×
1756

1757
    /* Level value */
1758
    str = attrs.value(KXMLQLCVCSliderLevelValue).toString();
×
1759
    setLevelValue(str.toInt());
×
1760

1761
    QXmlStreamReader::TokenType tType = level_root.readNext();
×
1762

1763
    if (tType == QXmlStreamReader::EndElement)
×
1764
    {
1765
        level_root.readNext();
×
1766
        return true;
×
1767
    }
1768

1769
    if (tType == QXmlStreamReader::Characters)
×
1770
        tType = level_root.readNext();
×
1771

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

1794
    return true;
×
1795
}
×
1796

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

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

1827
    return true;
×
1828
}
1829

1830
bool VCSlider::saveXML(QXmlStreamWriter *doc)
×
1831
{
1832
    QString str;
×
1833

1834
    Q_ASSERT(doc != NULL);
×
1835

1836
    /* VC Slider entry */
1837
    doc->writeStartElement(KXMLQLCVCSlider);
×
1838

1839
    saveXMLCommon(doc);
×
1840

1841
    /* Widget style */
1842
    doc->writeAttribute(KXMLQLCVCSliderWidgetStyle, widgetStyleToString(widgetStyle()));
×
1843

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

1850
    /* Values catching */
1851
    if (catchValues() == true)
×
1852
        doc->writeAttribute(KXMLQLCVCSliderCatchValues, "true");
×
1853

1854
    /* Window state */
1855
    saveXMLWindowState(doc);
×
1856

1857
    /* Appearance */
1858
    saveXMLAppearance(doc);
×
1859

1860
    /* External input */
1861
    saveXMLInput(doc, inputSource(sliderInputSourceId));
×
1862

1863
    /* SliderMode */
1864
    doc->writeStartElement(KXMLQLCVCSliderMode);
×
1865

1866
    /* Value display style */
1867
    str = valueDisplayStyleToString(valueDisplayStyle());
×
1868
    doc->writeAttribute(KXMLQLCVCSliderValueDisplayStyle, str);
×
1869

1870
    /* Click And Go type */
1871
    str = ClickAndGoWidget::clickAndGoTypeToString(m_cngType);
×
1872
    doc->writeAttribute(KXMLQLCVCSliderClickAndGoType, str);
×
1873

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

1883
    doc->writeCharacters(sliderModeToString(m_sliderMode));
×
1884

1885
    /* End the <SliderMode> tag */
1886
    doc->writeEndElement();
×
1887

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

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

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

1914
    /* End the <Level> tag */
1915
    doc->writeEndElement();
×
1916

1917
    /* Playback */
1918
    doc->writeStartElement(KXMLQLCVCSliderPlayback);
×
1919
    /* Playback function */
1920
    doc->writeTextElement(KXMLQLCVCSliderPlaybackFunction, QString::number(playbackFunction()));
×
1921

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

1931
    /* End the <Playback> tag */
1932
    doc->writeEndElement();
×
1933

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

1937
    return true;
×
1938
}
×
1939

1940
/****************************************************************************
1941
 * LevelChannel implementation
1942
 ****************************************************************************/
1943

1944
VCSlider::LevelChannel::LevelChannel(quint32 fid, quint32 ch)
×
1945
{
1946
    this->fixture = fid;
×
1947
    this->channel = ch;
×
1948
}
×
1949

1950
VCSlider::LevelChannel::LevelChannel(const LevelChannel& lc)
×
1951
{
1952
    *this = lc;
×
1953
}
×
1954

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

1963
    return *this;
×
1964
}
1965

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

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

1981
void VCSlider::LevelChannel::saveXML(QXmlStreamWriter *doc) const
×
1982
{
1983
    Q_ASSERT(doc != NULL);
×
1984

1985
    doc->writeStartElement(KXMLQLCVCSliderChannel);
×
1986

1987
    doc->writeAttribute(KXMLQLCVCSliderChannelFixture,
×
1988
                       QString::number(this->fixture));
×
1989

1990
    doc->writeCharacters(QString::number(this->channel));
×
1991
    doc->writeEndElement();
×
1992
}
×
1993

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

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