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

mcallegari / qlcplus / 9044680734

11 May 2024 03:24PM UTC coverage: 32.011% (-0.05%) from 32.065%
9044680734

push

github

mcallegari
vc/slider: add an optional button to flash in playback mode (fix #1524)

2 of 96 new or added lines in 2 files covered. (2.08%)

4 existing lines in 2 files now uncovered.

15397 of 48099 relevant lines covered (32.01%)

22906.25 hits per line

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

16.09
/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)
88
    , m_catchValues(false)
89
    , m_levelLowLimit(0)
90
    , m_levelHighLimit(UCHAR_MAX)
91
    , m_levelValueChanged(false)
92
    , m_levelValue(0)
93
    , m_monitorEnabled(false)
94
    , m_monitorValue(0)
95
    , m_playbackFunction(Function::invalidId())
2✔
96
    , m_playbackValue(0)
97
    , m_playbackChangeCounter(0)
98
    , m_playbackFlashEnable(false)
99
    , m_playbackIsFlashing(false)
100
    , m_externalMovement(false)
101
    , m_widgetMode(WSlider)
102
    , m_cngType(ClickAndGoWidget::None)
103
    , m_isOverriding(false)
104
    , m_lastInputValue(-1)
1✔
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;
2✔
191
    QVariant var = settings.value(SETTINGS_SLIDER_SIZE);
2✔
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.values())
2✔
221
    {
222
        if (!fader.isNull())
×
223
            fader->requestDelete();
×
224
    }
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 common stuff */
286
    return VCWidget::copyFrom(widget);
×
287
}
288

289
/*****************************************************************************
290
 * GUI
291
 *****************************************************************************/
292

293
void VCSlider::setCaption(const QString& text)
1✔
294
{
295
    VCWidget::setCaption(text);
1✔
296

297
    if (m_bottomLabel != NULL)
1✔
298
        setBottomLabelText(text);
×
299
}
1✔
300

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

316
void VCSlider::hideEvent(QHideEvent *)
×
317
{
318
    m_lastInputValue = -1;
×
319
}
×
320

321
/*****************************************************************************
322
 * Properties
323
 *****************************************************************************/
324

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

338
/*****************************************************************************
339
 * QLC Mode
340
 *****************************************************************************/
341

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

370
    VCWidget::slotModeChanged(mode);
1✔
371
}
1✔
372

373
/*****************************************************************************
374
 * Value display style
375
 *****************************************************************************/
376

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

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

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

407
VCSlider::ValueDisplayStyle VCSlider::valueDisplayStyle() const
2✔
408
{
409
    return m_valueDisplayStyle;
2✔
410
}
411

412
/*****************************************************************************
413
 * Inverted appearance
414
 *****************************************************************************/
415

416
bool VCSlider::invertedAppearance() const
×
417
{
418
    if (m_slider)
×
419
        return m_slider->invertedAppearance();
×
420

421
    return false;
×
422
}
423

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

433
/*********************************************************************
434
 * Value catching feature
435
 *********************************************************************/
436

437
bool VCSlider::catchValues() const
×
438
{
439
    return m_catchValues;
×
440
}
441

442
void VCSlider::setCatchValues(bool enable)
×
443
{
444
    if (enable == m_catchValues)
×
445
        return;
×
446

447
    m_catchValues = enable;
×
448
}
449

450
/*****************************************************************************
451
 * Slider Mode
452
 *****************************************************************************/
453

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

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

475
VCSlider::SliderMode VCSlider::sliderMode() const
×
476
{
477
    return m_sliderMode;
×
478
}
479

