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

mcallegari / qlcplus / 8961243534

05 May 2024 09:23PM UTC coverage: 32.068% (+4.0%) from 28.094%
8961243534

push

github

mcallegari
Merge branch 'master' into qmltoqt6

902 of 2557 new or added lines in 140 files covered. (35.28%)

166 existing lines in 76 files now uncovered.

15395 of 48008 relevant lines covered (32.07%)

22949.67 hits per line

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

0.0
/ui/src/chasereditor.cpp
1
/*
2
  Q Light Controller
3
  chasereditor.cpp
4

5
  Copyright (c) Heikki Junnila
6

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

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

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

20
#include <QTreeWidgetItem>
21
#include <QRadioButton>
22
#include <QHeaderView>
23
#include <QTreeWidget>
24
#include <QPushButton>
25
#include <QMessageBox>
26
#include <QLineEdit>
27
#include <QSettings>
28
#include <QDebug>
29
#include <QUrl>
30
#include <QAction>
31

32
#include "functionselection.h"
33
#include "speeddialwidget.h"
34
#include "chasereditor.h"
35
#include "mastertimer.h"
36
#include "chaserstep.h"
37
#include "sequence.h"
38
#include "apputil.h"
39
#include "chaser.h"
40
#include "scene.h"
41
#include "doc.h"
42

43
#define SETTINGS_GEOMETRY "chasereditor/geometry"
44
#define PROP_STEP Qt::UserRole
45

46
#define COL_NUM      0
47
#define COL_NAME     1
48
#define COL_FADEIN   2
49
#define COL_HOLD     3
50
#define COL_FADEOUT  4
51
#define COL_DURATION 5
52
#define COL_NOTES    6
53

54
ChaserEditor::ChaserEditor(QWidget* parent, Chaser* chaser, Doc* doc, bool liveMode)
×
55
    : QWidget(parent)
56
    , m_doc(doc)
57
    , m_chaser(chaser)
58
    , m_speedDials(NULL)
59
    , m_liveMode(liveMode)
×
60
{
61
    Q_ASSERT(chaser != NULL);
×
62
    Q_ASSERT(doc != NULL);
×
63

64
    setupUi(this);
×
65

66
    /* Disable editing of steps number */
67
    m_tree->setItemDelegateForColumn(COL_NUM, new NoEditDelegate(this));
×
68
    if (m_chaser->type() == Function::SequenceType)
×
69
        m_tree->header()->setSectionHidden(COL_NAME, true);
×
70

71
    m_cutAction = new QAction(QIcon(":/editcut.png"), tr("Cut"), this);
×
72
    m_cutButton->setDefaultAction(m_cutAction);
×
73
    m_cutAction->setShortcut(QKeySequence(QKeySequence::Cut));
×
74
    connect(m_cutAction, SIGNAL(triggered(bool)), this, SLOT(slotCutClicked()));
×
75

76
    m_copyAction = new QAction(QIcon(":/editcopy.png"), tr("Copy"), this);
×
77
    m_copyButton->setDefaultAction(m_copyAction);
×
78
    m_copyAction->setShortcut(QKeySequence(QKeySequence::Copy));
×
79
    connect(m_copyAction, SIGNAL(triggered(bool)), this, SLOT(slotCopyClicked()));
×
80

81
    m_pasteAction = new QAction(QIcon(":/editpaste.png"), tr("Paste"), this);
×
82
    m_pasteButton->setDefaultAction(m_pasteAction);
×
83
    m_pasteAction->setShortcut(QKeySequence(QKeySequence::Paste));
×
84
    connect(m_pasteAction, SIGNAL(triggered(bool)), this, SLOT(slotPasteClicked()));
×
85

86
    /* Name edit */
87
    m_nameEdit->setText(m_chaser->name());
×
88
    m_nameEdit->setSelection(0, m_nameEdit->text().length());
×
89

90
    /* Fade In Mode */
91
    switch (m_chaser->fadeInMode())
×
92
    {
93
    default:
×
94
    case Chaser::Default:
95
        m_fadeInDefaultRadio->setChecked(true);
×
96
        break;
×
97
    case Chaser::Common:
×
98
        m_fadeInCommonRadio->setChecked(true);
×
99
        break;
×
100
    case Chaser::PerStep:
×
101
        m_fadeInPerStepRadio->setChecked(true);
×
102
        break;
×
103
    }
104

105
    /* Fade Out Mode */
106
    switch (m_chaser->fadeOutMode())
×
107
    {
108
    default:
×
109
    case Chaser::Default:
110
        m_fadeOutDefaultRadio->setChecked(true);
×
111
        break;
×
112
    case Chaser::Common:
×
113
        m_fadeOutCommonRadio->setChecked(true);
×
114
        break;
×
115
    case Chaser::PerStep:
×
116
        m_fadeOutPerStepRadio->setChecked(true);
×
117
        break;
×
118
    }
119

120
    /* Duration Mode */
121
    switch (m_chaser->durationMode())
×
122
    {
123
    default:
×
124
    case Chaser::Default:
125
    case Chaser::Common:
126
        m_durationCommonRadio->setChecked(true);
×
127
        break;
×
128
    case Chaser::PerStep:
×
129
        m_durationPerStepRadio->setChecked(true);
×
130
        break;
×
131
    }
132

133
    /* Running order */
134
    switch (m_chaser->runOrder())
×
135
    {
136
    default:
×
137
    case Chaser::Loop:
138
        m_loop->setChecked(true);
×
139
        break;
×
140
    case Chaser::PingPong:
×
141
        m_pingPong->setChecked(true);
×
142
        break;
×
143
    case Chaser::SingleShot:
×
144
        m_singleShot->setChecked(true);
×
145
        break;
×
146
    case Chaser::Random:
×
147
        m_random->setChecked(true);
×
148
        break;
×
149
    }
150

151
    /* Running direction */
152
    switch (m_chaser->direction())
×
153
    {
154
    default:
×
155
    case Chaser::Forward:
156
        m_forward->setChecked(true);
×
157
        break;
×
158
    case Chaser::Backward:
×
159
        m_backward->setChecked(true);
×
160
        break;
×
161
    }
162

163
    connect(m_nameEdit, SIGNAL(textEdited(const QString&)),
×
164
            this, SLOT(slotNameEdited(const QString&)));
165
    connect(m_add, SIGNAL(clicked()),
×
166
            this, SLOT(slotAddClicked()));
167
    connect(m_remove, SIGNAL(clicked()),
×
168
            this, SLOT(slotRemoveClicked()));
169
    connect(m_raise, SIGNAL(clicked()),
×
170
            this, SLOT(slotRaiseClicked()));
171
    connect(m_lower, SIGNAL(clicked()),
×
172
            this, SLOT(slotLowerClicked()));
173
    connect(m_shuffle, SIGNAL(clicked()),
×
174
            this, SLOT(slotShuffleClicked()));
175
    connect(m_speeddial, SIGNAL(toggled(bool)),
×
176
            this, SLOT(slotSpeedDialToggle(bool)));
177
    connect(m_fadeInCommonRadio, SIGNAL(toggled(bool)),
×
178
            this, SLOT(slotFadeInToggled()));
179
    connect(m_fadeInPerStepRadio, SIGNAL(toggled(bool)),
×
180
            this, SLOT(slotFadeInToggled()));
181
    connect(m_fadeInDefaultRadio, SIGNAL(toggled(bool)),
×
182
            this, SLOT(slotFadeInToggled()));
183

184
    connect(m_fadeOutCommonRadio, SIGNAL(toggled(bool)),
×
185
            this, SLOT(slotFadeOutToggled()));
186
    connect(m_fadeOutPerStepRadio, SIGNAL(toggled(bool)),
×
187
            this, SLOT(slotFadeOutToggled()));
188
    connect(m_fadeOutDefaultRadio, SIGNAL(toggled(bool)),
×
189
            this, SLOT(slotFadeOutToggled()));
190

191
    connect(m_durationCommonRadio, SIGNAL(toggled(bool)),
×
192
            this, SLOT(slotDurationToggled()));
193
    connect(m_durationPerStepRadio, SIGNAL(toggled(bool)),
×
194
            this, SLOT(slotDurationToggled()));
195

196
    connect(m_loop, SIGNAL(clicked()),
×
197
            this, SLOT(slotLoopClicked()));
198
    connect(m_singleShot, SIGNAL(clicked()),
×
199
            this, SLOT(slotSingleShotClicked()));
200
    connect(m_pingPong, SIGNAL(clicked()),
×
201
            this, SLOT(slotPingPongClicked()));
202
    connect(m_random, SIGNAL(clicked()),
×
203
            this, SLOT(slotRandomClicked()));
204
    connect(m_random, SIGNAL(clicked()),
×
205
            this, SLOT(slotRestartTest()));
206

207
    connect(m_forward, SIGNAL(clicked()),
×
208
            this, SLOT(slotForwardClicked()));
209
    connect(m_backward, SIGNAL(clicked()),
×
210
            this, SLOT(slotBackwardClicked()));
211
    connect(m_forward, SIGNAL(clicked()),
×
212
            this, SLOT(slotRestartTest()));
213
    connect(m_backward, SIGNAL(clicked()),
×
214
            this, SLOT(slotRestartTest()));
215

216
    connect(m_tree, SIGNAL(itemSelectionChanged()),
×
217
            this, SLOT(slotItemSelectionChanged()));
218
    connect(m_tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
×
219
            this, SLOT(slotItemChanged(QTreeWidgetItem*,int)));
220

221
    //connect(m_testButton, SIGNAL(toggled(bool)), this, SLOT(slotTestToggled(bool)));
222
    connect(m_testPlayButton, SIGNAL(clicked()), this, SLOT(slotTestPlay()));
×
223
    connect(m_testStopButton, SIGNAL(clicked()), this, SLOT(slotTestStop()));
×
224
    connect(m_testPreviousButton, SIGNAL(clicked()), this, SLOT(slotTestPreviousClicked()));
×
225
    connect(m_testNextButton, SIGNAL(clicked()), this, SLOT(slotTestNextClicked()));
×
226
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)), this, SLOT(slotModeChanged(Doc::Mode)));
×
227
    connect(m_chaser, SIGNAL(currentStepChanged(int)), this, SLOT(slotStepChanged(int)));
×
228

229
    updateTree(true);
×
230
    updateClipboardButtons();
×
231
    updateSpeedDials();
×
232

233
    slotModeChanged(m_doc->mode());
×
234

235
    // Set focus to the editor
236
    m_nameEdit->setFocus();
×
237

238
    m_testPreviousButton->setEnabled(false);
×
239
    m_testNextButton->setEnabled(false);
×
240
}
×
241

242
ChaserEditor::~ChaserEditor()
×
243
{
244
    if (m_speedDials != NULL)
×
245
        m_speedDials->deleteLater();
×
246
    m_speedDials = NULL;
×
247

248
    // double check that the Chaser still exists !
249
    if (m_liveMode == false &&
×
250
        m_doc->functions().contains(m_chaser) == true)
×
251
        m_chaser->stopAndWait();
×
252
}
×
253

254
void ChaserEditor::showOrderAndDirection(bool show)
×
255
{
256
    groupBox->setVisible(show);
×
257
    groupBox_2->setVisible(show);
×
258
}
×
259

260
void ChaserEditor::stopTest()
×
261
{
262
    m_chaser->stopAndWait();
×
263
}
×
264

265
void ChaserEditor::selectStepAtTime(quint32 time)
×
266
{
267
    quint32 stepTime = 0;
×
268
    for (int i = 0; i < m_chaser->stepsCount(); i++)
×
269
    {
270
        quint32 timeIncr = 0;
×
271
        if (m_chaser->durationMode() == Chaser::Common)
×
272
            timeIncr = m_chaser->duration();
×
273
        else // Chaser::PerStep
274
        {
275
            timeIncr += m_chaser->stepAt(i)->duration;
×
276
        }
277
        if (time < stepTime + timeIncr)
×
278
        {
279
            QTreeWidgetItem *item = m_tree->topLevelItem(i);
×
280
            m_tree->setCurrentItem(item);
×
281
            m_tree->scrollToItem(item, QAbstractItemView::PositionAtCenter);
×
282
            return;
×
283
        }
284
        stepTime += timeIncr;
×
285
    }
286
}
287

288
void ChaserEditor::slotFunctionManagerActive(bool active)
×
289
{
290
    if (active == true)
×
291
    {
292
        updateSpeedDials();
×
293
    }
294
    else
295
    {
296
        if (m_speedDials != NULL)
×
297
            m_speedDials->deleteLater();
×
298
        m_speedDials = NULL;
×
299
    }
300
}
×
301

302
void ChaserEditor::slotNameEdited(const QString& text)
×
303
{
304
    m_chaser->setName(text);
×
305
}
×
306

307
void ChaserEditor::slotUpdateCurrentStep(SceneValue sv, bool enabled)
×
308
{
309
    qDebug() << "Value changed: " << sv.fxi << sv.channel << sv.value << enabled;
×
310
    QList <QTreeWidgetItem*> selected(m_tree->selectedItems());
×
311

312
    if (selected.size() == 0)
×
313
        return;
×
314

315
    QTreeWidgetItem* item(selected.first());
×
316
    int idx = m_tree->indexOfTopLevelItem(item);
×
317

318
    if (enabled == true)
×
319
    {
320
        bool created = false;
×
321
        int svIndex = m_chaser->stepAt(idx)->setValue(sv, -1, &created);
×
322

323
        if (created == true)
×
324
        {
325
            // this means the provided Scene value is new - for EVERY step.
326
            // All the non-selected steps should include the new value, but set to 0
327
            sv.value = 0;
×
328

329
            for (int i = 0; i < m_chaser->stepsCount(); i++)
×
330
            {
331
                // skip the original selected step, otherwise
332
                // the original Scene value would be overwritten
333
                if (i == idx)
×
334
                    continue;
×
335

336
                m_chaser->stepAt(i)->setValue(sv, svIndex);
×
337
                qDebug() << "[slotUpdateCurrentStep] Value added to step: " << i << "@pos" << svIndex;
×
338
            }
339
        }
340
    }
341
    else
342
    {
343
        int svIndex = m_chaser->stepAt(idx)->unSetValue(sv);
×
344

345
        if (svIndex == -1)
×
346
            return;
×
347

348
        for (int i = 0; i < m_chaser->stepsCount(); i++)
×
349
        {
350
            // do not unset again on the currently edited step
351
            if (i == idx)
×
352
                continue;
×
353

354
            m_chaser->stepAt(i)->unSetValue(sv, svIndex);
×
355
            qDebug() << "[slotUpdateCurrentStep] Value removed from step: " << i << "@pos" << svIndex;
×
356
        }
357
    }
358
}
359

360
/****************************************************************************
361
 * List manipulation
362
 ****************************************************************************/
363

364
void ChaserEditor::slotAddClicked()
×
365
{
366
    bool stepAdded = false;
×
367

368
    int insertionPoint = m_tree->topLevelItemCount();
×
369
    QTreeWidgetItem* item = m_tree->currentItem();
×
370
    if (item != NULL)
×
371
        insertionPoint = m_tree->indexOfTopLevelItem(item) + 1;
×
372

373
    if (m_chaser->type() == Function::SequenceType)
×
374
    {
375
        Sequence *sequence = qobject_cast<Sequence*>(m_chaser);
×
376
        ChaserStep step(sequence->boundSceneID());
×
377
        item = new QTreeWidgetItem;
×
378
        updateItem(item, step);
×
379
        // if this is the first step we add, then copy all DMX channels non-zero values
380
        Scene *currScene = qobject_cast<Scene*> (m_doc->function(sequence->boundSceneID()));
×
381
        QListIterator <SceneValue> it(currScene->values());
×
382
        qDebug() << "First step added !!";
×
383
        while (it.hasNext() == true)
×
384
        {
385
            SceneValue chan(it.next());
×
386
            step.values.append(chan);
×
387
            //qDebug() << "Value added: " << chan.value;
388
        }
389
        qDebug() << "Values added: " << step.values.count();
×
390

391
        m_tree->insertTopLevelItem(insertionPoint, item);
×
392
        m_chaser->addStep(step, insertionPoint);
×
393
        stepAdded = true;
×
394
    }
395
    else
396
    {
397
        FunctionSelection fs(this, m_doc);
×
398
        {
399
            QList<quint32> disabledList;
×
400
            disabledList << m_chaser->id();
×
401
            foreach (Function* function, m_doc->functions())
×
402
            {
403
                if (function->contains(m_chaser->id()))
×
404
                    disabledList << function->id();
×
405
            }
406
            fs.setDisabledFunctions(disabledList);
×
407
        }
408

409
        if (fs.exec() == QDialog::Accepted)
×
410
        {
411
            /* Append selected functions */
412
            QListIterator <quint32> it(fs.selection());
×
413
            while (it.hasNext() == true)
×
414
            {
415
                ChaserStep step(it.next());
×
416
                item = new QTreeWidgetItem;
×
417
                updateItem(item, step);
×
418
                m_tree->insertTopLevelItem(insertionPoint, item);
×
419
                qDebug() << "Insertion point: " << insertionPoint;
×
420
                m_chaser->addStep(step, insertionPoint++);
×
421
            }
422
            stepAdded = true;
×
423
        }
424
    }
425
    if (stepAdded == true)
×
426
    {
427
        // at last, select the newly created step, so in case of a Sequence,
428
        // the Scene Editor will show the current values, and users will
429
        // stop bugging us in the forums
430
        m_tree->setCurrentItem(item);
×
431
        updateStepNumbers();
×
432
        updateClipboardButtons();
×
433
        //printSteps();
434
    }
435
}
×
436

437
void ChaserEditor::slotRemoveClicked()
×
438
{
439
    return slotCutClicked();
×
440
}
441

442
void ChaserEditor::slotRaiseClicked()
×
443
{
444
    QList <QTreeWidgetItem*> items(m_tree->selectedItems());
×
445
    QListIterator <QTreeWidgetItem*> it(items);
×
446

447
    // Check, whether even one of the items would "bleed" over the edge and
448
    // cancel the operation if that is the case.
449
    while (it.hasNext() == true)
×
450
    {
451
        QTreeWidgetItem* item(it.next());
×
452
        int index = m_tree->indexOfTopLevelItem(item);
×
453
        if (index == 0)
×
454
            return;
×
455
    }
456

457
    // Move the items
458
    it.toFront();
×
459
    while (it.hasNext() == true)
×
460
    {
461
        QTreeWidgetItem* item(it.next());
×
462
        int index = m_tree->indexOfTopLevelItem(item);
×
463
        m_tree->takeTopLevelItem(index);
×
464
        m_tree->insertTopLevelItem(index - 1, item);
×
465
        m_chaser->moveStep(index, index - 1);
×
466
    }
467

468
    updateStepNumbers();
×
469

470
    // Select the moved items
471
    it.toFront();
×
472
    while (it.hasNext() == true)
×
473
        it.next()->setSelected(true);
×
474

475
    updateClipboardButtons();
×
476
    //printSteps();
477
}
478

479
void ChaserEditor::slotLowerClicked()
×
480
{
481
    QList <QTreeWidgetItem*> items(m_tree->selectedItems());
×
482
    QListIterator <QTreeWidgetItem*> it(items);
×
483

484
    // Check, whether even one of the items would "bleed" over the edge and
485
    // cancel the operation if that is the case.
486
    while (it.hasNext() == true)
×
487
    {
488
        QTreeWidgetItem* item(it.next());
×
489
        int index = m_tree->indexOfTopLevelItem(item);
×
490
        if (index == m_tree->topLevelItemCount() - 1)
×
491
            return;
×
492
    }
493

494
    // Move the items
495
    it.toBack();
×
496
    while (it.hasPrevious() == true)
×
497
    {
498
        QTreeWidgetItem* item(it.previous());
×
499
        int index = m_tree->indexOfTopLevelItem(item);
×
500
        m_tree->takeTopLevelItem(index);
×
501
        m_tree->insertTopLevelItem(index + 1, item);
×
502
        m_chaser->moveStep(index, index + 1);
×
503
    }
504

505
    updateStepNumbers();
×
506

507
    // Select the items
508
    it.toFront();
×
509
    while (it.hasNext() == true)
×
510
        it.next()->setSelected(true);
×
511

512
    updateClipboardButtons();
×
513
    //printSteps();
514
}
515

516
void ChaserEditor::slotShuffleClicked()
×
517
{
518
    int i;
519
    int selectedCount = m_tree->selectedItems().count();
×
520

521
    if (selectedCount == 1)
×
522
    {
523
        // it doesn't make sense shuffling one step
524
        return;
×
525
    }
526
    else if (selectedCount == 0)
×
527
    {
528
        m_tree->selectAll();
×
529
        selectedCount = m_tree->selectedItems().count();
×
530
    }
531

532
    QList <QTreeWidgetItem*> selectedItems(m_tree->selectedItems());
×
533
    int indicesToShuffle[selectedCount];
×
534

535
    // save the selected scenes and their indices into a sorted array
536
    QListIterator <QTreeWidgetItem*> it(selectedItems);
×
537
    for (i = 0; i < selectedCount; i++)
×
538
    {
539
        QTreeWidgetItem* item = it.next();
×
540
        indicesToShuffle[i] = m_tree->indexOfTopLevelItem(item);
×
541
    }
542
    std::sort(indicesToShuffle, indicesToShuffle + selectedCount);
×
543

544
    // shuffle the selected scenes using the Fisher-Yates algorithm
545
    // see https://bost.ocks.org/mike/shuffle/ for information on the algorithm
546
    int unshuffledCount = selectedCount;
×
547
    while (unshuffledCount > 0)
×
548
    {
549
        // pick a random unshuffled selected and swap it with the last unshuffled one -> now it is a shuffled step
550
        int toShuffle = rand() % unshuffledCount;
×
551
        unshuffledCount--;
×
552
        int indexToShuffle = indicesToShuffle[toShuffle];
×
553
        int lastUnshuffledIndex = indicesToShuffle[unshuffledCount];
×
554

555
        if (indexToShuffle != lastUnshuffledIndex)
×
556
        {
557
            QTreeWidgetItem* lastUnshuffledItem = m_tree->takeTopLevelItem(lastUnshuffledIndex);
×
558
            QTreeWidgetItem* itemToShuffle = m_tree->takeTopLevelItem(indexToShuffle);
×
559
            m_tree->insertTopLevelItem(indexToShuffle, lastUnshuffledItem);
×
560
            m_tree->insertTopLevelItem(lastUnshuffledIndex, itemToShuffle);
×
561
            m_chaser->moveStep(indexToShuffle, lastUnshuffledIndex);
×
562
            m_chaser->moveStep(lastUnshuffledIndex - 1, indexToShuffle);
×
563
        }
564
    }
565

566
    updateStepNumbers();
×
567
    updateClipboardButtons();
×
568

569
    // the selection is destroyed / weird after reordering scenes, so we restore it manually
570
    m_tree->clearSelection();
×
571
    for (i = 0; i < selectedCount; i++)
×
572
        m_tree->topLevelItem(indicesToShuffle[i])->setSelected(true);
×
573
}
574

575
void ChaserEditor::slotSpeedDialToggle(bool state)
×
576
{
577
    if (state == true)
×
578
        updateSpeedDials();
×
579
    else
580
    {
581
        if (m_speedDials != NULL)
×
582
            m_speedDials->deleteLater();
×
583
        m_speedDials = NULL;
×
584
    }
585
}
×
586

587
void ChaserEditor::slotItemSelectionChanged()
×
588
{
589
    if (m_chaser->isRunning())
×
590
        return;
×
591

592
    if (m_tree->selectedItems().count() > 0)
×
593
    {
594
        QTreeWidgetItem *item = m_tree->selectedItems().first();
×
595
        int idx = item->text(COL_NUM).toUInt() - 1;
×
596
        emit stepSelectionChanged(idx);
×
597
    }
598
    else
599
        emit stepSelectionChanged(-1);
×
600

601
    updateClipboardButtons();
×
602
    updateSpeedDials();
×
603
    applyStepValues();
×
604
}
605

606
void ChaserEditor::slotItemChanged(QTreeWidgetItem *item, int column)
×
607
{
608
    QString itemText = item->text(column);
×
609
    quint32 newValue = Function::stringToSpeed(itemText);
×
610
    int idx = m_tree->indexOfTopLevelItem(item);
×
611

612
    ChaserStep step = m_chaser->steps().at(idx);
×
613

614
    uint fadeIn = m_chaser->fadeInMode() == Chaser::Common ? m_chaser->fadeInSpeed() : step.fadeIn;
×
615
    uint fadeOut = m_chaser->fadeOutMode() == Chaser::Common ? m_chaser->fadeOutSpeed() : step.fadeOut;
×
616
    uint duration = m_chaser->durationMode() == Chaser::Common ? m_chaser->duration() : step.duration;
×
617
    uint hold = Function::speedSubtract(duration, fadeIn);
×
618
    bool updateTreeNeeded = false;
×
619

620
    if (column == COL_FADEIN)
×
621
    {
622
        fadeIn = newValue;
×
623
        if (m_chaser->fadeInMode() == Chaser::Common)
×
624
        {
625
            m_chaser->setFadeInSpeed(fadeIn);
×
626
            updateTreeNeeded = true;
×
627
            if (m_chaser->durationMode() == Chaser::Common)
×
628
                m_chaser->setDuration(Function::speedAdd(hold, fadeIn));
×
629
        }
630
        else
631
        {
632
            step.fadeIn = fadeIn;
×
633
            if (m_chaser->durationMode() != Chaser::Common)
×
634
                step.duration = Function::speedAdd(hold, fadeIn);
×
635
        }
636

637
    }
638
    else if (column == COL_HOLD)
×
639
    {
640
        hold = newValue;
×
641

642
        if (m_chaser->durationMode() == Chaser::Common)
×
643
        {
644
            m_chaser->setDuration(Function::speedAdd(hold, fadeIn));
×
645
            updateTreeNeeded = true;
×
646
        }
647
        else
648
        {
649
            step.hold = hold;
×
650
            step.duration = Function::speedAdd(hold, fadeIn);
×
651
        }
652
    }
653
    else if (column == COL_FADEOUT)
×
654
    {
655
        fadeOut = newValue;
×
656
        if (m_chaser->fadeOutMode() == Chaser::Common)
×
657
        {
658
            m_chaser->setFadeOutSpeed(fadeOut);
×
659
            updateTreeNeeded = true;
×
660
        }
661
        else
662
        {
663
            step.fadeOut = fadeOut;
×
664
        }
665
    }
666
    else if (column == COL_DURATION)
×
667
    {
668
        duration = newValue;
×
669

670
        if (m_chaser->durationMode() == Chaser::Common)
×
671
        {
672
            m_chaser->setDuration(duration);
×
673
            updateTreeNeeded = true;
×
674
        }
675
        else
676
        {
677
            step.duration = duration;
×
678
            step.hold = Function::speedSubtract(duration, fadeIn);
×
679
        }
680
    }
681
    else if (column == COL_NOTES)
×
682
    {
683
        step.note = itemText;
×
684
    }
685
    if (updateTreeNeeded)
×
686
        updateTree();
×
687

688
    m_chaser->replaceStep(step, idx);
×
689
    updateItem(item, step);
×
690

691
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
692
}
×
693

694
/****************************************************************************
695
 * Clipboard
696
 ****************************************************************************/
697

698
void ChaserEditor::slotCutClicked()
×
699
{
700
    QList <ChaserStep> copyList;
×
701
    QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
702
    while (it.hasNext() == true)
×
703
    {
704
        QTreeWidgetItem* item(it.next());
×
705
        int index = m_tree->indexOfTopLevelItem(item);
×
706
        copyList << stepAtIndex(index);
×
707
        m_chaser->removeStep(index);
×
708
        delete item;
×
709
    }
710

711
    m_doc->clipboard()->copyContent(m_chaser->id(), copyList);
×
712
    m_tree->setCurrentItem(NULL);
×
713

714
    updateStepNumbers();
×
715
    updateClipboardButtons();
×
716
}
×
717

718
void ChaserEditor::slotCopyClicked()
×
719
{
720
    QList <ChaserStep> copyList;
×
721
    foreach (QTreeWidgetItem *item, m_tree->selectedItems())
×
722
        copyList << stepAtItem(item);
×
723
    QLCClipboard *clipboard = m_doc->clipboard();
×
724
    clipboard->copyContent(m_chaser->id(), copyList);
×
725
    updateClipboardButtons();
×
726
}
×
727

728
void ChaserEditor::slotPasteClicked()
×
729
{
730
    if (m_doc->clipboard()->hasChaserSteps() == false)
×
731
        return;
×
732
    QList <ChaserStep> pasteList = m_doc->clipboard()->getChaserSteps();
×
733

734
    // If the Chaser is a sequence, then perform a sanity
735
    // check on each Step to see if they really belong to
736
    // this scene
737
    if (m_chaser->type() == Function::SequenceType)
×
738
    {
739
        Sequence *sequence = qobject_cast<Sequence*>(m_chaser);
×
740
        quint32 sceneID = sequence->boundSceneID();
×
741
        Scene *scene = qobject_cast<Scene*>(m_doc->function(sceneID));
×
NEW
742
        foreach (ChaserStep step, pasteList)
×
743
        {
744
            if (step.fid != sceneID) // if IDs are the same then it's a valid step
×
745
            {
NEW
746
                foreach (SceneValue scv, step.values)
×
747
                {
748
                    if (scene->checkValue(scv) == false)
×
749
                    {
750
                        QMessageBox::warning(this, tr("Paste error"), tr("Trying to paste on an incompatible Scene. Operation canceled."));
×
751
                        return;
×
752
                    }
753
                }
754
            }
755
        }
756
    }
757

758
    int insertionPoint = 0;
×
759
    QTreeWidgetItem* currentItem = m_tree->currentItem();
×
760
    if (currentItem != NULL)
×
761
    {
762
        insertionPoint = m_tree->indexOfTopLevelItem(currentItem) + 1;
×
763
        currentItem->setSelected(false);
×
764
    }
765
    else
766
    {
767
        insertionPoint = m_tree->topLevelItemCount();
×
768
    }
769

770
    QList<QTreeWidgetItem*>selectionList;
×
771

772
    QListIterator <ChaserStep> it(pasteList);
×
773
    while (it.hasNext() == true)
×
774
    {
775
        QTreeWidgetItem* item = new QTreeWidgetItem;
×
776
        ChaserStep step(it.next());
×
777
        if (step.resolveFunction(m_doc) == NULL) // Function has been removed
×
778
        {
779
            qWarning() << Q_FUNC_INFO << "Trying to paste an invalid function (removed function?)";
×
780
            continue;
×
781
        }
782
        updateItem(item, step);
×
783
        m_tree->insertTopLevelItem(insertionPoint, item);
×
784
        m_chaser->addStep(step, insertionPoint);
×
785
        selectionList.append(item); // defer items selection cause of performances issues
×
786
        insertionPoint++;
×
787
    }
788

789
    updateStepNumbers();
×
790
    updateClipboardButtons();
×
791

792
    // this is done here cause of a misterious performance issue
793
    foreach (QTreeWidgetItem *item, selectionList)
×
794
        item->setSelected(true);
×
795
}
796

797
/****************************************************************************
798
 * Run order & Direction
799
 ****************************************************************************/
800

801
void ChaserEditor::slotLoopClicked()
×
802
{
803
    m_chaser->setRunOrder(Function::Loop);
×
804
}
×
805

806
void ChaserEditor::slotSingleShotClicked()
×
807
{
808
    m_chaser->setRunOrder(Function::SingleShot);
×
809
}
×
810

811
void ChaserEditor::slotPingPongClicked()
×
812
{
813
    m_chaser->setRunOrder(Function::PingPong);
×
814
}
×
815

816
void ChaserEditor::slotRandomClicked()
×
817
{
818
    m_chaser->setRunOrder(Function::Random);
×
819
}
×
820

821
void ChaserEditor::slotForwardClicked()
×
822
{
823
    m_chaser->setDirection(Function::Forward);
×
824
}
×
825

826
void ChaserEditor::slotBackwardClicked()
×
827
{
828
    m_chaser->setDirection(Function::Backward);
×
829
}
×
830

831
/****************************************************************************
832
 * Speed
833
 ****************************************************************************/
834

835
void ChaserEditor::slotFadeInToggled()
×
836
{
837
    if (m_fadeInCommonRadio->isChecked() == true)
×
838
        m_chaser->setFadeInMode(Chaser::Common);
×
839
    else if (m_fadeInPerStepRadio->isChecked() == true)
×
840
        m_chaser->setFadeInMode(Chaser::PerStep);
×
841
    else
842
        m_chaser->setFadeInMode(Chaser::Default);
×
843

844
    updateTree();
×
845
    updateSpeedDials();
×
846
}
×
847

848
void ChaserEditor::slotFadeOutToggled()
×
849
{
850
    if (m_fadeOutCommonRadio->isChecked() == true)
×
851
        m_chaser->setFadeOutMode(Chaser::Common);
×
852
    else if (m_fadeOutPerStepRadio->isChecked() == true)
×
853
        m_chaser->setFadeOutMode(Chaser::PerStep);
×
854
    else
855
        m_chaser->setFadeOutMode(Chaser::Default);
×
856

857
    updateTree();
×
858
    updateSpeedDials();
×
859
}
×
860

861
void ChaserEditor::slotDurationToggled()
×
862
{
863
    if (m_durationPerStepRadio->isChecked() == true)
×
864
        m_chaser->setDurationMode(Chaser::PerStep);
×
865
    else
866
        m_chaser->setDurationMode(Chaser::Common);
×
867

868
    updateTree();
×
869
    updateSpeedDials();
×
870
}
×
871

872
void ChaserEditor::slotFadeInDialChanged(int ms)
×
873
{
874
    switch (m_chaser->fadeInMode())
×
875
    {
876
    case Chaser::Common:
×
877
        if (QTreeWidgetItem* item = m_tree->topLevelItem(0))
×
878
            item->setText(COL_FADEIN, Function::speedToString(ms));
×
879
        else
880
            m_chaser->setFadeInSpeed(Function::speedNormalize(ms));
×
881
        break;
×
882
    case Chaser::PerStep:
×
883
        foreach (QTreeWidgetItem* item, m_tree->selectedItems())
×
884
        {
885
            item->setText(COL_FADEIN, Function::speedToString(ms));
×
886
        }
887
        break;
×
888
    default:
×
889
    case Chaser::Default:
890
        break;
×
891
    }
892

893
    m_tree->resizeColumnToContents(COL_FADEIN);
×
894
}
×
895

896
void ChaserEditor::slotFadeOutDialChanged(int ms)
×
897
{
898
    switch (m_chaser->fadeOutMode())
×
899
    {
900
    case Chaser::Common:
×
901
        if (QTreeWidgetItem* item = m_tree->topLevelItem(0))
×
902
            item->setText(COL_FADEOUT, Function::speedToString(ms));
×
903
        else
904
            m_chaser->setFadeOutSpeed(Function::speedNormalize(ms));
×
905
        break;
×
906
    case Chaser::PerStep:
×
907
        foreach (QTreeWidgetItem* item, m_tree->selectedItems())
×
908
        {
909
            item->setText(COL_FADEOUT, Function::speedToString(ms));
×
910
        }
911
        break;
×
912
    default:
×
913
    case Chaser::Default:
914
        break;
×
915
    }
916

917
    m_tree->resizeColumnToContents(COL_FADEOUT);
×
918
}
×
919

920
void ChaserEditor::slotHoldDialChanged(int ms)
×
921
{
922
    switch (m_chaser->durationMode())
×
923
    {
924
    case Chaser::Common:
×
925
        if (QTreeWidgetItem* item = m_tree->topLevelItem(0))
×
926
            item->setText(COL_HOLD, Function::speedToString(ms));
×
927
        else
928
        {
929
            if (m_chaser->fadeInMode() == Chaser::Common)
×
930
                m_chaser->setDuration(Function::speedAdd(ms, m_chaser->fadeInSpeed()));
×
931
            else
932
                m_chaser->setDuration(Function::speedNormalize(ms));
×
933
        }
934
        break;
×
935
    case Chaser::PerStep:
×
936
        foreach (QTreeWidgetItem* item, m_tree->selectedItems())
×
937
        {
938
            item->setText(COL_HOLD, Function::speedToString(ms));
×
939
        }
940
        break;
×
941
    default:
×
942
    case Chaser::Default:
943
        break;
×
944
    }
945

946
    m_tree->resizeColumnToContents(COL_HOLD);
×
947
}
×
948

949
void ChaserEditor::slotDialDestroyed(QObject *)
×
950
{
951
    m_speeddial->setChecked(false);
×
952
}
×
953

954
void ChaserEditor::createSpeedDials()
×
955
{
956
    if (m_speedDials == NULL)
×
957
    {
958
        m_speedDials = new SpeedDialWidget(this);
×
959
        m_speedDials->setAttribute(Qt::WA_DeleteOnClose);
×
960

961
        connect(m_speedDials, SIGNAL(fadeInChanged(int)),
×
962
                this, SLOT(slotFadeInDialChanged(int)));
963
        connect(m_speedDials, SIGNAL(fadeOutChanged(int)),
×
964
                this, SLOT(slotFadeOutDialChanged(int)));
965
        connect(m_speedDials, SIGNAL(holdChanged(int)),
×
966
                this, SLOT(slotHoldDialChanged(int)));
967
        connect(m_speedDials, SIGNAL(destroyed(QObject*)),
×
968
                this, SLOT(slotDialDestroyed(QObject*)));
969
    }
970

971
    m_speedDials->show();
×
972
}
×
973

974
void ChaserEditor::updateSpeedDials()
×
975
{
976
    if (m_speeddial->isChecked() == false)
×
977
        return;
×
978

979
    static const QString fadeIn(tr("Fade In"));
×
980
    static const QString fadeOut(tr("Fade Out"));
×
981
    static const QString hold(tr("Hold"));
×
982
    static const QString globalFadeIn(tr("Common Fade In"));
×
983
    static const QString globalFadeOut(tr("Common Fade Out"));
×
984
    static const QString globalHold(tr("Common Hold"));
×
985

986
    createSpeedDials();
×
987

988
    QList <QTreeWidgetItem*> selected(m_tree->selectedItems());
×
989

990
    ChaserStep step;
×
991
    if (selected.size() != 0)
×
992
    {
993
        const QTreeWidgetItem* item(selected.first());
×
994
        step = stepAtItem(item);
×
995

996
        QString title;
×
997
        if (selected.size() == 1)
×
998
            title = QString("%1: %2").arg(item->text(COL_NUM)).arg(item->text(COL_NAME));
×
999
        else
1000
            title = tr("Multiple Steps");
×
1001
        m_speedDials->setWindowTitle(title);
×
1002
    }
1003
    else
1004
    {
1005
        m_speedDials->setWindowTitle(m_chaser->name());
×
1006
    }
1007

1008
    /* Fade in */
1009
    switch (m_chaser->fadeInMode())
×
1010
    {
1011
    case Chaser::Common:
×
1012
        m_speedDials->setFadeInSpeed(m_chaser->fadeInSpeed());
×
1013
        m_speedDials->setFadeInTitle(globalFadeIn);
×
1014
        m_speedDials->setFadeInEnabled(true);
×
1015
        break;
×
1016
    case Chaser::PerStep:
×
1017
        if (selected.size() != 0)
×
1018
        {
1019
            m_speedDials->setFadeInSpeed(step.fadeIn);
×
1020
            m_speedDials->setFadeInEnabled(true);
×
1021
        }
1022
        else
1023
        {
1024
            m_speedDials->setFadeInSpeed(0);
×
1025
            m_speedDials->setFadeInEnabled(false);
×
1026
        }
1027
        m_speedDials->setFadeInTitle(fadeIn);
×
1028
        break;
×
1029
    default:
×
1030
    case Chaser::Default:
1031
        m_speedDials->setFadeInTitle(fadeIn);
×
1032
        m_speedDials->setFadeInEnabled(false);
×
1033
        break;
×
1034
    }
1035

1036
    /* Fade out */
1037
    switch (m_chaser->fadeOutMode())
×
1038
    {
1039
    case Chaser::Common:
×
1040
        m_speedDials->setFadeOutSpeed(m_chaser->fadeOutSpeed());
×
1041
        m_speedDials->setFadeOutTitle(globalFadeOut);
×
1042
        m_speedDials->setFadeOutEnabled(true);
×
1043
        break;
×
1044
    case Chaser::PerStep:
×
1045
        if (selected.size() != 0)
×
1046
        {
1047
            m_speedDials->setFadeOutSpeed(step.fadeOut);
×
1048
            m_speedDials->setFadeOutEnabled(true);
×
1049
        }
1050
        else
1051
        {
1052
            m_speedDials->setFadeOutSpeed(0);
×
1053
            m_speedDials->setFadeOutEnabled(false);
×
1054
        }
1055
        m_speedDials->setFadeOutTitle(fadeOut);
×
1056
        break;
×
1057
    default:
×
1058
    case Chaser::Default:
1059
        m_speedDials->setFadeOutTitle(fadeOut);
×
1060
        m_speedDials->setFadeOutEnabled(false);
×
1061
        break;
×
1062
    }
1063

1064
    /* Hold */
1065
    switch (m_chaser->durationMode())
×
1066
    {
1067
    default:
×
1068
    case Chaser::Common:
1069
    {
1070
        if ((int)m_chaser->duration() < 0)
×
1071
            m_speedDials->setDuration(m_chaser->duration());
×
1072
        else
1073
            m_speedDials->setDuration(m_chaser->duration() - m_chaser->fadeInSpeed());
×
1074
        m_speedDials->setDurationTitle(globalHold);
×
1075
        m_speedDials->setDurationEnabled(true);
×
1076
        break;
×
1077
    }
1078
    case Chaser::PerStep:
×
1079
        if (selected.size() != 0)
×
1080
        {
1081
            m_speedDials->setDuration(step.hold);
×
1082
            m_speedDials->setDurationEnabled(true);
×
1083
        }
1084
        else
1085
        {
1086
            m_speedDials->setFadeOutSpeed(0);
×
1087
            m_speedDials->setDurationEnabled(false);
×
1088
        }
1089
        m_speedDials->setDurationTitle(hold);
×
1090
        break;
×
1091
    }
1092
}
1093

1094
/****************************************************************************
1095
 * Test
1096
 ****************************************************************************/
1097
int ChaserEditor::getCurrentIndex()
×
1098
{
1099
    // Return the index of the current selected item
1100
    // Return -1 if nothing is selected
1101
    return m_tree->indexOfTopLevelItem(m_tree->currentItem());
×
1102
}
1103

1104
void ChaserEditor::slotRestartTest()
×
1105
{
1106
    if (m_chaser->stopped() == false)
×
1107
    {
1108
        // Toggle off, toggle on. Derp.
1109
        m_testStopButton->click();
×
1110
        m_testPlayButton->click();
×
1111
    }
1112
}
×
1113

1114
void ChaserEditor::slotTestPlay()
×
1115
{
1116
    m_testPreviousButton->setEnabled(true);
×
1117
    m_testNextButton->setEnabled(true);
×
1118

1119
    int idx = getCurrentIndex();
×
1120
    if (idx >= 0)
×
1121
    {
1122
        ChaserAction action;
1123
        action.m_action = ChaserSetStepIndex;
×
1124
        action.m_stepIndex = idx;
×
1125
        action.m_masterIntensity = 1.0;
×
1126
        action.m_stepIntensity = 1.0;
×
1127
        action.m_fadeMode = Chaser::FromFunction;
×
1128
        m_chaser->setAction(action);
×
1129
    }
1130
    m_chaser->start(m_doc->masterTimer(), functionParent());
×
1131
}
×
1132

1133
FunctionParent ChaserEditor::functionParent() const
×
1134
{
1135
    return FunctionParent::master();
×
1136
}
1137

1138
void ChaserEditor::slotTestStop()
×
1139
{
1140
    m_testPreviousButton->setEnabled(false);
×
1141
    m_testNextButton->setEnabled(false);
×
1142

1143
    m_chaser->stopAndWait();
×
1144
}
×
1145

1146
void ChaserEditor::slotTestPreviousClicked()
×
1147
{
1148
    ChaserAction action;
1149
    action.m_action = ChaserPreviousStep;
×
1150
    action.m_masterIntensity = 1.0;
×
1151
    action.m_stepIntensity = 1.0;
×
1152
    action.m_fadeMode = Chaser::FromFunction;
×
1153
    m_chaser->setAction(action);
×
1154
}
×
1155

1156
void ChaserEditor::slotTestNextClicked()
×
1157
{
1158
    ChaserAction action;
1159
    action.m_action = ChaserNextStep;
×
1160
    action.m_masterIntensity = 1.0;
×
1161
    action.m_stepIntensity = 1.0;
×
1162
    action.m_fadeMode = Chaser::FromFunction;
×
1163
    m_chaser->setAction(action);
×
1164
}
×
1165

1166
void ChaserEditor::slotModeChanged(Doc::Mode mode)
×
1167
{
1168
    if (mode == Doc::Operate)
×
1169
    {
1170
        m_testPlayButton->setEnabled(false);
×
1171
        m_testStopButton->setEnabled(false);
×
1172
        if (m_liveMode == false)
×
1173
            m_chaser->stop(functionParent());
×
1174
    }
1175
    else
1176
    {
1177
        m_testPlayButton->setEnabled(true);
×
1178
        m_testStopButton->setEnabled(true);
×
1179
    }
1180
}
×
1181

1182
void ChaserEditor::slotStepChanged(int stepNumber)
×
1183
{
1184
    // Select only the item at step StepNumber
1185
    // If stepNumber is outside of bounds, select nothing
1186
    m_tree->setCurrentItem(m_tree->topLevelItem(stepNumber));
×
1187
}
×
1188

1189
/****************************************************************************
1190
 * Utilities
1191
 ****************************************************************************/
1192

1193
void ChaserEditor::updateTree(bool clear)
×
1194
{
1195
    if (clear == true)
×
1196
        m_tree->clear();
×
1197

1198
    for (int i = 0; i < m_chaser->steps().size(); i++)
×
1199
    {
1200
        QTreeWidgetItem* item = NULL;
×
1201

1202
        if (clear == true)
×
1203
            item = new QTreeWidgetItem(m_tree);
×
1204
        else
1205
            item = m_tree->topLevelItem(i);
×
1206
        Q_ASSERT(item != NULL);
×
1207

1208
        ChaserStep step(m_chaser->steps().at(i));
×
1209
        updateItem(item, step);
×
1210
    }
1211

1212
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
1213
}
×
1214

1215
void ChaserEditor::updateItem(QTreeWidgetItem* item, ChaserStep& step)
×
1216
{
1217
    Function* function = step.resolveFunction(m_doc);
×
1218
    Q_ASSERT(function != NULL);
×
1219
    Q_ASSERT(item != NULL);
×
1220

1221
    m_tree->blockSignals(true);
×
1222

1223
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
×
1224
    item->setText(COL_NUM, QString("%1").arg(m_tree->indexOfTopLevelItem(item) + 1));
×
1225
    if (m_chaser->type() == Function::ChaserType)
×
1226
    {
1227
        item->setText(COL_NAME, function->name());
×
1228
        item->setIcon(COL_NAME, function->getIcon());
×
1229
    }
1230

1231
    if (step.note.isEmpty() == false)
×
1232
        item->setText(COL_NOTES, step.note);
×
1233
    step.fid = function->id();
×
1234

1235
    switch (m_chaser->fadeInMode())
×
1236
    {
1237
        case Chaser::Common:
×
1238
            step.fadeIn = m_chaser->fadeInSpeed();
×
1239
            item->setText(COL_FADEIN, Function::speedToString(step.fadeIn));
×
1240
        break;
×
1241
        case Chaser::PerStep:
×
1242
            item->setText(COL_FADEIN, Function::speedToString(step.fadeIn));
×
1243
        break;
×
1244
        default:
×
1245
            item->setText(COL_FADEIN, QString());
×
1246
        break;
×
1247
    }
1248

1249
    switch (m_chaser->fadeOutMode())
×
1250
    {
1251
        case Chaser::Common:
×
1252
            step.fadeOut = m_chaser->fadeOutSpeed();
×
1253
            item->setText(COL_FADEOUT, Function::speedToString(step.fadeOut));
×
1254
        break;
×
1255
        case Chaser::PerStep:
×
1256
            item->setText(COL_FADEOUT, Function::speedToString(step.fadeOut));
×
1257
        break;
×
1258
        default:
×
1259
            item->setText(COL_FADEOUT, QString());
×
1260
        break;
×
1261
    }
1262

1263
    switch (m_chaser->durationMode())
×
1264
    {
1265
        default:
×
1266
        case Chaser::Common:
1267
            step.duration = m_chaser->duration();
×
1268
            step.hold = Function::speedSubtract(step.duration, step.fadeIn);
×
1269
            item->setText(COL_HOLD, Function::speedToString(step.hold));
×
1270
            item->setText(COL_DURATION, Function::speedToString(step.duration));
×
1271
        break;
×
1272
        case Chaser::PerStep:
×
1273
            item->setText(COL_HOLD, Function::speedToString(step.hold));
×
1274
            item->setText(COL_DURATION, Function::speedToString(step.duration));
×
1275
        break;
×
1276
    }
1277

1278
    m_tree->blockSignals(false);
×
1279
}
×
1280

1281
void ChaserEditor::updateStepNumbers()
×
1282
{
1283
    for (int i = 0; i < m_tree->topLevelItemCount(); i++)
×
1284
    {
1285
        QTreeWidgetItem* item = m_tree->topLevelItem(i);
×
1286
        Q_ASSERT(item != NULL);
×
1287
        item->setText(COL_NUM, QString("%1").arg(i + 1));
×
1288
    }
1289
}
×
1290

1291
ChaserStep ChaserEditor::stepAtItem(const QTreeWidgetItem* item) const
×
1292
{
1293
    Q_ASSERT(item != NULL);
×
1294

1295
    int idx = item->text(COL_NUM).toInt() - 1;
×
1296
    if (idx < 0 || idx >= m_chaser->steps().count())
×
1297
        return ChaserStep();
×
1298

1299
    return m_chaser->steps().at(idx);
×
1300
}
1301

1302
ChaserStep ChaserEditor::stepAtIndex(int index) const
×
1303
{
1304
    if (index < 0 || index >= m_chaser->steps().count())
×
1305
        return ChaserStep();
×
1306

1307
    return m_chaser->steps().at(index);
×
1308
}
1309

1310
void ChaserEditor::updateClipboardButtons()
×
1311
{
1312
    if (m_tree->selectedItems().size() > 0)
×
1313
    {
1314
        m_cutAction->setEnabled(true);
×
1315
        m_copyAction->setEnabled(true);
×
1316
    }
1317
    else
1318
    {
1319
        m_cutAction->setEnabled(false);
×
1320
        m_copyAction->setEnabled(false);
×
1321
    }
1322

1323
    if (m_doc->clipboard()->hasChaserSteps())
×
1324
        m_pasteAction->setEnabled(true);
×
1325
    else
1326
        m_pasteAction->setEnabled(false);
×
1327
}
×
1328

1329
void ChaserEditor::applyStepValues()
×
1330
{
1331
    QList <QTreeWidgetItem*> selected(m_tree->selectedItems());
×
1332

1333
    if (selected.size() != 0)
×
1334
    {
1335
        QTreeWidgetItem* item(selected.first());
×
1336
        int idx = m_tree->indexOfTopLevelItem(item);
×
1337
        qDebug() << "Idx: " << idx << ", steps: " << m_chaser->steps().count();
×
1338
        if (m_chaser != NULL && idx < m_chaser->steps().count())
×
1339
        {
1340
            ChaserStep step = m_chaser->steps().at(idx);
×
1341

1342
            if (step.values.count() > 0)
×
1343
                emit applyValues(step.values);
×
1344
        }
1345
    }
1346
}
×
1347

1348
void ChaserEditor::printSteps()
×
1349
{
1350
    int i = 0;
×
1351
    QListIterator <ChaserStep> it(m_chaser->steps());
×
1352
    while (it.hasNext() == true)
×
1353
    {
1354
        ChaserStep st(it.next());
×
1355
        qDebug() << "Step #" << i << ": id: " << st.fid << ": fadeIn: " << st.fadeIn << ", fadeOut: " << st.fadeOut << ", duration: " << st.duration;
×
1356
        if (st.values.count() > 0)
×
1357
            qDebug() << "-----> values found: " << st.values.count();
×
1358
    }
1359
}
×
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