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

mcallegari / qlcplus / 6812397245

09 Nov 2023 01:22PM UTC coverage: 28.086% (-0.004%) from 28.09%
6812397245

push

github

web-flow
Merge pull request #1477 from Itay-Lifshitz/webaccess_cuelist_sliders

Webaccess cuelist side fader

8 of 39 new or added lines in 1 file covered. (20.51%)

37 existing lines in 2 files now uncovered.

15420 of 54903 relevant lines covered (28.09%)

20284.04 hits per line

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

61.41
/ui/src/virtualconsole/vccuelist.cpp
1
/*
2
  Q Light Controller Plus
3
  vccuelist.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

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

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

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

21
#include <QStyledItemDelegate>
22
#include <QXmlStreamReader>
23
#include <QXmlStreamWriter>
24
#include <QTreeWidgetItem>
25
#include <QFontMetrics>
26
#include <QProgressBar>
27
#include <QTreeWidget>
28
#include <QHeaderView>
29
#include <QGridLayout>
30
#include <QSettings>
31
#include <QCheckBox>
32
#include <QString>
33
#include <QLabel>
34
#include <QDebug>
35
#include <QTimer>
36

37
#include "vccuelistproperties.h"
38
#include "vcpropertieseditor.h"
39
#include "clickandgoslider.h"
40
#include "chaserrunner.h"
41
#include "mastertimer.h"
42
#include "chaserstep.h"
43
#include "vccuelist.h"
44
#include "qlcmacros.h"
45
#include "function.h"
46
#include "vcwidget.h"
47
#include "apputil.h"
48
#include "chaser.h"
49
#include "qmath.h"
50
#include "doc.h"
51

52
#define COL_NUM      0
53
#define COL_NAME     1
54
#define COL_FADEIN   2
55
#define COL_FADEOUT  3
56
#define COL_DURATION 4
57
#define COL_NOTES    5
58

59
#define PROP_ID  Qt::UserRole
60
#define HYSTERESIS 3 // Hysteresis for next/previous external input
61

62
#define PROGRESS_INTERVAL 200
63
#define UPDATE_TIMEOUT 100
64

65
const quint8 VCCueList::nextInputSourceId = 0;
66
const quint8 VCCueList::previousInputSourceId = 1;
67
const quint8 VCCueList::playbackInputSourceId = 2;
68
const quint8 VCCueList::sideFaderInputSourceId = 3;
69
const quint8 VCCueList::stopInputSourceId = 4;
70

71
const QString progressDisabledStyle =
72
        "QProgressBar { border: 2px solid #C3C3C3; border-radius: 4px; background-color: #DCDCDC; }";
73
const QString progressFadeStyle =
74
        "QProgressBar { border: 2px solid grey; border-radius: 4px; background-color: #C3C3C3; text-align: center; }"
75
        "QProgressBar::chunk { background-color: #63C10B; width: 1px; }";
76
const QString progressHoldStyle =
77
        "QProgressBar { border: 2px solid grey; border-radius: 4px; background-color: #C3C3C3; text-align: center; }"
78
        "QProgressBar::chunk { background-color: #0F9BEC; width: 1px; }";
79

80
const QString cfLabelBlueStyle =
81
        "QLabel { background-color: #4E8DDE; color: white; border: 1px solid; border-radius: 3px; font: bold; }";
82
const QString cfLabelOrangeStyle =
83
        "QLabel { background-color: orange; color: black; border: 1px solid; border-radius: 3px; font: bold; }";
84
const QString cfLabelNoStyle =
85
        "QLabel { border: 1px solid; border-radius: 3px; font: bold; }";
86

87
VCCueList::VCCueList(QWidget *parent, Doc *doc) : VCWidget(parent, doc)
15✔
88
    , m_chaserID(Function::invalidId())
30✔
89
    , m_nextPrevBehavior(DefaultRunFirst)
90
    , m_playbackLayout(PlayPauseStop)
91
    , m_timer(NULL)
92
    , m_primaryIndex(0)
93
    , m_secondaryIndex(0)
94
    , m_primaryTop(true)
95
    , m_slidersMode(None)
15✔
96
{
97
    /* Set the class name "VCCueList" as the object name as well */
98
    setObjectName(VCCueList::staticMetaObject.className());
15✔
99

100
    /* Create a layout for this widget */
101
    QGridLayout *grid = new QGridLayout(this);
15✔
102
    grid->setSpacing(2);
15✔
103

104
    QFontMetrics m_fm = QFontMetrics(this->font());
30✔
105

106
    m_topPercentageLabel = new QLabel("100%");
15✔
107
    m_topPercentageLabel->setAlignment(Qt::AlignHCenter);
15✔
108
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
109
    m_topPercentageLabel->setFixedWidth(m_fm.width("100%"));
110
#else
111
    m_topPercentageLabel->setFixedWidth(m_fm.horizontalAdvance("100%"));
15✔
112
#endif
113
    grid->addWidget(m_topPercentageLabel, 1, 0, 1, 1);
15✔
114

115
    m_topStepLabel = new QLabel("");
15✔
116
    m_topStepLabel->setStyleSheet(cfLabelNoStyle);
15✔
117
    m_topStepLabel->setAlignment(Qt::AlignCenter);
15✔
118
    m_topStepLabel->setFixedSize(32, 24);
15✔
119
    grid->addWidget(m_topStepLabel, 2, 0, 1, 1);
15✔
120

121
    m_sideFader = new ClickAndGoSlider();
15✔
122
    m_sideFader->setSliderStyleSheet(CNG_DEFAULT_STYLE);
15✔
123
    m_sideFader->setFixedWidth(32);
15✔
124
    m_sideFader->setRange(0, 100);
15✔
125
    m_sideFader->setValue(100);
15✔
126
    grid->addWidget(m_sideFader, 3, 0, 1, 1);
15✔
127

128
    m_bottomStepLabel = new QLabel("");
15✔
129
    m_bottomStepLabel->setStyleSheet(cfLabelNoStyle);
15✔
130
    m_bottomStepLabel->setAlignment(Qt::AlignCenter);
15✔
131
    m_bottomStepLabel->setFixedSize(32, 24);
15✔
132
    grid->addWidget(m_bottomStepLabel, 4, 0, 1, 1);
15✔
133

134
    m_bottomPercentageLabel = new QLabel("0%");
15✔
135
    m_bottomPercentageLabel->setAlignment(Qt::AlignHCenter);
15✔
136
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
137
    m_bottomPercentageLabel->setFixedWidth(m_fm.width("100%"));
138
#else
139
    m_bottomPercentageLabel->setFixedWidth(m_fm.horizontalAdvance("100%"));
15✔
140
#endif
141
    grid->addWidget(m_bottomPercentageLabel, 5, 0, 1, 1);
15✔
142

143
    connect(m_sideFader, SIGNAL(valueChanged(int)),
15✔
144
            this, SLOT(slotSideFaderValueChanged(int)));
145

146
    slotShowCrossfadePanel(false);
15✔
147

148
    QVBoxLayout *vbox = new QVBoxLayout();
15✔
149

150
    /* Create a list for scenes (cues) */
151
    m_tree = new QTreeWidget(this);
15✔
152
    m_tree->setSelectionMode(QAbstractItemView::SingleSelection);
15✔
153
    //m_tree->setAlternatingRowColors(true);
154
    m_tree->setAllColumnsShowFocus(true);
15✔
155
    m_tree->setRootIsDecorated(false);
15✔
156
    m_tree->setItemsExpandable(false);
15✔
157
    m_tree->header()->setSortIndicatorShown(false);
15✔
158
    m_tree->header()->setMinimumSectionSize(0); // allow columns to be hidden
15✔
159
    m_tree->header()->setSectionsClickable(false);
15✔
160
    m_tree->header()->setSectionsMovable(false);
15✔
161

162
    // Make only the notes column editable
163
    m_tree->setItemDelegateForColumn(COL_NUM, new NoEditDelegate(this));
15✔
164
    m_tree->setItemDelegateForColumn(COL_NAME, new NoEditDelegate(this));
15✔
165
    m_tree->setItemDelegateForColumn(COL_FADEIN, new NoEditDelegate(this));
15✔
166
    m_tree->setItemDelegateForColumn(COL_FADEOUT, new NoEditDelegate(this));
15✔
167
    m_tree->setItemDelegateForColumn(COL_DURATION, new NoEditDelegate(this));
15✔
168

169
    connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
15✔
170
            this, SLOT(slotItemActivated(QTreeWidgetItem*)));
171
    connect(m_tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
15✔
172
            this, SLOT(slotItemChanged(QTreeWidgetItem*,int)));
173
    vbox->addWidget(m_tree);
15✔
174

175
    m_progress = new QProgressBar(this);
15✔
176
    m_progress->setOrientation(Qt::Horizontal);
15✔
177
    m_progress->setStyleSheet(progressDisabledStyle);
15✔
178
    m_progress->setProperty("status", 0);
15✔
179
    m_progress->setFixedHeight(20);
15✔
180
    vbox->addWidget(m_progress);
15✔
181

182
    m_timer = new QTimer(this);
15✔
183
    connect(m_timer, SIGNAL(timeout()),
15✔
184
            this, SLOT(slotProgressTimeout()));
185

186
    m_updateTimer = new QTimer(this);
15✔
187
    connect(m_updateTimer, SIGNAL(timeout()),
15✔
188
            this, SLOT(slotUpdateStepList()));
189
    m_updateTimer->setSingleShot(true);
15✔
190

191
    /* Create control buttons */
192
    QHBoxLayout *hbox = new QHBoxLayout();
15✔
193
    hbox->setSpacing(2);
15✔
194

195
    m_crossfadeButton = new QToolButton(this);
15✔
196
    m_crossfadeButton->setIcon(QIcon(":/slider.png"));
15✔
197
    m_crossfadeButton->setIconSize(QSize(24, 24));
15✔
198
    m_crossfadeButton->setCheckable(true);
15✔
199
    m_crossfadeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
15✔
200
    m_crossfadeButton->setFixedHeight(32);
15✔
201
    m_crossfadeButton->setToolTip(tr("Show/Hide crossfade sliders"));
15✔
202
    m_crossfadeButton->setVisible(false);
15✔
203
    connect(m_crossfadeButton, SIGNAL(toggled(bool)),
15✔
204
            this, SLOT(slotShowCrossfadePanel(bool)));
205
    hbox->addWidget(m_crossfadeButton);
15✔
206

207
    m_playbackButton = new QToolButton(this);
15✔
208
    m_playbackButton->setIcon(QIcon(":/player_play.png"));
15✔
209
    m_playbackButton->setIconSize(QSize(24, 24));
15✔
210
    m_playbackButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
15✔
211
    m_playbackButton->setFixedHeight(32);
15✔
212
    m_playbackButton->setToolTip(tr("Play/Pause Cue list"));
15✔
213
    connect(m_playbackButton, SIGNAL(clicked()), this, SLOT(slotPlayback()));
15✔
214
    hbox->addWidget(m_playbackButton);
15✔
215

216
    m_stopButton = new QToolButton(this);
15✔
217
    m_stopButton->setIcon(QIcon(":/player_stop.png"));
15✔
218
    m_stopButton->setIconSize(QSize(24, 24));
15✔
219
    m_stopButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
15✔
220
    m_stopButton->setFixedHeight(32);
15✔
221
    m_stopButton->setToolTip(tr("Stop Cue list"));
15✔
222
    connect(m_stopButton, SIGNAL(clicked()), this, SLOT(slotStop()));
15✔
223
    hbox->addWidget(m_stopButton);
15✔
224

225
    m_previousButton = new QToolButton(this);
15✔
226
    m_previousButton->setIcon(QIcon(":/back.png"));
15✔
227
    m_previousButton->setIconSize(QSize(24, 24));
15✔
228
    m_previousButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
15✔
229
    m_previousButton->setFixedHeight(32);
15✔
230
    m_previousButton->setToolTip(tr("Go to previous step in the list"));
15✔
231
    connect(m_previousButton, SIGNAL(clicked()), this, SLOT(slotPreviousCue()));
15✔
232
    hbox->addWidget(m_previousButton);
15✔
233

234
    m_nextButton = new QToolButton(this);
15✔
235
    m_nextButton->setIcon(QIcon(":/forward.png"));
15✔
236
    m_nextButton->setIconSize(QSize(24, 24));
15✔
237
    m_nextButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
15✔
238
    m_nextButton->setFixedHeight(32);
15✔
239
    m_nextButton->setToolTip(tr("Go to next step in the list"));
15✔
240
    connect(m_nextButton, SIGNAL(clicked()), this, SLOT(slotNextCue()));
15✔
241
    hbox->addWidget(m_nextButton);
15✔
242

243
    vbox->addItem(hbox);
15✔
244
    grid->addItem(vbox, 0, 1, 6);
15✔
245

246
    setFrameStyle(KVCFrameStyleSunken);
15✔
247
    setType(VCWidget::CueListWidget);
15✔
248
    setCaption(tr("Cue list"));
15✔
249

250
    QSettings settings;
30✔
251
    QVariant var = settings.value(SETTINGS_CUELIST_SIZE);
30✔
252
    if (var.isValid() == true)
15✔
253
        resize(var.toSize());
×
254
    else
255
        resize(QSize(300, 220));
15✔
256

257
    slotModeChanged(m_doc->mode());
15✔
258
    setLiveEdit(m_liveEdit);
15✔
259

260
    connect(m_doc, SIGNAL(functionRemoved(quint32)),
15✔
261
            this, SLOT(slotFunctionRemoved(quint32)));
262
    connect(m_doc, SIGNAL(functionChanged(quint32)),
15✔
263
            this, SLOT(slotFunctionChanged(quint32)));
264
    connect(m_doc, SIGNAL(functionNameChanged(quint32)),
15✔
265
            this, SLOT(slotFunctionNameChanged(quint32)));
266

267
    m_nextLatestValue = 0;
15✔
268
    m_previousLatestValue = 0;
15✔
269
    m_playbackLatestValue = 0;
15✔
270
    m_stopLatestValue = 0;
15✔
271
}
15✔
272

273
VCCueList::~VCCueList()
17✔
274
{
275
}
17✔
276

277
void VCCueList::enableWidgetUI(bool enable)
23✔
278
{
279
    m_tree->setEnabled(enable);
23✔
280
    m_playbackButton->setEnabled(enable);
23✔
281
    m_stopButton->setEnabled(enable);
23✔
282
    m_previousButton->setEnabled(enable);
23✔
283
    m_nextButton->setEnabled(enable);
23✔
284

285
    m_topPercentageLabel->setEnabled(enable);
23✔
286
    m_sideFader->setEnabled(enable);
23✔
287
    m_topStepLabel->setEnabled(enable);
23✔
288
    m_bottomPercentageLabel->setEnabled(enable);
23✔
289
    m_bottomStepLabel->setEnabled(enable);
23✔
290
}
23✔
291

292
/*****************************************************************************
293
 * Clipboard
294
 *****************************************************************************/
295

296
VCWidget *VCCueList::createCopy(VCWidget *parent)
1✔
297
{
298
    Q_ASSERT(parent != NULL);
1✔
299

300
    VCCueList *cuelist = new VCCueList(parent, m_doc);
1✔
301
    if (cuelist->copyFrom(this) == false)
1✔
302
    {
303
        delete cuelist;
×
304
        cuelist = NULL;
×
305
    }
306

307
    return cuelist;
1✔
308
}
309

310
bool VCCueList::copyFrom(const VCWidget *widget)
3✔
311
{
312
    const VCCueList *cuelist = qobject_cast<const VCCueList*> (widget);
3✔
313
    if (cuelist == NULL)
3✔
314
        return false;
1✔
315

316
    /* Function list contents */
317
    setChaser(cuelist->chaserID());
2✔
318

319
    /* Key sequence */
320
    setNextKeySequence(cuelist->nextKeySequence());
2✔
321
    setPreviousKeySequence(cuelist->previousKeySequence());
2✔
322
    setPlaybackKeySequence(cuelist->playbackKeySequence());
2✔
323
    setStopKeySequence(cuelist->stopKeySequence());
2✔
324

325
    /* Sliders mode */
326
    setSideFaderMode(cuelist->sideFaderMode());
2✔
327

328
    /* Common stuff */
329
    return VCWidget::copyFrom(widget);
2✔
330
}
331

332
/*****************************************************************************
333
 * Cue list
334
 *****************************************************************************/
335

336
void VCCueList::setChaser(quint32 id)
14✔
337
{
338
    Function *old = m_doc->function(m_chaserID);
14✔
339
    if (old != NULL)
14✔
340
    {
341
        /* Get rid of old function connections */
342
        disconnect(old, SIGNAL(running(quint32)),
1✔
343
                this, SLOT(slotFunctionRunning(quint32)));
344
        disconnect(old, SIGNAL(stopped(quint32)),
1✔
345
                this, SLOT(slotFunctionStopped(quint32)));
346
        disconnect(old, SIGNAL(currentStepChanged(int)),
1✔
347
                this, SLOT(slotCurrentStepChanged(int)));
348
    }
349

350
    Chaser *chaser = qobject_cast<Chaser*> (m_doc->function(id));
14✔
351
    if (chaser != NULL)
14✔
352
    {
353
        /* Connect to the new function */
354
        connect(chaser, SIGNAL(running(quint32)),
11✔
355
                this, SLOT(slotFunctionRunning(quint32)));
356
        connect(chaser, SIGNAL(stopped(quint32)),
11✔
357
                this, SLOT(slotFunctionStopped(quint32)));
358
        connect(chaser, SIGNAL(currentStepChanged(int)),
11✔
359
                this, SLOT(slotCurrentStepChanged(int)));
360

361
        m_chaserID = id;
11✔
362
    }
363
    else
364
    {
365
        m_chaserID = Function::invalidId();
3✔
366
    }
367

368
    updateStepList();
14✔
369

370
    /* Current status */
371
    if (chaser != NULL && chaser->isRunning())
14✔
372
    {
373
        slotFunctionRunning(m_chaserID);
×
374
        slotCurrentStepChanged(chaser->currentStepIndex());
×
375
    }
376
    else
377
        slotFunctionStopped(m_chaserID);
14✔
378
}
14✔
379

380
quint32 VCCueList::chaserID() const
9✔
381
{
382
    return m_chaserID;
9✔
383
}
384

385
Chaser *VCCueList::chaser()
88✔
386
{
387
    if (m_chaserID == Function::invalidId())
88✔
388
        return NULL;
6✔
389
    Chaser *chaser = qobject_cast<Chaser*>(m_doc->function(m_chaserID));
82✔
390
    return chaser;
82✔
391
}
392

393
void VCCueList::updateStepList()
15✔
394
{
395
    m_listIsUpdating = true;
15✔
396

397
    m_tree->clear();
15✔
398

399
    Chaser *ch = chaser();
15✔
400
    if (ch == NULL)
15✔
401
        return;
3✔
402

403
    QListIterator <ChaserStep> it(ch->steps());
24✔
404
    while (it.hasNext() == true)
59✔
405
    {
406
        ChaserStep step(it.next());
94✔
407

408
        Function *function = m_doc->function(step.fid);
47✔
409
        Q_ASSERT(function != NULL);
47✔
410

411
        QTreeWidgetItem *item = new QTreeWidgetItem(m_tree);
47✔
412
        item->setFlags(item->flags() | Qt::ItemIsEditable);
47✔
413
        int index = m_tree->indexOfTopLevelItem(item) + 1;
47✔
414
        item->setText(COL_NUM, QString("%1").arg(index));
47✔
415
        item->setData(COL_NUM, PROP_ID, function->id());
47✔
416
        item->setText(COL_NAME, function->name());
47✔
417
        if (step.note.isEmpty() == false)
47✔
418
            item->setText(COL_NOTES, step.note);
×
419

420
        switch (ch->fadeInMode())
47✔
421
        {
422
            case Chaser::Common:
×
423
                item->setText(COL_FADEIN, Function::speedToString(ch->fadeInSpeed()));
×
424
                break;
×
425
            case Chaser::PerStep:
×
426
                item->setText(COL_FADEIN, Function::speedToString(step.fadeIn));
×
427
                break;
×
428
            default:
47✔
429
            case Chaser::Default:
430
                item->setText(COL_FADEIN, QString());
47✔
431
        }
432

433
        switch (ch->fadeOutMode())
47✔
434
        {
435
            case Chaser::Common:
×
436
                item->setText(COL_FADEOUT, Function::speedToString(ch->fadeOutSpeed()));
×
437
                break;
×
438
            case Chaser::PerStep:
×
439
                item->setText(COL_FADEOUT, Function::speedToString(step.fadeOut));
×
440
                break;
×
441
            default:
47✔
442
            case Chaser::Default:
443
                item->setText(COL_FADEOUT, QString());
47✔
444
        }
445

446
        switch (ch->durationMode())
47✔
447
        {
448
            case Chaser::Common:
47✔
449
                item->setText(COL_DURATION, Function::speedToString(ch->duration()));
47✔
450
                break;
47✔
451
            case Chaser::PerStep:
×
452
                item->setText(COL_DURATION, Function::speedToString(step.duration));
×
453
                break;
×
454
            default:
×
455
            case Chaser::Default:
456
                item->setText(COL_DURATION, QString());
×
457
        }
458
    }
459

460
    QTreeWidgetItem *item = m_tree->topLevelItem(0);
12✔
461
    if (item != NULL)
12✔
462
        m_defCol = item->background(COL_NUM);
12✔
463

464
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
12✔
465
    m_tree->header()->setSectionHidden(COL_NAME, ch->type() == Function::SequenceType ? true : false);
12✔
466
    m_listIsUpdating = false;
12✔
467
}
468

469
int VCCueList::getCurrentIndex()
×
470
{
471
    int index = m_tree->indexOfTopLevelItem(m_tree->currentItem());
×
472
    if (index == -1)
×
473
        index = 0;
×
474
    return index;
×
475
}
476

477
int VCCueList::getNextIndex()
×
478
{
479
    Chaser *ch = chaser();
×
480
    if (ch == NULL)
×
481
        return -1;
×
482

483
    if (ch->direction() == Function::Forward)
×
484
        return getNextTreeIndex();
×
485
    else
486
        return getPrevTreeIndex();
×
487
}
488

489
int VCCueList::getPrevIndex()
×
490
{
491
    Chaser *ch = chaser();
×
492
    if (ch == NULL)
×
493
        return -1;
×
494

495
    if (ch->direction() == Function::Forward)
×
496
        return getPrevTreeIndex();
×
497
    else
498
        return getNextTreeIndex();
×
499
}
500

501
int VCCueList::getFirstIndex()
3✔
502
{
503
    Chaser *ch = chaser();
3✔
504
    if (ch == NULL)
3✔
505
        return -1;
×
506

507
    if (ch->direction() == Function::Forward)
3✔
508
        return getFirstTreeIndex();
3✔
509
    else
510
        return getLastTreeIndex();
×
511
}
512

513
int VCCueList::getLastIndex()
×
514
{
515
    Chaser *ch = chaser();
×
516
    if (ch == NULL)
×
517
        return -1;
×
518

519
    if (ch->direction() == Function::Forward)
×
520
        return getLastTreeIndex();
×
521
    else
522
        return getFirstTreeIndex();
×
523
}
524

525
int VCCueList::getNextTreeIndex()
×
526
{
527
    int count = m_tree->topLevelItemCount();
×
528
    if (count > 0)
×
529
        return (getCurrentIndex() + 1) % count;
×
530
    return 0;
×
531
}
532

533
int VCCueList::getPrevTreeIndex()
×
534
{
535
    int currentIndex = getCurrentIndex();
×
536
    if (currentIndex <= 0)
×
537
        return getLastTreeIndex();
×
538
    return currentIndex - 1;
×
539
}
540

541
int VCCueList::getFirstTreeIndex()
3✔
542
{
543
    return 0;
3✔
544
}
545

546
int VCCueList::getLastTreeIndex()
×
547
{
548
    return m_tree->topLevelItemCount() - 1;
×
549
}
550

551
qreal VCCueList::getPrimaryIntensity() const
20✔
552
{
553
    if (sideFaderMode() == Steps)
20✔
554
        return  1.0;
×
555

556
    return m_primaryTop ? qreal(m_sideFader->value() / 100.0) : qreal((100 - m_sideFader->value()) / 100.0);
20✔
557
}
558

559
void VCCueList::notifyFunctionStarting(quint32 fid, qreal intensity)
×
560
{
561
    Q_UNUSED(intensity);
562

563
    if (mode() == Doc::Design)
×
564
        return;
×
565

566
    if (fid == m_chaserID)
×
567
        return;
×
568

569
    stopChaser();
×
570
}
571

572
void VCCueList::slotFunctionRemoved(quint32 fid)
2✔
573
{
574
    if (fid == m_chaserID)
2✔
575
    {
576
        setChaser(Function::invalidId());
1✔
577
        resetIntensityOverrideAttribute();
1✔
578
    }
579
}
2✔
580

581
void VCCueList::slotFunctionChanged(quint32 fid)
5✔
582
{
583
    if (fid == m_chaserID && !m_updateTimer->isActive())
5✔
584
        m_updateTimer->start(UPDATE_TIMEOUT);
1✔
585
}
5✔
586

587
void VCCueList::slotFunctionNameChanged(quint32 fid)
×
588
{
589
    if (fid == m_chaserID)
×
590
        m_updateTimer->start(UPDATE_TIMEOUT);
×
591
    else
592
    {
593
        // fid might be an ID of a ChaserStep of m_chaser
594
        Chaser *ch = chaser();
×
595
        if (ch == NULL)
×
596
            return;
×
597
        foreach (ChaserStep step, ch->steps())
×
598
        {
599
            if (step.fid == fid)
×
600
            {
601
                m_updateTimer->start(UPDATE_TIMEOUT);
×
602
                return;
×
603
            }
604
        }
605
    }
606
}
607

608
void VCCueList::slotUpdateStepList()
1✔
609
{
610
    updateStepList();
1✔
611
}
1✔
612

613
void VCCueList::slotPlayback()
2✔
614
{
615
    if (mode() != Doc::Operate)
2✔
616
        return;
×
617

618
    Chaser *ch = chaser();
2✔
619
    if (ch == NULL)
2✔
620
        return;
×
621

622
    if (ch->isRunning())
2✔
623
    {
624
        if (playbackLayout() == PlayPauseStop)
2✔
625
        {
626
            if (ch->isPaused())
2✔
627
            {
628
                m_playbackButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
629
                                                .arg(m_stopButton->palette().window().color().name()));
×
630
                m_playbackButton->setIcon(QIcon(":/player_pause.png"));
×
631
            }
632
            else
633
            {
634
                m_playbackButton->setStyleSheet("QToolButton{ background: #5B81FF; }");
2✔
635
                m_playbackButton->setIcon(QIcon(":/player_play.png"));
2✔
636
            }
637

638
            // check if the item selection has been changed during pause
639
            int currentTreeIndex = m_tree->indexOfTopLevelItem(m_tree->currentItem());
2✔
640
            if (currentTreeIndex != ch->currentStepIndex())
2✔
641
                playCueAtIndex(currentTreeIndex);
×
642

643
            ch->setPause(!ch->isPaused());
2✔
644
        }
645
        else if (playbackLayout() == PlayStopPause)
×
646
        {
647
            stopChaser();
×
648
            m_stopButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
649
                                            .arg(m_playbackButton->palette().window().color().name()));
×
650
        }
651
    }
652
    else
653
    {
654
        if (m_tree->currentItem() != NULL)
×
655
            startChaser(getCurrentIndex());
×
656
        else
657
            startChaser();
×
658
    }
659
}
660

661
void VCCueList::slotStop()
×
662
{
663
    if (mode() != Doc::Operate)
×
664
        return;
×
665

666
    Chaser *ch = chaser();
×
667
    if (ch == NULL)
×
668
        return;
×
669

670
    if (ch->isRunning())
×
671
    {
672
        if (playbackLayout() == PlayPauseStop)
×
673
        {
674
            stopChaser();
×
675
            m_playbackButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
676
                                            .arg(m_stopButton->palette().window().color().name()));
×
677
            m_progress->setFormat("");
×
678
            m_progress->setValue(0);
×
679

NEW
680
            emit progressStateChanged();
×
681
        }
682
        else if (playbackLayout() == PlayStopPause)
×
683
        {
684
            if (ch->isPaused())
×
685
            {
686
                m_stopButton->setStyleSheet(QString("QToolButton{ background: %1; }")
×
687
                                                .arg(m_playbackButton->palette().window().color().name()));
×
688
                m_stopButton->setIcon(QIcon(":/player_pause.png"));
×
689
            }
690
            else
691
            {
692
                m_stopButton->setStyleSheet("QToolButton{ background: #5B81FF; }");
×
693
            }
694
            ch->setPause(!ch->isPaused());
×
695
        }
696
    }
697
    else
698
    {
699
        m_primaryIndex = 0;
×
700
        m_tree->setCurrentItem(m_tree->topLevelItem(getFirstIndex()));
×
701
    }
702
}
703

704
void VCCueList::slotNextCue()
10✔
705
{
706
    if (mode() != Doc::Operate)
10✔
707
        return;
1✔
708

709
    Chaser *ch = chaser();
9✔
710
    if (ch == NULL)
9✔
711
        return;
×
712

713
    if (ch->isRunning())
9✔
714
    {
715
        if (ch->isPaused())
6✔
716
        {
717
            m_tree->setCurrentItem(m_tree->topLevelItem(getNextIndex()));
×
718
        }
719
        else
720
        {
721
            ChaserAction action;
722
            action.m_action = ChaserNextStep;
6✔
723
            action.m_masterIntensity = intensity();
6✔
724
            action.m_stepIntensity = getPrimaryIntensity();
6✔
725
            action.m_fadeMode = getFadeMode();
6✔
726
            ch->setAction(action);
6✔
727
        }
728
    }
729
    else
730
    {
731
        switch (m_nextPrevBehavior)
3✔
732
        {
733
            case DefaultRunFirst:
3✔
734
                startChaser(getFirstIndex());
3✔
735
            break;
3✔
736
            case RunNext:
×
737
                startChaser(getNextIndex());
×
738
            break;
×
739
            case Select:
×
740
                m_tree->setCurrentItem(m_tree->topLevelItem(getNextIndex()));
×
741
            break;
×
742
            case Nothing:
×
743
            break;
×
744
            default:
×
745
                Q_ASSERT(false);
×
746
        }
747
    }
748
}
749

750
void VCCueList::slotPreviousCue()
8✔
751
{
752
    if (mode() != Doc::Operate)
8✔
753
        return;
1✔
754

755
    Chaser *ch = chaser();
7✔
756
    if (ch == NULL)
7✔
757
        return;
×
758

759
    if (ch->isRunning())
7✔
760
    {
761
        if (ch->isPaused())
7✔
762
        {
763
            m_tree->setCurrentItem(m_tree->topLevelItem(getPrevIndex()));
×
764
        }
765
        else
766
        {
767
            ChaserAction action;
768
            action.m_action = ChaserPreviousStep;
7✔
769
            action.m_masterIntensity = intensity();
7✔
770
            action.m_stepIntensity = getPrimaryIntensity();
7✔
771
            action.m_fadeMode = getFadeMode();
7✔
772
            ch->setAction(action);
7✔
773
        }
774
    }
775
    else
776
    {
777
        switch (m_nextPrevBehavior)
×
778
        {
779
            case DefaultRunFirst:
×
780
                startChaser(getLastIndex());
×
781
            break;
×
782
            case RunNext:
×
783
                startChaser(getPrevIndex());
×
784
            break;
×
785
            case Select:
×
786
                m_tree->setCurrentItem(m_tree->topLevelItem(getPrevIndex()));
×
787
            break;
×
788
            case Nothing:
×
789
            break;
×
790
            default:
×
791
                Q_ASSERT(false);
×
792
        }
793
    }
794
}
795

796
void VCCueList::slotCurrentStepChanged(int stepNumber)
19✔
797
{
798
    // Chaser is being edited, channels count may change.
799
    // Wait for the CueList to update its steps.
800
    if (m_updateTimer->isActive())
19✔
801
        return;
×
802

803
    Q_ASSERT(stepNumber < m_tree->topLevelItemCount() && stepNumber >= 0);
19✔
804
    QTreeWidgetItem *item = m_tree->topLevelItem(stepNumber);
19✔
805
    Q_ASSERT(item != NULL);
19✔
806
    m_tree->scrollToItem(item, QAbstractItemView::PositionAtCenter);
19✔
807
    m_tree->setCurrentItem(item);
19✔
808
    m_primaryIndex = stepNumber;
19✔
809
    if (sideFaderMode() == Steps)
19✔
810
    {
811
        m_bottomStepLabel->setStyleSheet(cfLabelBlueStyle);
×
812
        m_bottomStepLabel->setText(QString("#%1").arg(m_primaryIndex + 1));
×
813

814
        float stepVal;
815
        int stepsCount = m_tree->topLevelItemCount();
×
816
        if (stepsCount < 256)
×
817
            stepVal = 255.0 / (float)stepsCount;
×
818
        else
819
            stepVal = 1.0;
×
820
        int slValue = (stepVal * (float)stepNumber);
×
821
        if (slValue > 255)
×
822
            slValue = 255;
×
823

824
        int upperBound = 255 - slValue;
×
825
        int lowerBound = qFloor(upperBound - stepVal);
×
826
        //qDebug() << "Slider value:" << m_slider1->value() << "Step range:" << (255 - slValue) << (255 - slValue - stepVal);
827
        // if the Step slider is already in range, then do not set its value
828
        // this means a user interaction is going on, either with the mouse or external controller
829
        if (m_sideFader->value() < lowerBound || m_sideFader->value() >= upperBound)
×
830
        {
831
            m_sideFader->blockSignals(true);
×
832
            m_sideFader->setValue(upperBound);
×
833
            m_topPercentageLabel->setText(QString("%1").arg(slValue));
×
834
            m_sideFader->blockSignals(false);
×
835
        }
836
    }
837
    else
838
    {
839
        setFaderInfo(m_primaryIndex);
19✔
840
    }
841
    emit stepChanged(m_primaryIndex);
19✔
842
    emit sideFaderValueChanged();
19✔
843
}
844

845
void VCCueList::slotItemActivated(QTreeWidgetItem *item)
5✔
846
{
847
    if (mode() != Doc::Operate)
5✔
848
        return;
1✔
849

850
    playCueAtIndex(m_tree->indexOfTopLevelItem(item));
4✔
851
}
852

853
void VCCueList::slotItemChanged(QTreeWidgetItem *item, int column)
374✔
854
{
855
    if (m_listIsUpdating || column != COL_NOTES)
374✔
856
        return;
374✔
857

858
    Chaser *ch = chaser();
×
859
    if (ch == NULL)
×
860
        return;
×
861

862
    QString itemText = item->text(column);
×
863
    int idx = m_tree->indexOfTopLevelItem(item);
×
864
    ChaserStep step = ch->steps().at(idx);
×
865

866
    step.note = itemText;
×
867
    ch->replaceStep(step, idx);
×
868
}
869

870
void VCCueList::slotFunctionRunning(quint32 fid)
4✔
871
{
872
    if (fid != m_chaserID)
4✔
873
        return;
×
874

875
    if (playbackLayout() == PlayPauseStop)
4✔
876
        m_playbackButton->setIcon(QIcon(":/player_pause.png"));
4✔
877
    else if (playbackLayout() == PlayStopPause)
×
878
        m_playbackButton->setIcon(QIcon(":/player_stop.png"));
×
879
    m_timer->start(PROGRESS_INTERVAL);
4✔
880
    updateFeedback();
4✔
881
}
882

883
void VCCueList::slotFunctionStopped(quint32 fid)
14✔
884
{
885
    if (fid != m_chaserID)
14✔
886
        return;
×
887

888
    m_playbackButton->setIcon(QIcon(":/player_play.png"));
14✔
889
    m_topStepLabel->setText("");
14✔
890
    m_topStepLabel->setStyleSheet(cfLabelNoStyle);
14✔
891
    m_bottomStepLabel->setText("");
14✔
892
    m_bottomStepLabel->setStyleSheet(cfLabelNoStyle);
14✔
893
    // reset any previously set background
894
    QTreeWidgetItem *item = m_tree->topLevelItem(m_secondaryIndex);
14✔
895
    if (item != NULL)
14✔
896
        item->setBackground(COL_NUM, m_defCol);
11✔
897

898
    emit stepChanged(-1);
14✔
899

900
    m_progress->setFormat("");
14✔
901
    m_progress->setValue(0);    
14✔
902

903
    emit progressStateChanged();
14✔
904
    emit sideFaderValueChanged();
14✔
905

906
    qDebug() << Q_FUNC_INFO << "Cue stopped";
14✔
907
    updateFeedback();
14✔
908
}
909

910
void VCCueList::slotProgressTimeout()
×
911
{
912
    Chaser *ch = chaser();
×
913
    if (ch == NULL || !ch->isRunning())
×
914
        return;
×
915

916
    ChaserRunnerStep step(ch->currentRunningStep());
×
917
    if (step.m_function != NULL)
×
918
    {
919
        int status = m_progress->property("status").toInt();
×
920
        int newstatus;
921
        if (step.m_fadeIn == Function::defaultSpeed())
×
922
            newstatus = 1;
×
923
        else if (step.m_elapsed > (quint32)step.m_fadeIn)
×
924
            newstatus = 1;
×
925
        else
926
            newstatus = 0;
×
927

928
        if (newstatus != status)
×
929
        {
930
            if (newstatus == 0)
×
931
                m_progress->setStyleSheet(progressFadeStyle);
×
932
            else
933
                m_progress->setStyleSheet(progressHoldStyle);
×
934
            m_progress->setProperty("status", newstatus);
×
935
        }
936
        if (step.m_duration == Function::infiniteSpeed())
×
937
        {
938
            if (newstatus == 0 && step.m_fadeIn != Function::defaultSpeed())
×
939
            {
940
                double progress = ((double)step.m_elapsed / (double)step.m_fadeIn) * (double)m_progress->width();
×
941
                m_progress->setFormat(QString("-%1").arg(Function::speedToString(step.m_fadeIn - step.m_elapsed)));
×
942
                m_progress->setValue(progress);
×
943

NEW
944
                emit progressStateChanged();
×
945
            }
946
            else
947
            {
948
                m_progress->setValue(m_progress->maximum());
×
949
                m_progress->setFormat("");
×
950

NEW
951
                emit progressStateChanged();
×
952
            }
953
            return;
×
954
        }
955
        else
956
        {
957
            double progress = ((double)step.m_elapsed / (double)step.m_duration) * (double)m_progress->width();
×
958
            m_progress->setFormat(QString("-%1").arg(Function::speedToString(step.m_duration - step.m_elapsed)));
×
959
            m_progress->setValue(progress);
×
960

NEW
961
            emit progressStateChanged();
×
962
        }
963
    }
964
    else
965
    {
966
        m_progress->setValue(0);
×
967
    }
968
}
969

NEW
970
QString VCCueList::progressText()
×
971
{
NEW
972
    return m_progress->text();
×
973
}
974

NEW
975
double VCCueList::progressPercent()
×
976
{
NEW
977
    return ((double)m_progress->value() * 100) / (double)m_progress->width();
×
978
}
979

980
void VCCueList::startChaser(int startIndex)
4✔
981
{
982
    Chaser *ch = chaser();
4✔
983
    if (ch == NULL)
4✔
984
        return;
×
985

986
    adjustFunctionIntensity(ch, intensity());
4✔
987

988
    ChaserAction action;
989
    action.m_action = ChaserSetStepIndex;
4✔
990
    action.m_stepIndex = startIndex;
4✔
991
    action.m_masterIntensity = intensity();
4✔
992
    action.m_stepIntensity = getPrimaryIntensity();
4✔
993
    action.m_fadeMode = getFadeMode();
4✔
994
    ch->setAction(action);
4✔
995

996
    ch->start(m_doc->masterTimer(), functionParent());
4✔
997
    emit functionStarting(m_chaserID);
4✔
998
}
999

1000
void VCCueList::stopChaser()
×
1001
{
1002
    Chaser *ch = chaser();
×
1003
    if (ch == NULL)
×
1004
        return;
×
1005

1006
    ch->stop(functionParent());
×
1007
    resetIntensityOverrideAttribute();
×
1008
}
1009

1010
int VCCueList::getFadeMode()
20✔
1011
{
1012
    if (sideFaderMode() != Crossfade)
20✔
1013
        return Chaser::FromFunction;
20✔
1014

1015
    if (m_sideFader->value() != 0 && m_sideFader->value() != 100)
×
1016
        return Chaser::BlendedCrossfade;
×
1017

1018
    return Chaser::Blended;
×
1019
}
1020

1021
void VCCueList::setNextPrevBehavior(NextPrevBehavior nextPrev)
×
1022
{
1023
    Q_ASSERT(nextPrev == DefaultRunFirst
×
1024
            || nextPrev == RunNext
1025
            || nextPrev == Select
1026
            || nextPrev == Nothing);
1027
    m_nextPrevBehavior = nextPrev;
×
1028
}
×
1029

1030
VCCueList::NextPrevBehavior VCCueList::nextPrevBehavior() const
1✔
1031
{
1032
    return m_nextPrevBehavior;
1✔
1033
}
1034

1035
void VCCueList::setPlaybackLayout(VCCueList::PlaybackLayout layout)
×
1036
{
1037
    if (layout == m_playbackLayout)
×
1038
        return;
×
1039

1040
    if (layout == PlayStopPause)
×
1041
    {
1042
        m_stopButton->setIcon(QIcon(":/player_pause.png"));
×
1043
        m_playbackButton->setToolTip(tr("Play/Stop Cue list"));
×
1044
        m_stopButton->setToolTip(tr("Pause Cue list"));
×
1045
    }
1046
    else if (layout == PlayPauseStop)
×
1047
    {
1048
        m_stopButton->setIcon(QIcon(":/player_stop.png"));
×
1049
        m_playbackButton->setToolTip(tr("Play/Pause Cue list"));
×
1050
        m_stopButton->setToolTip(tr("Stop Cue list"));
×
1051
    }
1052
    else
1053
    {
1054
        qWarning() << "Playback layout" << layout << "doesn't exist!";
×
1055
        layout = PlayPauseStop;
×
1056
    }
1057

1058
    m_playbackLayout = layout;
×
1059
}
1060

1061
VCCueList::PlaybackLayout VCCueList::playbackLayout() const
7✔
1062
{
1063
    return m_playbackLayout;
7✔
1064
}
1065

1066
VCCueList::FaderMode VCCueList::sideFaderMode() const
67✔
1067
{
1068
    return m_slidersMode;
67✔
1069
}
1070

1071
void VCCueList::setSideFaderMode(VCCueList::FaderMode mode)
3✔
1072
{
1073
    m_slidersMode = mode;
3✔
1074

1075
    bool show = (mode == None) ? false : true;
3✔
1076
    m_crossfadeButton->setVisible(show);
3✔
1077
    m_topPercentageLabel->setVisible(show);
3✔
1078
    m_topStepLabel->setVisible(mode == Steps ? false : show);
3✔
1079
    m_sideFader->setVisible(show);
3✔
1080
    m_bottomPercentageLabel->setVisible(mode == Steps ? false : show);
3✔
1081
    m_bottomStepLabel->setVisible(show);
3✔
1082
    m_sideFader->setMaximum(mode == Steps ? 255 : 100);
3✔
1083
    m_sideFader->setValue(mode == Steps ? 255 : 100);
3✔
1084
}
3✔
1085

1086
VCCueList::FaderMode VCCueList::stringToFaderMode(QString modeStr)
×
1087
{
1088
    if (modeStr == "Crossfade")
×
1089
        return Crossfade;
×
1090
    else if (modeStr == "Steps")
×
1091
        return Steps;
×
1092

1093
    return None;
×
1094
}
1095

1096
QString VCCueList::faderModeToString(VCCueList::FaderMode mode)
1✔
1097
{
1098
    if (mode == Crossfade)
1✔
1099
        return "Crossfade";
1✔
1100
    else if (mode == Steps)
×
1101
        return "Steps";
×
1102

1103
    return "None";
×
1104
}
1105

1106
/*****************************************************************************
1107
 * Crossfade
1108
 *****************************************************************************/
1109
void VCCueList::setFaderInfo(int index)
19✔
1110
{
1111
    Chaser *ch = chaser();
19✔
1112
    if (ch == NULL || !ch->isRunning())
19✔
1113
        return;
×
1114

1115
    int tmpIndex = ch->computeNextStep(index);
19✔
1116

1117
    m_topStepLabel->setText(QString("#%1").arg(m_primaryTop ? index + 1 : tmpIndex + 1));
19✔
1118
    m_topStepLabel->setStyleSheet(m_primaryTop ? cfLabelBlueStyle : cfLabelOrangeStyle);
19✔
1119

1120
    m_bottomStepLabel->setText(QString("#%1").arg(m_primaryTop ? tmpIndex + 1 : index + 1));
19✔
1121
    m_bottomStepLabel->setStyleSheet(m_primaryTop ? cfLabelOrangeStyle : cfLabelBlueStyle);
19✔
1122

1123
    // reset any previously set background
1124
    QTreeWidgetItem *item = m_tree->topLevelItem(m_secondaryIndex);
19✔
1125
    if (item != NULL)
19✔
1126
        item->setBackground(COL_NUM, m_defCol);
19✔
1127

1128
    item = m_tree->topLevelItem(tmpIndex);
19✔
1129
    if (item != NULL)
19✔
1130
        item->setBackground(COL_NUM, QColor("#FF8000"));
19✔
1131
    m_secondaryIndex = tmpIndex;
19✔
1132

1133
    emit sideFaderValueChanged();
19✔
1134
}
1135

1136
void VCCueList::slotShowCrossfadePanel(bool enable)
15✔
1137
{
1138
    m_topPercentageLabel->setVisible(enable);
15✔
1139
    m_topStepLabel->setVisible(enable);
15✔
1140
    m_sideFader->setVisible(enable);
15✔
1141
    m_bottomStepLabel->setVisible(enable);
15✔
1142
    m_bottomPercentageLabel->setVisible(enable);
15✔
1143

1144
    emit sideFaderButtonToggled();
15✔
1145
}
15✔
1146

NEW
1147
QString VCCueList::topPercentageValue()
×
1148
{
NEW
1149
    return m_topPercentageLabel->text();
×
1150
}
1151

NEW
1152
QString VCCueList::bottomPercentageValue()
×
1153
{
NEW
1154
    return m_bottomPercentageLabel->text();
×
1155
}
1156

NEW
1157
QString VCCueList::topStepValue()
×
1158
{
NEW
1159
    return m_topStepLabel->text();
×
1160
}
1161

NEW
1162
QString VCCueList::bottomStepValue()
×
1163
{
NEW
1164
    return m_bottomStepLabel->text();
×
1165
}
1166

NEW
1167
int VCCueList::sideFaderValue()
×
1168
{
NEW
1169
    return m_sideFader->value();
×
1170
}
1171

NEW
1172
bool VCCueList::primaryTop()
×
1173
{
NEW
1174
    return m_primaryTop;
×
1175
}
1176

NEW
1177
void VCCueList::slotSideFaderButtonChecked(bool enable)
×
1178
{
NEW
1179
    m_crossfadeButton->setChecked(enable);
×
NEW
1180
}
×
1181

NEW
1182
bool VCCueList::isSideFaderVisible()
×
1183
{
NEW
1184
    return m_sideFader->isVisible();
×
1185
}
1186

NEW
1187
bool VCCueList::sideFaderButtonChecked()
×
1188
{
NEW
1189
    return m_crossfadeButton->isChecked();
×
1190
}
1191

NEW
1192
void VCCueList::slotSetSideFaderValue(int value)
×
1193
{
NEW
1194
    m_sideFader->setValue(value);
×
UNCOV
1195
}
×
1196

1197
void VCCueList::slotSideFaderValueChanged(int value)
×
1198
{
1199
    if (sideFaderMode() == Steps)
×
1200
    {
1201
        value = 255 - value;
×
1202
        m_topPercentageLabel->setText(QString("%1").arg(value));
×
1203

NEW
1204
        emit sideFaderValueChanged();
×
1205

1206
        Chaser *ch = chaser();
×
1207
        if (ch == NULL || ch->stopped())
×
1208
            return;
×
1209

1210
        int newStep = value; // by default we assume the Chaser has more than 256 steps
×
1211
        if (ch->stepsCount() < 256)
×
1212
        {
1213
            float stepSize = 255.0 / (float)ch->stepsCount();
×
1214
            if(value >= 255.0 - stepSize)
×
1215
                newStep = ch->stepsCount() - 1;
×
1216
            else
1217
                newStep = qFloor((float)value / stepSize);
×
1218
        }
1219
        //qDebug() << "value:" << value << "steps:" << ch->stepsCount() << "new step:" << newStep;
1220

1221
        if (newStep == ch->currentStepIndex())
×
1222
            return;
×
1223

1224
        ChaserAction action;
1225
        action.m_action = ChaserSetStepIndex;
×
1226
        action.m_stepIndex = newStep;
×
1227
        action.m_masterIntensity = intensity();
×
1228
        action.m_stepIntensity = getPrimaryIntensity();
×
1229
        action.m_fadeMode = getFadeMode();
×
1230
        ch->setAction(action);
×
1231
    }
1232
    else
1233
    {
1234
        m_topPercentageLabel->setText(QString("%1%").arg(value));
×
1235
        m_bottomPercentageLabel->setText(QString("%1%").arg(100 - value));
×
1236

NEW
1237
        emit sideFaderValueChanged();
×
1238

1239
        Chaser *ch = chaser();
×
1240
        if (!(ch == NULL || ch->stopped()))
×
1241
        {
1242
            ch->adjustStepIntensity(qreal(value) / 100.0, m_primaryTop ? m_primaryIndex : m_secondaryIndex,
×
1243
                                    Chaser::FadeControlMode(getFadeMode()));
×
1244
            ch->adjustStepIntensity(qreal(100 - value) / 100.0, m_primaryTop ? m_secondaryIndex : m_primaryIndex,
×
1245
                                    Chaser::FadeControlMode(getFadeMode()));
×
1246
            stopStepIfNeeded(ch);
×
1247
        }
1248
    }
1249

1250
    updateFeedback();
×
1251
}
1252

1253
void VCCueList::stopStepIfNeeded(Chaser *ch)
×
1254
{
1255
    if (ch->runningStepsNumber() != 2)
×
1256
        return;
×
1257

1258
    int primaryValue = m_primaryTop ? m_sideFader->value() : 100 - m_sideFader->value();
×
1259
    int secondaryValue = m_primaryTop ? 100 - m_sideFader->value() : m_sideFader->value();
×
1260

1261
    ChaserAction action;
1262
    action.m_action = ChaserStopStep;
×
1263

1264
    if (primaryValue == 0)
×
1265
    {
1266
        m_primaryTop = !m_primaryTop;
×
1267
        action.m_stepIndex = m_primaryIndex;
×
1268
        ch->setAction(action);
×
1269
    }
1270
    else if (secondaryValue == 0)
×
1271
    {
1272
        action.m_stepIndex = m_secondaryIndex;
×
1273
        ch->setAction(action);
×
1274
    }
1275
}
1276

1277
/*****************************************************************************
1278
 * Key Sequences
1279
 *****************************************************************************/
1280

1281
void VCCueList::setNextKeySequence(const QKeySequence& keySequence)
6✔
1282
{
1283
    m_nextKeySequence = QKeySequence(keySequence);
6✔
1284
}
6✔
1285

1286
QKeySequence VCCueList::nextKeySequence() const
8✔
1287
{
1288
    return m_nextKeySequence;
8✔
1289
}
1290

1291
void VCCueList::setPreviousKeySequence(const QKeySequence& keySequence)
6✔
1292
{
1293
    m_previousKeySequence = QKeySequence(keySequence);
6✔
1294
}
6✔
1295

1296
QKeySequence VCCueList::previousKeySequence() const
8✔
1297
{
1298
    return m_previousKeySequence;
8✔
1299
}
1300

1301
void VCCueList::setPlaybackKeySequence(const QKeySequence& keySequence)
6✔
1302
{
1303
    m_playbackKeySequence = QKeySequence(keySequence);
6✔
1304
}
6✔
1305

1306
QKeySequence VCCueList::playbackKeySequence() const
8✔
1307
{
1308
    return m_playbackKeySequence;
8✔
1309
}
1310

1311
void VCCueList::setStopKeySequence(const QKeySequence &keySequence)
3✔
1312
{
1313
    m_stopKeySequence = QKeySequence(keySequence);
3✔
1314
}
3✔
1315

1316
QKeySequence VCCueList::stopKeySequence() const
3✔
1317
{
1318
    return m_stopKeySequence;
3✔
1319
}
1320

1321
void VCCueList::slotKeyPressed(const QKeySequence& keySequence)
7✔
1322
{
1323
    if (acceptsInput() == false)
7✔
1324
        return;
×
1325

1326
    if (m_nextKeySequence == keySequence)
7✔
1327
        slotNextCue();
3✔
1328
    else if (m_previousKeySequence == keySequence)
4✔
1329
        slotPreviousCue();
2✔
1330
    else if (m_playbackKeySequence == keySequence)
2✔
1331
        slotPlayback();
1✔
1332
    else if (m_stopKeySequence == keySequence)
1✔
1333
        slotStop();
×
1334
}
1335

1336
void VCCueList::updateFeedback()
25✔
1337
{
1338
    int fbv = int(SCALE(float(m_sideFader->value()), 
25✔
1339
                        float(m_sideFader->minimum()),
1340
                        float(m_sideFader->maximum()), 
1341
                        float(0), float(UCHAR_MAX)));
25✔
1342
    sendFeedback(fbv, sideFaderInputSourceId);
25✔
1343

1344
    Chaser *ch = chaser();
25✔
1345
    if (ch == NULL)
25✔
1346
        return;
3✔
1347

1348
    sendFeedback(ch->isRunning() ? UCHAR_MAX : 0, playbackInputSourceId);
22✔
1349
}
1350

1351
/*****************************************************************************
1352
 * External Input
1353
 *****************************************************************************/
1354

1355
void VCCueList::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
12✔
1356
{
1357
    /* Don't let input data through in design mode or if disabled */
1358
    if (acceptsInput() == false)
12✔
1359
        return;
×
1360

1361
    quint32 pagedCh = (page() << 16) | channel;
12✔
1362

1363
    if (checkInputSource(universe, pagedCh, value, sender(), nextInputSourceId))
12✔
1364
    {
1365
        // Use hysteresis for values, in case the cue list is being controlled
1366
        // by a slider. The value has to go to zero before the next non-zero
1367
        // value is accepted as input. And the non-zero values have to visit
1368
        // above $HYSTERESIS before a zero is accepted again.
1369
        if (m_nextLatestValue == 0 && value > 0)
3✔
1370
        {
1371
            slotNextCue();
2✔
1372
            m_nextLatestValue = value;
2✔
1373
        }
1374
        else if (m_nextLatestValue > HYSTERESIS && value == 0)
1✔
1375
        {
1376
            m_nextLatestValue = 0;
1✔
1377
        }
1378

1379
        if (value > HYSTERESIS)
3✔
1380
            m_nextLatestValue = value;
2✔
1381
    }
1382
    else if (checkInputSource(universe, pagedCh, value, sender(), previousInputSourceId))
9✔
1383
    {
1384
        // Use hysteresis for values, in case the cue list is being controlled
1385
        // by a slider. The value has to go to zero before the next non-zero
1386
        // value is accepted as input. And the non-zero values have to visit
1387
        // above $HYSTERESIS before a zero is accepted again.
1388
        if (m_previousLatestValue == 0 && value > 0)
3✔
1389
        {
1390
            slotPreviousCue();
2✔
1391
            m_previousLatestValue = value;
2✔
1392
        }
1393
        else if (m_previousLatestValue > HYSTERESIS && value == 0)
1✔
1394
        {
1395
            m_previousLatestValue = 0;
1✔
1396
        }
1397

1398
        if (value > HYSTERESIS)
3✔
1399
            m_previousLatestValue = value;
2✔
1400
    }
1401
    else if (checkInputSource(universe, pagedCh, value, sender(), playbackInputSourceId))
6✔
1402
    {
1403
        // Use hysteresis for values, in case the cue list is being controlled
1404
        // by a slider. The value has to go to zero before the next non-zero
1405
        // value is accepted as input. And the non-zero values have to visit
1406
        // above $HYSTERESIS before a zero is accepted again.
1407
        if (m_playbackLatestValue == 0 && value > 0)
2✔
1408
        {
1409
            slotPlayback();
1✔
1410
            m_playbackLatestValue = value;
1✔
1411
        }
1412
        else if (m_playbackLatestValue > HYSTERESIS && value == 0)
1✔
1413
        {
1414
            m_playbackLatestValue = 0;
1✔
1415
        }
1416

1417
        if (value > HYSTERESIS)
2✔
1418
            m_playbackLatestValue = value;
1✔
1419
    }
1420
    else if (checkInputSource(universe, pagedCh, value, sender(), stopInputSourceId))
4✔
1421
    {
1422
        // Use hysteresis for values, in case the cue list is being controlled
1423
        // by a slider. The value has to go to zero before the next non-zero
1424
        // value is accepted as input. And the non-zero values have to visit
1425
        // above $HYSTERESIS before a zero is accepted again.
1426
        if (m_stopLatestValue == 0 && value > 0)
×
1427
        {
1428
            slotStop();
×
1429
            m_stopLatestValue = value;
×
1430
        }
1431
        else if (m_stopLatestValue > HYSTERESIS && value == 0)
×
1432
        {
1433
            m_stopLatestValue = 0;
×
1434
        }
1435

1436
        if (value > HYSTERESIS)
×
1437
            m_stopLatestValue = value;
×
1438
    }
1439
    else if (checkInputSource(universe, pagedCh, value, sender(), sideFaderInputSourceId))
4✔
1440
    {
1441
        if (sideFaderMode() == None)
×
1442
            return;
×
1443

1444
        float val = SCALE((float) value, (float) 0, (float) UCHAR_MAX,
×
1445
                          (float) m_sideFader->minimum(),
1446
                          (float) m_sideFader->maximum());
1447
        m_sideFader->setValue(val);
×
1448
    }
1449
}
1450

1451
/*****************************************************************************
1452
 * VCWidget-inherited methods
1453
 *****************************************************************************/
1454

1455
void VCCueList::adjustIntensity(qreal val)
×
1456
{
1457
    Chaser *ch = chaser();
×
1458
    if (ch != NULL)
×
1459
    {
1460
        adjustFunctionIntensity(ch, val);
×
1461
/*
1462
        // Refresh intensity of current steps
1463
        if (!ch->stopped() && sideFaderMode() == Crossfade && m_sideFader->value() != 100)
1464
        {
1465
                ch->adjustStepIntensity((qreal)m_sideFader->value() / 100, m_primaryTop ? m_primaryIndex : m_secondaryIndex);
1466
                ch->adjustStepIntensity((qreal)(100 - m_sideFader->value()) / 100, m_primaryTop ? m_secondaryIndex : m_primaryIndex);
1467
        }
1468
*/
1469
    }
1470

1471
    VCWidget::adjustIntensity(val);
×
1472
}
×
1473

1474
void VCCueList::setCaption(const QString& text)
20✔
1475
{
1476
    VCWidget::setCaption(text);
20✔
1477

1478
    QStringList list;
40✔
1479
    list << "#" << text << tr("Fade In") << tr("Fade Out") << tr("Duration") << tr("Notes");
20✔
1480
    m_tree->setHeaderLabels(list);
20✔
1481
}
20✔
1482

1483
void VCCueList::setFont(const QFont& font)
1✔
1484
{
1485
    VCWidget::setFont(font);
1✔
1486

1487
    QFontMetrics m_fm = QFontMetrics(font);
2✔
1488
#if (QT_VERSION < QT_VERSION_CHECK(5, 11, 0))
1489
    int w = m_fm.width("100%");
1490
#else
1491
    int w = m_fm.horizontalAdvance("100%");
1✔
1492
#endif
1493
    m_topPercentageLabel->setFixedWidth(w);
1✔
1494
    m_bottomPercentageLabel->setFixedWidth(w);
1✔
1495
}
1✔
1496

1497
void VCCueList::slotModeChanged(Doc::Mode mode)
23✔
1498
{
1499
    bool enable = false;
23✔
1500
    if (mode == Doc::Operate)
23✔
1501
    {
1502
        m_progress->setStyleSheet(progressFadeStyle);
6✔
1503
        m_progress->setRange(0, m_progress->width());
6✔
1504
        enable = true;
6✔
1505
        // send the initial feedback for the current step slider
1506
        updateFeedback();
6✔
1507
    }
1508
    else
1509
    {
1510
        m_topStepLabel->setStyleSheet(cfLabelNoStyle);
17✔
1511
        m_topStepLabel->setText("");
17✔
1512
        m_bottomStepLabel->setStyleSheet(cfLabelNoStyle);
17✔
1513
        m_bottomStepLabel->setText("");
17✔
1514
        m_progress->setStyleSheet(progressDisabledStyle);
17✔
1515
        // reset any previously set background
1516
        QTreeWidgetItem *item = m_tree->topLevelItem(m_secondaryIndex);
17✔
1517
        if (item != NULL)
17✔
1518
            item->setBackground(COL_NUM, m_defCol);
2✔
1519
    }
1520

1521
    enableWidgetUI(enable);
23✔
1522

1523
    /* Always start from the beginning */
1524
    m_tree->setCurrentItem(NULL);
23✔
1525

1526
    VCWidget::slotModeChanged(mode);
23✔
1527

1528
    emit sideFaderValueChanged();
23✔
1529
}
23✔
1530

1531
void VCCueList::editProperties()
×
1532
{
1533
    VCCueListProperties prop(this, m_doc);
×
1534
    if (prop.exec() == QDialog::Accepted)
×
1535
        m_doc->setModified();
×
1536
}
×
1537

1538
void VCCueList::playCueAtIndex(int idx)
4✔
1539
{
1540
    if (mode() != Doc::Operate)
4✔
1541
        return;
×
1542

1543
    m_primaryIndex = idx;
4✔
1544

1545
    Chaser *ch = chaser();
4✔
1546
    if (ch == NULL)
4✔
1547
        return;
×
1548

1549
    if (ch->isRunning())
4✔
1550
    {
1551
        ChaserAction action;
1552
        action.m_action = ChaserSetStepIndex;
3✔
1553
        action.m_stepIndex = m_primaryIndex;
3✔
1554
        action.m_masterIntensity = intensity();
3✔
1555
        action.m_stepIntensity = getPrimaryIntensity();
3✔
1556
        action.m_fadeMode = getFadeMode();
3✔
1557
        ch->setAction(action);
3✔
1558
    }
1559
    else
1560
    {
1561
        startChaser(m_primaryIndex);
1✔
1562
    }
1563

1564
    if (sideFaderMode() == Crossfade)
4✔
1565
        setFaderInfo(m_primaryIndex);
×
1566
}
1567

1568
FunctionParent VCCueList::functionParent() const
4✔
1569
{
1570
    return FunctionParent(FunctionParent::ManualVCWidget, id());
4✔
1571
}
1572

1573
/*****************************************************************************
1574
 * Load & Save
1575
 *****************************************************************************/
1576

1577
bool VCCueList::loadXML(QXmlStreamReader &root)
3✔
1578
{
1579
    QList <quint32> legacyStepList;
6✔
1580

1581
    if (root.name() != KXMLQLCVCCueList)
3✔
1582
    {
1583
        qWarning() << Q_FUNC_INFO << "CueList node not found";
1✔
1584
        return false;
1✔
1585
    }
1586

1587
    /* Widget commons */
1588
    loadXMLCommon(root);
2✔
1589

1590
    /* Children */
1591
    while (root.readNextStartElement())
18✔
1592
    {
1593
        if (root.name() == KXMLQLCWindowState)
16✔
1594
        {
1595
            bool visible = false;
1✔
1596
            int x = 0, y = 0, w = 0, h = 0;
1✔
1597
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
1✔
1598
            setGeometry(x, y, w, h);
1✔
1599
        }
1600
        else if (root.name() == KXMLQLCVCWidgetAppearance)
15✔
1601
        {
1602
            loadXMLAppearance(root);
1✔
1603
        }
1604
        else if (root.name() == KXMLQLCVCCueListNext)
14✔
1605
        {
1606
            QString str = loadXMLSources(root, nextInputSourceId);
2✔
1607
            if (str.isEmpty() == false)
1✔
1608
                m_nextKeySequence = stripKeySequence(QKeySequence(str));
1✔
1609
        }
1610
        else if (root.name() == KXMLQLCVCCueListPrevious)
13✔
1611
        {
1612
            QString str = loadXMLSources(root, previousInputSourceId);
2✔
1613
            if (str.isEmpty() == false)
1✔
1614
                m_previousKeySequence = stripKeySequence(QKeySequence(str));
1✔
1615
        }
1616
        else if (root.name() == KXMLQLCVCCueListPlayback)
12✔
1617
        {
1618
            QString str = loadXMLSources(root, playbackInputSourceId);
2✔
1619
            if (str.isEmpty() == false)
1✔
1620
                m_playbackKeySequence = stripKeySequence(QKeySequence(str));
1✔
1621
        }
1622
        else if (root.name() == KXMLQLCVCCueListStop)
11✔
1623
        {
1624
            QString str = loadXMLSources(root, stopInputSourceId);
2✔
1625
            if (str.isEmpty() == false)
1✔
1626
                m_stopKeySequence = stripKeySequence(QKeySequence(str));
1✔
1627
        }
1628
        else if (root.name() == KXMLQLCVCCueListSlidersMode)
10✔
1629
        {
1630
            setSideFaderMode(stringToFaderMode(root.readElementText()));
×
1631
        }
1632
        else if (root.name() == KXMLQLCVCCueListCrossfadeLeft)
10✔
1633
        {
1634
            loadXMLSources(root, sideFaderInputSourceId);
×
1635
        }
1636
        else if (root.name() == KXMLQLCVCCueListCrossfadeRight) /* Legacy */
10✔
1637
        {
1638
            root.skipCurrentElement();
×
1639
        }
1640
        else if (root.name() == KXMLQLCVCWidgetKey) /* Legacy */
10✔
1641
        {
1642
            setNextKeySequence(QKeySequence(root.readElementText()));
×
1643
        }
1644
        else if (root.name() == KXMLQLCVCCueListChaser)
10✔
1645
        {
1646
            setChaser(root.readElementText().toUInt());
×
1647
        }
1648
        else if (root.name() == KXMLQLCVCCueListPlaybackLayout)
10✔
1649
        {
1650
            PlaybackLayout layout = PlaybackLayout(root.readElementText().toInt());
×
1651
            if (layout != PlayPauseStop && layout != PlayStopPause)
×
1652
            {
1653
                qWarning() << Q_FUNC_INFO << "Playback layout" << layout << "does not exist.";
×
1654
                layout = PlayPauseStop;
×
1655
            }
1656
            setPlaybackLayout(layout);
×
1657
        }
1658
        else if (root.name() == KXMLQLCVCCueListNextPrevBehavior)
10✔
1659
        {
1660
            NextPrevBehavior nextPrev = NextPrevBehavior(root.readElementText().toInt());
×
1661
            if (nextPrev != DefaultRunFirst
×
1662
                    && nextPrev != RunNext
×
1663
                    && nextPrev != Select
×
1664
                    && nextPrev != Nothing)
×
1665
            {
1666
                qWarning() << Q_FUNC_INFO << "Next/Prev behavior" << nextPrev << "does not exist.";
×
1667
                nextPrev = DefaultRunFirst;
×
1668
            }
1669
            setNextPrevBehavior(nextPrev);
×
1670
        }
1671
        else if (root.name() == KXMLQLCVCCueListCrossfade)
10✔
1672
        {
1673
            m_crossfadeButton->setChecked(true);
×
1674
            root.skipCurrentElement();
×
1675
        }
1676
        else if (root.name() == KXMLQLCVCCueListFunction)
10✔
1677
        {
1678
            // Collect legacy file format steps into a list
1679
            legacyStepList << root.readElementText().toUInt();
6✔
1680
        }
1681
        else
1682
        {
1683
            qWarning() << Q_FUNC_INFO << "Unknown cuelist tag:" << root.name().toString();
4✔
1684
            root.skipCurrentElement();
4✔
1685
        }
1686
    }
1687

1688
    if (legacyStepList.isEmpty() == false)
2✔
1689
    {
1690
        /* Construct a new chaser from legacy step functions and use that chaser */
1691
        Chaser *chaser = new Chaser(m_doc);
1✔
1692
        chaser->setName(caption());
1✔
1693

1694
        // Legacy cue lists relied on individual functions' timings and a common hold time
1695
        chaser->setFadeInMode(Chaser::Default);
1✔
1696
        chaser->setFadeOutMode(Chaser::Default);
1✔
1697
        chaser->setDurationMode(Chaser::Common);
1✔
1698

1699
        foreach (quint32 id, legacyStepList)
13✔
1700
        {
1701
            Function *function = m_doc->function(id);
6✔
1702
            if (function == NULL)
6✔
1703
                continue;
2✔
1704

1705
            // Legacy cuelists relied on individual functions' fadein/out speed and
1706
            // infinite duration. So don't touch them at all.
1707
            ChaserStep step(id);
8✔
1708
            chaser->addStep(step);
4✔
1709
        }
1710

1711
        // Add the chaser to Doc and attach it to the cue list
1712
        m_doc->addFunction(chaser);
1✔
1713
        setChaser(chaser->id());
1✔
1714
    }
1715

1716
    return true;
2✔
1717
}
1718

1719
bool VCCueList::saveXML(QXmlStreamWriter *doc)
1✔
1720
{
1721
    Q_ASSERT(doc != NULL);
1✔
1722

1723
    /* VC CueList entry */
1724
    doc->writeStartElement(KXMLQLCVCCueList);
1✔
1725

1726
    saveXMLCommon(doc);
1✔
1727

1728
    /* Window state */
1729
    saveXMLWindowState(doc);
1✔
1730

1731
    /* Appearance */
1732
    saveXMLAppearance(doc);
1✔
1733

1734
    /* Chaser */
1735
    doc->writeTextElement(KXMLQLCVCCueListChaser, QString::number(chaserID()));
1✔
1736

1737
    /* Playback layout */
1738
    if (playbackLayout() != PlayPauseStop)
1✔
1739
        doc->writeTextElement(KXMLQLCVCCueListPlaybackLayout, QString::number(playbackLayout()));
×
1740

1741
    /* Next/Prev behavior */
1742
    doc->writeTextElement(KXMLQLCVCCueListNextPrevBehavior, QString::number(nextPrevBehavior()));
1✔
1743

1744
    /* Next cue */
1745
    doc->writeStartElement(KXMLQLCVCCueListNext);
1✔
1746
    if (m_nextKeySequence.toString().isEmpty() == false)
1✔
1747
        doc->writeTextElement(KXMLQLCVCWidgetKey, m_nextKeySequence.toString());
1✔
1748
    saveXMLInput(doc, inputSource(nextInputSourceId));
1✔
1749
    doc->writeEndElement();
1✔
1750

1751
    /* Previous cue */
1752
    doc->writeStartElement(KXMLQLCVCCueListPrevious);
1✔
1753
    if (m_previousKeySequence.toString().isEmpty() == false)
1✔
1754
        doc->writeTextElement(KXMLQLCVCWidgetKey, m_previousKeySequence.toString());
1✔
1755
    saveXMLInput(doc, inputSource(previousInputSourceId));
1✔
1756
    doc->writeEndElement();
1✔
1757

1758
    /* Cue list playback */
1759
    doc->writeStartElement(KXMLQLCVCCueListPlayback);
1✔
1760
    if (m_playbackKeySequence.toString().isEmpty() == false)
1✔
1761
        doc->writeTextElement(KXMLQLCVCWidgetKey, m_playbackKeySequence.toString());
1✔
1762
    saveXMLInput(doc, inputSource(playbackInputSourceId));
1✔
1763
    doc->writeEndElement();
1✔
1764

1765
    /* Cue list stop */
1766
    doc->writeStartElement(KXMLQLCVCCueListStop);
1✔
1767
    if (m_stopKeySequence.toString().isEmpty() == false)
1✔
1768
        doc->writeTextElement(KXMLQLCVCWidgetKey, m_stopKeySequence.toString());
1✔
1769
    saveXMLInput(doc, inputSource(stopInputSourceId));
1✔
1770
    doc->writeEndElement();
1✔
1771

1772
    /* Crossfade cue list */
1773
    if (sideFaderMode() != None)
1✔
1774
        doc->writeTextElement(KXMLQLCVCCueListSlidersMode, faderModeToString(sideFaderMode()));
1✔
1775

1776
    QSharedPointer<QLCInputSource> cf1Src = inputSource(sideFaderInputSourceId);
1✔
1777
    if (!cf1Src.isNull() && cf1Src->isValid())
1✔
1778
    {
1779
        doc->writeStartElement(KXMLQLCVCCueListCrossfadeLeft);
×
1780
        saveXMLInput(doc, cf1Src);
×
1781
        doc->writeEndElement();
×
1782
    }
1783

1784
    /* End the <CueList> tag */
1785
    doc->writeEndElement();
1✔
1786

1787
    return true;
2✔
1788
}
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