480
void VCSlider::setSliderMode(SliderMode mode)
2✔
481
{
482
    Q_ASSERT(mode >= Level && mode <= Submaster);
2✔
483

484
    m_sliderMode = mode;
2✔
485

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

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

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

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

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

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

547
/*****************************************************************************
548
 * Level
549
 *****************************************************************************/
550

551
void VCSlider::addLevelChannel(quint32 fixture, quint32 channel)
×
552
{
553
    LevelChannel lch(fixture, channel);
×
554

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

562
void VCSlider::removeLevelChannel(quint32 fixture, quint32 channel)
×
563
{
564
    LevelChannel lch(fixture, channel);
×
565
    m_levelChannels.removeAll(lch);
×
566
}
×
567

568
void VCSlider::clearLevelChannels()
×
569
{
570
    m_levelChannels.clear();
×
571
}
×
572

573
QList <VCSlider::LevelChannel> VCSlider::levelChannels()
×
574
{
575
    return m_levelChannels;
×
576
}
577

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

585
uchar VCSlider::levelLowLimit() const
×
586
{
587
    return m_levelLowLimit;
×
588
}
589

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

597
uchar VCSlider::levelHighLimit() const
×
598
{
599
    return m_levelHighLimit;
×
600
}
601

602
void VCSlider::setChannelsMonitorEnabled(bool enable)
×
603
{
604
    m_monitorEnabled = enable;
×
605

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

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

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

636
bool VCSlider::channelsMonitorEnabled() const
×
637
{
638
    return m_monitorEnabled;
×
639
}
640

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

651
uchar VCSlider::levelValue() const
×
652
{
653
    return m_levelValue;
×
654
}
655

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

667
void VCSlider::slotMonitorDMXValueChanged(int value)
×
668
{
669
    if (value == sliderValue())
×
670
        return;
×
671

672
    m_monitorValue = value;
×
673

674
    if (m_isOverriding == false)
×
675
    {
676
        {
677
            QMutexLocker locker(&m_levelValueMutex);
×
678
            m_levelValue = m_monitorValue;
×
679
        }
680

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

692
void VCSlider::slotUniverseWritten(quint32 idx, const QByteArray &universeData)
×
693
{
694
    if (m_levelValueChanged)
×
695
        return;
×
696

697
    bool mixedDMXlevels = false;
×
698
    int monitorSliderValue = -1;
×
699
    QListIterator <LevelChannel> it(m_levelChannels);
×
700

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

708
        if (lch.channel >= fxi->channels() ||
×
709
            fxi->address() + lch.channel >= (quint32)universeData.length())
×
710
            continue;
×
711

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

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

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

748
/*********************************************************************
749
 * Click & Go
750
 *********************************************************************/
751

752
void VCSlider::setClickAndGoType(ClickAndGoWidget::ClickAndGo type)
×
753
{
754
    m_cngType = type;
×
755
}
×
756

757
ClickAndGoWidget::ClickAndGo VCSlider::clickAndGoType() const
×
758
{
759
    return m_cngType;
×
760
}
761

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

784
ClickAndGoWidget *VCSlider::getClickAndGoWidget()
×
785
{
786
    return m_cngWidget;
×
787
}
788

789
void VCSlider::setClickAndGoWidgetFromLevel(uchar level)
×
790
{
791
    if (m_cngType == ClickAndGoWidget::None || m_cngWidget == NULL)
×
792
        return;
×
793

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

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

817
void VCSlider::slotClickAndGoLevelChanged(uchar level)
×
818
{
819
    setSliderValue(level, false, false);
×
820
    updateFeedback();
×
821

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

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

837
    // place the slider half way to reach white@255 and black@0
838
    setSliderValue(128);
×
839
    updateFeedback();
×
840

841
    // let's force a value change to cover all the HTP/LTP cases
842
    m_levelValueChanged = true;
×
843
}
×
844

845
void VCSlider::slotClickAndGoLevelAndPresetChanged(uchar level, QImage img)
×
846
{
847
    setSliderValue(level, false, false);
×
848
    updateFeedback();
×
849

850
    QPixmap px = QPixmap::fromImage(img);
×
851
    m_cngButton->setIcon(px);
×
852
    m_levelValueChanged = true;
×
853
}
×
854

855
/*********************************************************************
856
 * Override reset button
857
 *********************************************************************/
858

859
void VCSlider::setOverrideResetKeySequence(const QKeySequence &keySequence)
×
860
{
861
    m_overrideResetKeySequence = QKeySequence(keySequence);
×
862
}
×
863

864
QKeySequence VCSlider::overrideResetKeySequence() const
×
865
{
866
    return m_overrideResetKeySequence;
×
867
}
868

869
void VCSlider::slotResetButtonClicked()
×
870
{
871
    m_isOverriding = false;
×
872
    m_resetButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
873
                                 .arg(m_slider->palette().window().color().name()));
×
874

875
    // request to delete all the active fader channels
876
    foreach (QSharedPointer<GenericFader> fader, m_fadersMap.values())
×
877
    {
878
        if (!fader.isNull())
×
879
            fader->removeAll();
×
880
    }
881

882
    emit monitorDMXValueChanged(m_monitorValue);
×
883
}
×
884

885
void VCSlider::slotKeyPressed(const QKeySequence &keySequence)
×
886
{
887
    if (isEnabled() == false)
×
888
        return;
×
889

890
    if (m_overrideResetKeySequence == keySequence)
×
891
        slotResetButtonClicked();
×
NEW
892
    else if (m_playbackFlashKeySequence == keySequence)
×
NEW
893
        flashPlayback(true);
×
894
}
895

NEW
896
void VCSlider::slotKeyReleased(const QKeySequence &keySequence)
×
897
{
NEW
898
    if (m_playbackFlashKeySequence == keySequence && m_playbackIsFlashing)
×
NEW
899
        flashPlayback(false);
×
NEW
900
}
×
901

902
/*********************************************************************
903
 * Flash button
904
 *********************************************************************/
905

NEW
906
QKeySequence VCSlider::playbackFlashKeySequence() const
×
907
{
NEW
908
    return m_playbackFlashKeySequence;
×
909
}
910

NEW
911
void VCSlider::setPlaybackFlashKeySequence(const QKeySequence &keySequence)
×
912
{
NEW
913
    m_playbackFlashKeySequence = QKeySequence(keySequence);
×
NEW
914
}
×
915

NEW
916
void VCSlider::mousePressEvent(QMouseEvent *e)
×
917
{
NEW
918
    VCWidget::mousePressEvent(e);
×
919

NEW
920
    if (mode() != Doc::Design && e->button() == Qt::LeftButton &&
×
NEW
921
        m_flashButton && m_flashButton->isDown())
×
922
    {
NEW
923
        flashPlayback(true);
×
924
    }
NEW
925
}
×
926

NEW
927
void VCSlider::mouseReleaseEvent(QMouseEvent *e)
×
928
{
NEW
929
    if (mode() == Doc::Design)
×
930
    {
NEW
931
        VCWidget::mouseReleaseEvent(e);
×
932
    }
NEW
933
    else if (m_playbackIsFlashing)
×
934
    {
NEW
935
        flashPlayback(false);
×
936
    }
UNCOV
937
}
×
938

939
/*****************************************************************************
940
 * Playback
941
 *****************************************************************************/
942

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

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

978
        m_playbackFunction = fid;
×
979
    }
980
    else
981
    {
982
        /* No function attachment */
983
        m_playbackFunction = Function::invalidId();
2✔
984
    }
985
}
2✔
986

987
quint32 VCSlider::playbackFunction() const
×
988
{
989
    return m_playbackFunction;
×
990
}
991

992
void VCSlider::setPlaybackValue(uchar value)
×
993
{
994
    if (m_externalMovement == true || value == m_playbackValue)
×
995
        return;
×
996

997
    QMutexLocker locker(&m_playbackValueMutex);
×
998
    m_playbackValue = value;
×
999
    m_playbackChangeCounter = 5;
×
1000
}
1001

1002
uchar VCSlider::playbackValue() const
2✔
1003
{
1004
    return m_playbackValue;
2✔
1005
}
1006

1007
void VCSlider::notifyFunctionStarting(quint32 fid, qreal functionIntensity)
×
1008
{
1009
    if (mode() == Doc::Design || sliderMode() != Playback)
×
1010
        return;
×
1011

1012
    if (fid == playbackFunction())
×
1013
        return;
×
1014

1015
    if (m_slider != NULL)
×
1016
    {
1017
        int value = SCALE(1.0 - functionIntensity, 0, 1.0,
×
1018
                          m_slider->minimum(), m_slider->maximum());
1019
        if (m_slider->value() > value)
×
1020
        {
1021
            m_externalMovement = true;
×
1022
            m_slider->setValue(value);
×
1023
            m_externalMovement = false;
×
1024

1025
            Function* function = m_doc->function(m_playbackFunction);
×
1026
            if (function != NULL)
×
1027
            {
1028
                qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
1029
                adjustFunctionIntensity(function, pIntensity * intensity());
×
1030
                if (value == 0 && !function->stopped())
×
1031
                    function->stop(functionParent());
×
1032
            }
1033
        }
1034
    }
1035
}
1036

NEW
1037
bool VCSlider::playbackFlashEnable()
×
1038
{
NEW
1039
    return m_playbackFlashEnable;
×
1040
}
1041

NEW
1042
void VCSlider::setPlaybackFlashEnable(bool enable)
×
1043
{
NEW
1044
    m_playbackFlashEnable = enable;
×
1045

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

NEW
1061
        m_flashButton->show();
×
1062
    }
NEW
1063
}
×
1064

NEW
1065
void VCSlider::flashPlayback(bool on)
×
1066
{
NEW
1067
    if (on)
×
NEW
1068
        m_playbackFlashPreviousValue = m_playbackValue;
×
NEW
1069
    m_playbackIsFlashing = on;
×
1070

NEW
1071
    setPlaybackValue(on ? UCHAR_MAX : m_playbackFlashPreviousValue);
×
NEW
1072
}
×
1073

UNCOV
1074
void VCSlider::slotPlaybackFunctionRunning(quint32 fid)
×
1075
{
1076
    Q_UNUSED(fid);
1077
}
×
1078

1079
void VCSlider::slotPlaybackFunctionStopped(quint32 fid)
×
1080
{
1081
    if (fid != playbackFunction())
×
1082
        return;
×
1083

1084
    m_externalMovement = true;
×
1085
    if (m_slider)
×
1086
        m_slider->setValue(0);
×
1087
    resetIntensityOverrideAttribute();
×
1088
    updateFeedback();
×
1089
    m_externalMovement = false;
×
1090
}
1091

1092
void VCSlider::slotPlaybackFunctionIntensityChanged(int attrIndex, qreal fraction)
×
1093
{
1094
    //qDebug() << "Function intensity changed" << attrIndex << fraction << m_playbackChangeCounter;
1095

1096
    if (attrIndex != Function::Intensity || m_playbackChangeCounter)
×
1097
        return;
×
1098

1099
    m_externalMovement = true;
×
1100
    if (m_slider)
×
1101
        m_slider->setValue(int(floor((qreal(m_slider->maximum()) * fraction) + 0.5)));
×
1102
    updateFeedback();
×
1103
    m_externalMovement = false;
×
1104
}
1105

1106
void VCSlider::slotPlaybackFunctionFlashing(quint32 fid, bool flashing)
×
1107
{
1108
    if (fid != playbackFunction())
×
1109
        return;
×
1110

1111
    m_externalMovement = true;
×
1112
    if (m_slider)
×
1113
        m_slider->setValue(flashing ? m_slider->maximum() : m_slider->minimum());
×
1114
    updateFeedback();
×
1115
    m_externalMovement = false;
×
1116
}
1117

1118
FunctionParent VCSlider::functionParent() const
×
1119
{
1120
    return FunctionParent(FunctionParent::ManualVCWidget, id());
×
1121
}
1122

1123
/*********************************************************************
1124
 * Submaster
1125
 *********************************************************************/
1126

1127
void VCSlider::emitSubmasterValue()
×
1128
{
1129
    Q_ASSERT(sliderMode() == Submaster);
×
1130

1131
    emit submasterValueChanged(SCALE(float(m_levelValue), float(0),
×
1132
                float(UCHAR_MAX), float(0), float(1)) * intensity());
×
1133
}
×
1134

1135
/*****************************************************************************
1136
 * DMXSource
1137
 *****************************************************************************/
1138

1139
void VCSlider::writeDMX(MasterTimer *timer, QList<Universe *> universes)
×
1140
{
1141
    if (sliderMode() == Level)
×
1142
        writeDMXLevel(timer, universes);
×
1143
    else if (sliderMode() == Playback)
×
1144
        writeDMXPlayback(timer, universes);
×
1145
}
×
1146

1147
void VCSlider::writeDMXLevel(MasterTimer *timer, QList<Universe *> universes)
×
1148
{
1149
    Q_UNUSED(timer);
1150

1151
    QMutexLocker locker(&m_levelValueMutex);
×
1152

1153
    uchar modLevel = m_levelValue;
×
1154
    int r = 0, g = 0, b = 0, c = 0, m = 0, y = 0;
×
1155

1156
    if (m_cngType == ClickAndGoWidget::RGB)
×
1157
    {
1158
        float f = 0;
×
1159
        if (m_slider)
×
1160
            f = SCALE(float(m_levelValue), float(m_slider->minimum()),
×
1161
                      float(m_slider->maximum()), float(0), float(200));
1162

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

1186
    if (m_levelValueChanged)
×
1187
    {
1188
        QListIterator <LevelChannel> it(m_levelChannels);
×
1189
        while (it.hasNext() == true)
×
1190
        {
1191
            LevelChannel lch(it.next());
×
1192
            Fixture *fxi = m_doc->fixture(lch.fixture);
×
1193
            if (fxi == NULL)
×
1194
                continue;
×
1195

1196
            quint32 universe = fxi->universe();
×
1197

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

1213
            FadeChannel *fc = fader->getChannelFader(m_doc, universes[universe], lch.fixture, lch.channel);
×
1214
            if (fc->universe() == Universe::invalid())
×
1215
            {
1216
                fader->remove(fc);
×
1217
                continue;
×
1218
            }
1219

1220
            int chType = fc->flags();
×
1221
            const QLCChannel *qlcch = fxi->channel(lch.channel);
×
1222
            if (qlcch == NULL)
×
1223
                continue;
×
1224

1225
            // set override flag if needed
1226
            if (m_isOverriding)
×
1227
                fc->addFlag(FadeChannel::Override);
×
1228

1229
            // request to autoremove LTP channels when set
1230
            if (qlcch->group() != QLCChannel::Intensity)
×
1231
                fc->addFlag(FadeChannel::AutoRemove);
×
1232

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

1255
            fc->setStart(fc->current());
×
1256
            fc->setTarget(modLevel);
×
1257
            fc->setReady(false);
×
1258
            fc->setElapsed(0);
×
1259

1260
            //qDebug() << "VC Slider write channel" << fc->target();
1261
        }
1262
    }
1263
    m_levelValueChanged = false;
×
1264
}
×
1265

1266
void VCSlider::writeDMXPlayback(MasterTimer* timer, QList<Universe *> ua)
×
1267
{
1268
    Q_UNUSED(ua);
1269

1270
    QMutexLocker locker(&m_playbackValueMutex);
×
1271

1272
    if (m_playbackChangeCounter == 0)
×
1273
        return;
×
1274

1275
    Function* function = m_doc->function(m_playbackFunction);
×
1276
    if (function == NULL || mode() == Doc::Design)
×
1277
        return;
×
1278

1279
    uchar value = m_playbackValue;
×
1280
    qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
1281

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

1309
/*****************************************************************************
1310
 * Top label
1311
 *****************************************************************************/
1312

1313
void VCSlider::setTopLabelText(int value)
2✔
1314
{
1315
    QString text;
2✔
1316

1317
    if (valueDisplayStyle() == ExactValue)
2✔
1318
    {
1319
        text = text.asprintf("%.3d", value);
2✔
1320
    }
1321
    else
1322
    {
1323

1324
        float f = 0;
×
1325
        if (m_slider)
×
1326
            f = SCALE(float(value), float(m_slider->minimum()),
×
1327
                      float(m_slider->maximum()), float(0), float(100));
1328
        text = text.asprintf("%.3d%%", static_cast<int> (f));
×
1329
    }
1330
    m_topLabel->setText(text);
2✔
1331
    emit valueChanged(text);
2✔
1332
}
2✔
1333

1334
QString VCSlider::topLabelText()
×
1335
{
1336
    return m_topLabel->text();
×
1337
}
1338

1339
/*****************************************************************************
1340
 * Slider
1341
 *****************************************************************************/
1342

1343
void VCSlider::setSliderValue(uchar value, bool scale, bool external)
×
1344
{
1345
    if (m_slider == NULL)
×
1346
        return;
×
1347

1348
    float val = value;
×
1349

1350
    /* Scale from input value range to this slider's range */
1351
    if (scale)
×
1352
    {
1353
        val = SCALE(float(value), float(0), float(UCHAR_MAX),
×
1354
                float(m_slider->minimum()),
1355
                float(m_slider->maximum()));
1356
    }
1357

1358
    /* Request the UI to update */
1359
    if (m_slider->isSliderDown() == false && val != m_slider->value())
×
1360
       emit requestSliderUpdate(val);
×
1361

1362
    switch (sliderMode())
×
1363
    {
1364
        case Level:
×
1365
        {
1366
            if (m_monitorEnabled == true && m_isOverriding == false && m_slider->isSliderDown())
×
1367
            {
1368
                m_resetButton->setStyleSheet(QString("QToolButton{ background: red; }"));
×
1369
                m_isOverriding = true;
×
1370
            }
1371
            setLevelValue(val, external);
×
1372
            setClickAndGoWidgetFromLevel(val);
×
1373
        }
1374
        break;
×
1375

1376
        case Playback:
×
1377
        {
1378
            setPlaybackValue(value);
×
1379
        }
1380
        break;
×
1381

1382
        case Submaster:
×
1383
        {
1384
            setLevelValue(val);
×
1385
            emitSubmasterValue();
×
1386
        }
1387
        break;
×
1388
    }
1389
}
1390

1391
void VCSlider::setSliderShadowValue(int value)
×
1392
{
1393
    if (m_widgetMode == WSlider)
×
1394
    {
1395
        ClickAndGoSlider *sl = qobject_cast<ClickAndGoSlider*> (m_slider);
×
1396
        sl->setShadowLevel(value);
×
1397
    }
1398
}
×
1399

1400
int VCSlider::sliderValue() const
×
1401
{
1402
    if (m_slider)
×
1403
        return m_slider->value();
×
1404

1405
    return 0;
×
1406
}
1407

1408
void VCSlider::setWidgetStyle(SliderWidgetStyle mode)
×
1409
{
1410
    if (mode == m_widgetMode)
×
1411
        return;
×
1412

1413
    if (mode == WKnob)
×
1414
    {
1415
        qDebug() << "Switching to knob widget";
×
1416
        disconnect(m_slider, SIGNAL(valueChanged(int)),
×
1417
                this, SLOT(slotSliderMoved(int)));
1418

1419
        QLayoutItem* item;
1420
        while ((item = m_hbox->takeAt(0)) != NULL)
×
1421
        {
1422
            delete item->widget();
×
1423
            delete item;
×
1424
        }
1425

1426
        m_slider = NULL;
×
1427

1428
        m_slider = new KnobWidget(this);
×
1429
        m_slider->setEnabled(false);
×
1430
        m_slider->setRange(levelLowLimit(), levelHighLimit());
×
1431
        m_hbox->addWidget(m_slider);
×
1432
        m_slider->show();
×
1433
        connect(m_slider, SIGNAL(valueChanged(int)),
×
1434
                this, SLOT(slotSliderMoved(int)));
1435
    }
1436
    else if (mode == WSlider)
×
1437
    {
1438
        qDebug() << "Switching to slider widget";
×
1439
        disconnect(m_slider, SIGNAL(valueChanged(int)),
×
1440
                this, SLOT(slotSliderMoved(int)));
1441

1442
        QLayoutItem* item;
1443
        while ((item = m_hbox->takeAt(0)) != NULL)
×
1444
        {
1445
            delete item->widget();
×
1446
            delete item;
×
1447
        }
1448

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

1470
VCSlider::SliderWidgetStyle VCSlider::widgetStyle() const
×
1471
{
1472
    return m_widgetMode;
×
1473
}
1474

1475
QString VCSlider::widgetStyleToString(VCSlider::SliderWidgetStyle style)
×
1476
{
1477
    if (style == VCSlider::WSlider)
×
1478
        return QString("Slider");
×
1479
    else if (style == VCSlider::WKnob)
×
1480
        return QString("Knob");
×
1481

1482
    return QString();
×
1483
}
1484

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

1492
    return VCSlider::WSlider;
×
1493
}
1494

1495
void VCSlider::updateFeedback()
×
1496
{
1497
    int fbv = 0;
×
1498
    if (m_slider)
×
1499
    {
1500
        if (invertedAppearance() == true)
×
1501
            fbv = m_slider->maximum() - m_slider->value() + m_slider->minimum();
×
1502
        else
1503
            fbv = m_slider->value();
×
1504
        fbv = int(SCALE(float(fbv), float(m_slider->minimum()),
×
1505
                        float(m_slider->maximum()), float(0), float(UCHAR_MAX)));
1506
    }
1507
    sendFeedback(fbv);
×
1508
}
×
1509

1510
void VCSlider::slotSliderMoved(int value)
2✔
1511
{
1512
    /* Set text for the top label */
1513
    setTopLabelText(value);
2✔
1514

1515
    /* Do the rest only if the slider is being moved by the user */
1516
    if (m_slider->isSliderDown() == false)
2✔
1517
        return;
2✔
1518

1519
    setSliderValue(value, false);
×
1520

1521
    updateFeedback();
×
1522
}
1523

1524
/*****************************************************************************
1525
 * Bottom label
1526
 *****************************************************************************/
1527
void VCSlider::setBottomLabelText(const QString& text)
×
1528
{
1529
    m_bottomLabel->setText(text);
×
1530
}
×
1531

1532
QString VCSlider::bottomLabelText()
×
1533
{
1534
    return m_bottomLabel->text();
×
1535
}
1536

1537
/*****************************************************************************
1538
 * External input
1539
 *****************************************************************************/
1540

1541
void VCSlider::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
1542
{
1543
    /* Don't let input data through in design mode or if disabled */
1544
    if (acceptsInput() == false)
×
1545
        return;
×
1546

1547
    quint32 pagedCh = (page() << 16) | channel;
×
1548

1549
    if (checkInputSource(universe, pagedCh, value, sender(), sliderInputSourceId))
×
1550
    {
1551
        if (m_slider)
×
1552
        {
1553
            /* When 'values catching" is enabled, controllers that do not have motorized faders
1554
             * can catch up with the current slider value by entering a certain threshold
1555
             * or by 'surpassing' the current value */
1556
            if (catchValues())
×
1557
            {
1558
                uchar currentValue = sliderValue();
×
1559

1560
                // filter 'out of threshold' cases
1561
                if (m_lastInputValue == -1 ||
×
1562
                    (m_lastInputValue < currentValue - VALUE_CATCHING_THRESHOLD && value < currentValue - VALUE_CATCHING_THRESHOLD) ||
×
1563
                    (m_lastInputValue > currentValue + VALUE_CATCHING_THRESHOLD && value > currentValue + VALUE_CATCHING_THRESHOLD))
×
1564
                {
1565
                    m_lastInputValue = value;
×
1566
                    return;
×
1567
                }
1568
            }
1569

1570
            if (m_monitorEnabled == true && m_isOverriding == false)
×
1571
            {
1572
                m_resetButton->setStyleSheet(QString("QToolButton{ background: red; }"));
×
1573
                m_isOverriding = true;
×
1574
            }
1575

1576
            if (invertedAppearance())
×
1577
                value = UCHAR_MAX - value;
×
1578

1579
            setSliderValue(value, true, true);
×
1580
            m_lastInputValue = value;
×
1581
        }
1582
    }
1583
    else if (checkInputSource(universe, pagedCh, value, sender(), overrideResetInputSourceId))
×
1584
    {
1585
        if (value > 0)
×
1586
            slotResetButtonClicked();
×
1587
    }
NEW
1588
    else if (checkInputSource(universe, pagedCh, value, sender(), flashButtonInputSourceId))
×
1589
    {
NEW
1590
        flashPlayback(value ? true : false);
×
1591
    }
1592
}
1593

1594
void VCSlider::adjustIntensity(qreal val)
×
1595
{
1596
    VCWidget::adjustIntensity(val);
×
1597

1598
    if (sliderMode() == Playback)
×
1599
    {
1600
        Function* function = m_doc->function(m_playbackFunction);
×
1601
        if (function == NULL || mode() == Doc::Design)
×
1602
            return;
×
1603

1604
        qreal pIntensity = qreal(m_playbackValue) / qreal(UCHAR_MAX);
×
1605
        adjustFunctionIntensity(function, pIntensity * intensity());
×
1606
    }
1607
    else if (sliderMode() == Level)
×
1608
    {
1609
        foreach (QSharedPointer<GenericFader> fader, m_fadersMap.values())
×
1610
        {
1611
            if (!fader.isNull())
×
1612
                fader->adjustIntensity(val);
×
1613
        }
1614
    }
1615
}
1616

1617
/*****************************************************************************
1618
 * Load & Save
1619
 *****************************************************************************/
1620

1621
bool VCSlider::loadXML(QXmlStreamReader &root)
1✔
1622
{
1623
    bool visible = false;
1✔
1624
    int x = 0;
1✔
1625
    int y = 0;
1✔
1626
    int w = 0;
1✔
1627
    int h = 0;
1✔
1628

1629
    SliderMode sliderMode = Playback;
1✔
1630
    QString str;
2✔
1631

1632
    if (root.name() != KXMLQLCVCSlider)
1✔
1633
    {
1634
        qWarning() << Q_FUNC_INFO << "Slider node not found";
×
1635
        return false;
×
1636
    }
1637

1638
    /* Widget commons */
1639
    loadXMLCommon(root);
1✔
1640

1641
    QXmlStreamAttributes attrs = root.attributes();
1✔
1642

1643
    /* Widget style */
1644
    if (attrs.hasAttribute(KXMLQLCVCSliderWidgetStyle))
1✔
1645
        setWidgetStyle(stringToWidgetStyle(attrs.value(KXMLQLCVCSliderWidgetStyle).toString()));
×
1646

1647
    if (attrs.value(KXMLQLCVCSliderInvertedAppearance).toString() == "false")
1✔
1648
        setInvertedAppearance(false);
×
1649
    else
1650
        setInvertedAppearance(true);
1✔
1651

1652
    /* Values catching */
1653
    if (attrs.hasAttribute(KXMLQLCVCSliderCatchValues))
1✔
1654
        setCatchValues(true);
×
1655

1656
    /* Children */
1657
    while (root.readNextStartElement())
1✔
1658
    {
1659
        //qDebug() << "VC Slider tag:" << root.name();
1660
        if (root.name() == KXMLQLCWindowState)
×
1661
        {
1662
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
1663
            setGeometry(x, y, w, h);
×
1664
        }
1665
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
1666
        {
1667
            loadXMLAppearance(root);
×
1668
        }
1669
        else if (root.name() == KXMLQLCVCSliderMode)
×
1670
        {
1671
            QXmlStreamAttributes mAttrs = root.attributes();
×
1672
            sliderMode = stringToSliderMode(root.readElementText());
×
1673

1674
            str = mAttrs.value(KXMLQLCVCSliderValueDisplayStyle).toString();
×
1675
            setValueDisplayStyle(stringToValueDisplayStyle(str));
×
1676

1677
            if (mAttrs.hasAttribute(KXMLQLCVCSliderClickAndGoType))
×
1678
            {
1679
                str = mAttrs.value(KXMLQLCVCSliderClickAndGoType).toString();
×
1680
                setClickAndGoType(ClickAndGoWidget::stringToClickAndGoType(str));
×
1681
            }
1682

1683
            if (mAttrs.hasAttribute(KXMLQLCVCSliderLevelMonitor))
×
1684
            {
1685
                if (mAttrs.value(KXMLQLCVCSliderLevelMonitor).toString() == "false")
×
1686
                    setChannelsMonitorEnabled(false);
×
1687
                else
1688
                    setChannelsMonitorEnabled(true);
×
1689
            }
1690
        }
1691
        else if (root.name() == KXMLQLCVCSliderOverrideReset)
×
1692
        {
1693
            QString str = loadXMLSources(root, overrideResetInputSourceId);
×
1694
            if (str.isEmpty() == false)
×
1695
                m_overrideResetKeySequence = stripKeySequence(QKeySequence(str));
×
1696
        }
1697
        else if (root.name() == KXMLQLCVCSliderLevel)
×
1698
        {
1699
            loadXMLLevel(root);
×
1700
        }
1701
        else if (root.name() == KXMLQLCVCWidgetInput)
×
1702
        {
1703
            loadXMLInput(root);
×
1704
        }
1705
        else if (root.name() == KXMLQLCVCSliderPlayback)
×
1706
        {
1707
            loadXMLPlayback(root);
×
1708
        }
1709
        else
1710
        {
1711
            qWarning() << Q_FUNC_INFO << "Unknown slider tag:" << root.name().toString();
×
1712
            root.skipCurrentElement();
×
1713
        }
1714
    }
1715

1716
    /* Set the mode last, after everything else has been set */
1717
    setSliderMode(sliderMode);
1✔
1718

1719
    return true;
1✔
1720
}
1721

1722
bool VCSlider::loadXMLLevel(QXmlStreamReader &level_root)
×
1723
{
1724
    QString str;
×
1725

1726
    if (level_root.name() != KXMLQLCVCSliderLevel)
×
1727
    {
1728
        qWarning() << Q_FUNC_INFO << "Slider level node not found";
×
1729
        return false;
×
1730
    }
1731

1732
    QXmlStreamAttributes attrs = level_root.attributes();
×
1733

1734
    /* Level low limit */
1735
    str = attrs.value(KXMLQLCVCSliderLevelLowLimit).toString();
×
1736
    setLevelLowLimit(str.toInt());
×
1737

1738
    /* Level high limit */
1739
    str = attrs.value(KXMLQLCVCSliderLevelHighLimit).toString();
×
1740
    setLevelHighLimit(str.toInt());
×
1741

1742
    /* Level value */
1743
    str = attrs.value(KXMLQLCVCSliderLevelValue).toString();
×
1744
    setLevelValue(str.toInt());
×
1745

1746
    QXmlStreamReader::TokenType tType = level_root.readNext();
×
1747

1748
    if (tType == QXmlStreamReader::EndElement)
×
1749
    {
1750
        level_root.readNext();
×
1751
        return true;
×
1752
    }
1753

1754
    if (tType == QXmlStreamReader::Characters)
×
1755
        tType = level_root.readNext();
×
1756

1757
    // check if there is a Channel tag defined
1758
    if (tType == QXmlStreamReader::StartElement)
×
1759
    {
1760
        /* Children */
1761
        do
×
1762
        {
1763
            if (level_root.name() == KXMLQLCVCSliderChannel)
×
1764
            {
1765
                /* Fixture & channel */
1766
                str = level_root.attributes().value(KXMLQLCVCSliderChannelFixture).toString();
×
1767
                addLevelChannel(
×
1768
                    static_cast<quint32>(str.toInt()),
×
1769
                    static_cast<quint32> (level_root.readElementText().toInt()));
×
1770
            }
1771
            else
1772
            {
1773
                qWarning() << Q_FUNC_INFO << "Unknown slider level tag:" << level_root.name().toString();
×
1774
                level_root.skipCurrentElement();
×
1775
            }
1776
        } while (level_root.readNextStartElement());
×
1777
    }
1778

1779
    return true;
×
1780
}
1781

1782
bool VCSlider::loadXMLPlayback(QXmlStreamReader &pb_root)
×
1783
{
1784
    if (pb_root.name() != KXMLQLCVCSliderPlayback)
×
1785
    {
1786
        qWarning() << Q_FUNC_INFO << "Slider playback node not found";
×
1787
        return false;
×
1788
    }
1789

1790
    /* Children */
1791
    while (pb_root.readNextStartElement())
×
1792
    {
1793
        if (pb_root.name() == KXMLQLCVCSliderPlaybackFunction)
×
1794
        {
1795
            /* Function */
1796
            setPlaybackFunction(pb_root.readElementText().toUInt());
×
1797
        }
NEW
1798
        else if (pb_root.name() == KXMLQLCVCSliderPlaybackFlash)
×
1799
        {
NEW
1800
            setPlaybackFlashEnable(true);
×
NEW
1801
            QString str = loadXMLSources(pb_root, flashButtonInputSourceId);
×
NEW
1802
            if (str.isEmpty() == false)
×
NEW
1803
                m_playbackFlashKeySequence = stripKeySequence(QKeySequence(str));
×
1804
        }
1805
        else
1806
        {
1807
            qWarning() << Q_FUNC_INFO << "Unknown slider playback tag:" << pb_root.name().toString();
×
1808
            pb_root.skipCurrentElement();
×
1809
        }
1810
    }
1811

1812
    return true;
×
1813
}
1814

1815
bool VCSlider::saveXML(QXmlStreamWriter *doc)
×
1816
{
1817
    QString str;
×
1818

1819
    Q_ASSERT(doc != NULL);
×
1820

1821
    /* VC Slider entry */
1822
    doc->writeStartElement(KXMLQLCVCSlider);
×
1823

1824
    saveXMLCommon(doc);
×
1825

1826
    /* Widget style */
1827
    doc->writeAttribute(KXMLQLCVCSliderWidgetStyle, widgetStyleToString(widgetStyle()));
×
1828

1829
    /* Inverted appearance */
1830
    if (invertedAppearance() == true)
×
1831
        doc->writeAttribute(KXMLQLCVCSliderInvertedAppearance, "true");
×
1832
    else
1833
        doc->writeAttribute(KXMLQLCVCSliderInvertedAppearance, "false");
×
1834

1835
    /* Values catching */
1836
    if (catchValues() == true)
×
1837
        doc->writeAttribute(KXMLQLCVCSliderCatchValues, "true");
×
1838

1839
    /* Window state */
1840
    saveXMLWindowState(doc);
×
1841

1842
    /* Appearance */
1843
    saveXMLAppearance(doc);
×
1844

1845
    /* External input */
1846
    saveXMLInput(doc, inputSource(sliderInputSourceId));
×
1847

1848
    /* SliderMode */
1849
    doc->writeStartElement(KXMLQLCVCSliderMode);
×
1850

1851
    /* Value display style */
1852
    str = valueDisplayStyleToString(valueDisplayStyle());
×
1853
    doc->writeAttribute(KXMLQLCVCSliderValueDisplayStyle, str);
×
1854

1855
    /* Click And Go type */
1856
    str = ClickAndGoWidget::clickAndGoTypeToString(m_cngType);
×
1857
    doc->writeAttribute(KXMLQLCVCSliderClickAndGoType, str);
×
1858

1859
    /* Monitor channels */
1860
    if (sliderMode() == Level)
×
1861
    {
1862
        if (channelsMonitorEnabled() == true)
×
1863
            doc->writeAttribute(KXMLQLCVCSliderLevelMonitor, "true");
×
1864
        else
1865
            doc->writeAttribute(KXMLQLCVCSliderLevelMonitor, "false");
×
1866
    }
1867

1868
    doc->writeCharacters(sliderModeToString(m_sliderMode));
×
1869

1870
    /* End the <SliderMode> tag */
1871
    doc->writeEndElement();
×
1872

1873
    if (sliderMode() == Level && channelsMonitorEnabled() == true)
×
1874
    {
1875
        doc->writeStartElement(KXMLQLCVCSliderOverrideReset);
×
1876
        if (m_overrideResetKeySequence.toString().isEmpty() == false)
×
1877
            doc->writeTextElement(KXMLQLCVCWidgetKey, m_overrideResetKeySequence.toString());
×
1878
        saveXMLInput(doc, inputSource(overrideResetInputSourceId));
×
1879
        doc->writeEndElement();
×
1880
    }
1881

1882
    /* Level */
1883
    doc->writeStartElement(KXMLQLCVCSliderLevel);
×
1884
    /* Level low limit */
1885
    doc->writeAttribute(KXMLQLCVCSliderLevelLowLimit, QString::number(levelLowLimit()));
×
1886
    /* Level high limit */
1887
    doc->writeAttribute(KXMLQLCVCSliderLevelHighLimit, QString::number(levelHighLimit()));
×
1888
    /* Level value */
1889
    doc->writeAttribute(KXMLQLCVCSliderLevelValue, QString::number(levelValue()));
×
1890

1891
    /* Level channels */
1892
    QListIterator <LevelChannel> it(m_levelChannels);
×
1893
    while (it.hasNext() == true)
×
1894
    {
1895
        LevelChannel lch(it.next());
×
1896
        lch.saveXML(doc);
×
1897
    }
1898

1899
    /* End the <Level> tag */
1900
    doc->writeEndElement();
×
1901

1902
    /* Playback */
1903
    doc->writeStartElement(KXMLQLCVCSliderPlayback);
×
1904
    /* Playback function */
1905
    doc->writeTextElement(KXMLQLCVCSliderPlaybackFunction, QString::number(playbackFunction()));
×
1906

NEW
1907
    if (sliderMode() == Playback && playbackFlashEnable() == true)
×
1908
    {
NEW
1909
        doc->writeStartElement(KXMLQLCVCSliderPlaybackFlash);
×
NEW
1910
        if (m_playbackFlashKeySequence.toString().isEmpty() == false)
×
NEW
1911
            doc->writeTextElement(KXMLQLCVCWidgetKey, m_playbackFlashKeySequence.toString());
×
NEW
1912
        saveXMLInput(doc, inputSource(flashButtonInputSourceId));
×
NEW
1913
        doc->writeEndElement();
×
1914
    }
1915

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

1919
    /* End the <Slider> tag */
1920
    doc->writeEndElement();
×
1921

1922
    return true;
×
1923
}
1924

1925
/****************************************************************************
1926
 * LevelChannel implementation
1927
 ****************************************************************************/
1928

1929
VCSlider::LevelChannel::LevelChannel(quint32 fid, quint32 ch)
×
1930
{
1931
    this->fixture = fid;
×
1932
    this->channel = ch;
×
1933
}
×
1934

1935
VCSlider::LevelChannel::LevelChannel(const LevelChannel& lc)
×
1936
{
1937
    *this = lc;
×
1938
}
×
1939

1940
VCSlider::LevelChannel &VCSlider::LevelChannel::operator=(const VCSlider::LevelChannel &lc)
×
1941
{
1942
    if (this != &lc)
×
1943
    {
1944
        this->fixture = lc.fixture;
×
1945
        this->channel = lc.channel;
×
1946
    }
1947

1948
    return *this;
×
1949
}
1950

1951
bool VCSlider::LevelChannel::operator==(const LevelChannel& lc) const
×
1952
{
1953
    return (this->fixture == lc.fixture && this->channel == lc.channel);
×
1954
}
1955

1956
bool VCSlider::LevelChannel::operator<(const LevelChannel& lc) const
×
1957
{
1958
    if (this->fixture < lc.fixture)
×
1959
        return true;
×
1960
    else if (this->fixture == lc.fixture && this->channel < lc.channel)
×
1961
        return true;
×
1962
    else
1963
        return false;
×
1964
}
1965

1966
void VCSlider::LevelChannel::saveXML(QXmlStreamWriter *doc) const
×
1967
{
1968
    Q_ASSERT(doc != NULL);
×
1969

1970
    doc->writeStartElement(KXMLQLCVCSliderChannel);
×
1971

1972
    doc->writeAttribute(KXMLQLCVCSliderChannelFixture,
×
1973
                       QString::number(this->fixture));
×
1974

1975
    doc->writeCharacters(QString::number(this->channel));
×
1976
    doc->writeEndElement();
×
1977
}
×
1978

NEW
1979
void VCSlider::FlashButton::mousePressEvent(QMouseEvent *e)
×
1980
{
NEW
1981
    QToolButton::mousePressEvent(e);
×
1982
    // ignore event so that it can be
1983
    // forwarded to parent widget
NEW
1984
    e->ignore();
×
NEW
1985
}
×
1986

NEW
1987
void VCSlider::FlashButton::mouseReleaseEvent(QMouseEvent *e)
×
1988
{
NEW
1989
    QToolButton::mouseReleaseEvent(e);
×
1990
    // ignore event so that it can be
1991
    // forwarded to parent widget
NEW
1992
    e->ignore();
×
NEW
1993
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc