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

mcallegari / qlcplus / 7252848206

18 Dec 2023 07:26PM UTC coverage: 32.067% (+0.001%) from 32.066%
7252848206

push

github

mcallegari
Code style review #1427

199 of 628 new or added lines in 101 files covered. (31.69%)

8 existing lines in 2 files now uncovered.

15169 of 47304 relevant lines covered (32.07%)

23733.74 hits per line

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

0.0
/ui/src/efxeditor.cpp
1
/*
2
  Q Light Controller
3
  efxeditor.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 <QTreeWidget>
22
#include <QMessageBox>
23
#include <QPaintEvent>
24
#include <QSettings>
25
#include <QComboBox>
26
#include <QCheckBox>
27
#include <QLineEdit>
28
#include <QCheckBox>
29
#include <QSpinBox>
30
#include <QPainter>
31
#include <QLabel>
32
#include <QDebug>
33
#include <QPen>
34

35
#include "fixtureselection.h"
36
#include "speeddialwidget.h"
37
#include "efxpreviewarea.h"
38
#include "efxeditor.h"
39
#include "fixture.h"
40
#include "doc.h"
41

42
#define SETTINGS_GEOMETRY "efxeditor/geometry"
43

44
#define KColumnNumber  0
45
#define KColumnName    1
46
#define KColumnMode    2
47
#define KColumnReverse 3
48
#define KColumnStartOffset 4
49

50
#define PROPERTY_FIXTURE "fixture"
51
#define UI_STATE_TAB_INDEX "tabIndex"
52
#define UI_STATE_SHOW_DIAL "showDial"
53

54
#define KTabGeneral 0
55
#define KTabMovement 1
56

57
/*****************************************************************************
58
 * Initialization
59
 *****************************************************************************/
60

61
EFXEditor::EFXEditor(QWidget* parent, EFX* efx, Doc* doc)
×
62
    : QWidget(parent)
63
    , m_doc(doc)
64
    , m_efx(efx)
65
    , m_previewArea(NULL)
66
    , m_points(NULL)
67
    , m_speedDials(NULL)
×
68
{
69
    Q_ASSERT(doc != NULL);
×
70
    Q_ASSERT(efx != NULL);
×
71

72
    setupUi(this);
×
73

74
    connect(m_speedDial, SIGNAL(toggled(bool)),
×
75
            this, SLOT(slotSpeedDialToggle(bool)));
76

77
    initGeneralPage();
×
78
    initMovementPage();
×
79

80
    QVariant tabIndex = efx->uiStateValue(UI_STATE_TAB_INDEX);
×
81
    if (tabIndex.isNull())
×
82
        m_tab->setCurrentIndex(0);
×
83
    else
84
        m_tab->setCurrentIndex(tabIndex.toInt());
×
85

86
    /* Tab widget */
87
    connect(m_tab, SIGNAL(currentChanged(int)),
×
88
            this, SLOT(slotTabChanged(int)));
89

90
    // Used for UI parameter changes
91
    m_testTimer.setSingleShot(true);
×
92
    m_testTimer.setInterval(500);
×
93
    connect(&m_testTimer, SIGNAL(timeout()), this, SLOT(slotRestartTest()));
×
94
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)), this, SLOT(slotModeChanged(Doc::Mode)));
×
95

96
    updateSpeedDials();
×
97

98
    QVariant showDial = efx->uiStateValue(UI_STATE_SHOW_DIAL);
×
99
    if (showDial.isNull() == false && showDial.toBool() == true)
×
100
        m_speedDial->setChecked(true);
×
101

102
    // Set focus to the editor
103
    m_nameEdit->setFocus();
×
104
}
×
105

106
EFXEditor::~EFXEditor()
×
107
{
108
    if (m_testButton->isChecked() == true)
×
109
        m_efx->stopAndWait();
×
110
}
×
111

112
void EFXEditor::stopTest()
×
113
{
114
    if (m_testButton->isChecked() == true)
×
115
        m_testButton->click();
×
116
}
×
117

118
void EFXEditor::slotFunctionManagerActive(bool active)
×
119
{
120
    if (active == true)
×
121
    {
122
        updateSpeedDials();
×
123
    }
124
    else
125
    {
126
        if (m_speedDials != NULL)
×
127
            m_speedDials->deleteLater();
×
128
        m_speedDials = NULL;
×
129
    }
130
}
×
131

132
void EFXEditor::initGeneralPage()
×
133
{
134
    // Doc
135
    connect(m_doc, SIGNAL(fixtureRemoved(quint32)), this, SLOT(slotFixtureRemoved()));
×
136
    connect(m_doc, SIGNAL(fixtureChanged(quint32)), this, SLOT(slotFixtureChanged()));
×
137

138
    /* Set the EFX's name to the name field */
139
    m_nameEdit->setText(m_efx->name());
×
140
    m_nameEdit->setSelection(0, m_nameEdit->text().length());
×
141

142
    /* Put all of the EFX's fixtures to the tree view */
143
    updateFixtureTree();
×
144

145
    /* Set propagation mode */
146
    if (m_efx->propagationMode() == EFX::Serial)
×
147
        m_serialRadio->setChecked(true);
×
148
    else if (m_efx->propagationMode() == EFX::Asymmetric)
×
149
        m_asymmetricRadio->setChecked(true);
×
150
    else
151
        m_parallelRadio->setChecked(true);
×
152

153
    /* Disable test button if we're in operate mode */
154
    if (m_doc->mode() == Doc::Operate)
×
155
        m_testButton->setEnabled(false);
×
156

157
    connect(m_nameEdit, SIGNAL(textEdited(const QString&)),
×
158
            this, SLOT(slotNameEdited(const QString&)));
159

160
    connect(m_tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
×
161
            this, SLOT(slotFixtureItemChanged(QTreeWidgetItem*,int)));
162

163
    connect(m_addFixtureButton, SIGNAL(clicked()),
×
164
            this, SLOT(slotAddFixtureClicked()));
165
    connect(m_removeFixtureButton, SIGNAL(clicked()),
×
166
            this, SLOT(slotRemoveFixtureClicked()));
167

168
    connect(m_raiseFixtureButton, SIGNAL(clicked()),
×
169
            this, SLOT(slotRaiseFixtureClicked()));
170
    connect(m_lowerFixtureButton, SIGNAL(clicked()),
×
171
            this, SLOT(slotLowerFixtureClicked()));
172

173
    connect(m_parallelRadio, SIGNAL(toggled(bool)),
×
174
            this, SLOT(slotParallelRadioToggled(bool)));
175
    connect(m_serialRadio, SIGNAL(toggled(bool)),
×
176
            this, SLOT(slotSerialRadioToggled(bool)));
177
    connect(m_asymmetricRadio, SIGNAL(toggled(bool)),
×
178
            this, SLOT(slotAsymmetricRadioToggled(bool)));
179

180
    // Test slots
181
    connect(m_testButton, SIGNAL(clicked()),
×
182
            this, SLOT(slotTestClicked()));
183
    connect(m_raiseFixtureButton, SIGNAL(clicked()),
×
184
            this, SLOT(slotRestartTest()));
185
    connect(m_lowerFixtureButton, SIGNAL(clicked()),
×
186
            this, SLOT(slotRestartTest()));
187
    connect(m_parallelRadio, SIGNAL(toggled(bool)),
×
188
            this, SLOT(slotRestartTest()));
189
    connect(m_serialRadio, SIGNAL(toggled(bool)),
×
190
            this, SLOT(slotRestartTest()));
191
    connect(m_asymmetricRadio, SIGNAL(toggled(bool)),
×
192
            this, SLOT(slotRestartTest()));
193
}
×
194

195
void EFXEditor::initMovementPage()
×
196
{
197
    new QHBoxLayout(m_previewFrame);
×
198
    m_previewArea = new EFXPreviewArea(m_previewFrame);
×
199
    m_previewFrame->layout()->setContentsMargins(0, 0, 0, 0);
×
200
    m_previewFrame->layout()->addWidget(m_previewArea);
×
201

202
    /* Get supported algorithms and fill the algorithm combo with them */
203
    m_algorithmCombo->addItems(EFX::algorithmList());
×
204

205
    QString algo(EFX::algorithmToString(m_efx->algorithm()));
×
206
    /* Select the EFX's algorithm from the algorithm combo */
207
    for (int i = 0; i < m_algorithmCombo->count(); i++)
×
208
    {
209
        if (m_algorithmCombo->itemText(i) == algo)
×
210
        {
211
            m_algorithmCombo->setCurrentIndex(i);
×
212
            break;
×
213
        }
214
    }
215

216
    /* Causes the EFX function to update the preview point array */
217
    slotAlgorithmSelected(algo);
×
218

219
    /* Get the algorithm parameters */
220
    m_widthSpin->setValue(m_efx->width());
×
221
    m_heightSpin->setValue(m_efx->height());
×
222
    m_xOffsetSpin->setValue(m_efx->xOffset());
×
223
    m_yOffsetSpin->setValue(m_efx->yOffset());
×
224
    m_rotationSpin->setValue(m_efx->rotation());
×
225
    m_startOffsetSpin->setValue(m_efx->startOffset());
×
226
    m_isRelativeCheckbox->setChecked(m_efx->isRelative());
×
227

228
    m_xFrequencySpin->setValue(m_efx->xFrequency());
×
229
    m_yFrequencySpin->setValue(m_efx->yFrequency());
×
230
    m_xPhaseSpin->setValue(m_efx->xPhase());
×
231
    m_yPhaseSpin->setValue(m_efx->yPhase());
×
232

233
    /* Running order */
234
    switch (m_efx->runOrder())
×
235
    {
236
        default:
×
237
        case Function::Loop:
238
            m_loop->setChecked(true);
×
239
        break;
×
240
        case Function::SingleShot:
×
241
            m_singleShot->setChecked(true);
×
242
        break;
×
243
        case Function::PingPong:
×
244
            m_pingPong->setChecked(true);
×
245
        break;
×
246
    }
247

248
    /* Direction */
249
    switch (m_efx->direction())
×
250
    {
251
        default:
×
252
        case Function::Forward:
253
            m_forward->setChecked(true);
×
254
        break;
×
255
        case Function::Backward:
×
256
            m_backward->setChecked(true);
×
257
        break;
×
258
    }
259

260
    connect(m_loop, SIGNAL(clicked()),
×
261
            this, SLOT(slotLoopClicked()));
262
    connect(m_singleShot, SIGNAL(clicked()),
×
263
            this, SLOT(slotSingleShotClicked()));
264
    connect(m_pingPong, SIGNAL(clicked()),
×
265
            this, SLOT(slotPingPongClicked()));
266

267
    connect(m_forward, SIGNAL(clicked()),
×
268
            this, SLOT(slotForwardClicked()));
269
    connect(m_backward, SIGNAL(clicked()),
×
270
            this, SLOT(slotBackwardClicked()));
271

272
    connect(m_algorithmCombo, SIGNAL(activated(const QString&)),
×
273
            this, SLOT(slotAlgorithmSelected(const QString&)));
274
    connect(m_widthSpin, SIGNAL(valueChanged(int)),
×
275
            this, SLOT(slotWidthSpinChanged(int)));
276
    connect(m_heightSpin, SIGNAL(valueChanged(int)),
×
277
            this, SLOT(slotHeightSpinChanged(int)));
278
    connect(m_xOffsetSpin, SIGNAL(valueChanged(int)),
×
279
            this, SLOT(slotXOffsetSpinChanged(int)));
280
    connect(m_yOffsetSpin, SIGNAL(valueChanged(int)),
×
281
            this, SLOT(slotYOffsetSpinChanged(int)));
282
    connect(m_rotationSpin, SIGNAL(valueChanged(int)),
×
283
            this, SLOT(slotRotationSpinChanged(int)));
284
    connect(m_startOffsetSpin, SIGNAL(valueChanged(int)),
×
285
            this, SLOT(slotStartOffsetSpinChanged(int)));
286
    connect(m_isRelativeCheckbox, SIGNAL(stateChanged(int)),
×
287
            this, SLOT(slotIsRelativeCheckboxChanged(int)));
288

289
    connect(m_xFrequencySpin, SIGNAL(valueChanged(int)),
×
290
            this, SLOT(slotXFrequencySpinChanged(int)));
291
    connect(m_yFrequencySpin, SIGNAL(valueChanged(int)),
×
292
            this, SLOT(slotYFrequencySpinChanged(int)));
293
    connect(m_xPhaseSpin, SIGNAL(valueChanged(int)),
×
294
            this, SLOT(slotXPhaseSpinChanged(int)));
295
    connect(m_yPhaseSpin, SIGNAL(valueChanged(int)),
×
296
            this, SLOT(slotYPhaseSpinChanged(int)));
297

298
    connect(m_colorCheck, SIGNAL(toggled(bool)),
×
299
            this, SLOT(slotSetColorBackground(bool)));
300

301
    redrawPreview();
×
302
}
×
303

304
void EFXEditor::slotTestClicked()
×
305
{
306
    if (m_testButton->isChecked() == true)
×
307
    {
308
        m_efx->start(m_doc->masterTimer(), functionParent());
×
309

310
        //Restart animation so preview it is in sync with real test
311
        m_previewArea->restart();
×
312
    }
313
    else
314
        m_efx->stopAndWait();
×
315
}
×
316

317
void EFXEditor::slotRestartTest()
×
318
{
319
    if (m_testButton->isChecked() == true)
×
320
    {
321
        // Toggle off, toggle on. Duh.
322
        m_testButton->click();
×
323
        m_testButton->click();
×
324
    }
325
}
×
326

327
void EFXEditor::slotModeChanged(Doc::Mode mode)
×
328
{
329
    if (mode == Doc::Operate)
×
330
    {
331
        m_efx->stopAndWait();
×
332
        m_testButton->setChecked(false);
×
333
        m_testButton->setEnabled(false);
×
334
    }
335
    else
336
    {
337
        m_testButton->setEnabled(true);
×
338
    }
339
}
×
340

341
void EFXEditor::slotTabChanged(int tab)
×
342
{
343
    m_efx->setUiStateValue(UI_STATE_TAB_INDEX, tab);
×
344

345
    //When preview animation is opened restart animation but avoid restart if test is running.
NEW
346
    if (tab == 1 && (m_testButton->isChecked () == false))
×
347
        m_previewArea->restart ();
×
348
}
×
349

350
void EFXEditor::slotSetColorBackground(bool checked)
×
351
{
352
    m_previewArea->showGradientBackground(checked);
×
353
}
×
354

355
bool EFXEditor::interruptRunning()
×
356
{
357
    if (m_testButton->isChecked() == true)
×
358
    {
359
        m_efx->stopAndWait();
×
360
        m_testButton->setChecked(false);
×
361
        return true;
×
362
    }
363
    else
364
    {
365
        return false;
×
366
    }
367
}
368

369
void EFXEditor::continueRunning(bool running)
×
370
{
371
    if (running == true)
×
372
    {
373
        if (m_doc->mode() == Doc::Operate)
×
374
            m_efx->start(m_doc->masterTimer(), functionParent());
×
375
        else
376
            m_testButton->click();
×
377
    }
378
}
×
379

380
FunctionParent EFXEditor::functionParent() const
×
381
{
382
    return FunctionParent::master();
×
383
}
384

385
/*****************************************************************************
386
 * General page
387
 *****************************************************************************/
388

389
void EFXEditor::updateFixtureTree()
×
390
{
391
    m_tree->clear();
×
392
    QListIterator <EFXFixture*> it(m_efx->fixtures());
×
393
    while (it.hasNext() == true)
×
394
        addFixtureItem(it.next());
×
395
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
396
}
×
397

398
QTreeWidgetItem* EFXEditor::fixtureItem(EFXFixture* ef)
×
399
{
400
    QTreeWidgetItemIterator it(m_tree);
×
401
    while (*it != NULL)
×
402
    {
403
        QTreeWidgetItem* item = *it;
×
404
        EFXFixture* ef_item = reinterpret_cast<EFXFixture*>
405
                              (item->data(0, Qt::UserRole).toULongLong());
×
406
        if (ef_item == ef)
×
407
            return item;
×
408
        ++it;
×
409
    }
410

411
    return NULL;
×
412
}
413

414
const QList <EFXFixture*> EFXEditor::selectedFixtures() const
×
415
{
416
    QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
417
    QList <EFXFixture*> list;
×
418

419
    /* Put all selected fixture IDs to a list and return it */
420
    while (it.hasNext() == true)
×
421
    {
422
        EFXFixture* ef = reinterpret_cast <EFXFixture*>
423
                         (it.next()->data(0, Qt::UserRole).toULongLong());
×
424
        list << ef;
×
425
    }
426

427
    return list;
×
428
}
429

430
void EFXEditor::updateIndices(int from, int to)
×
431
{
432
    for (int i = from; i <= to; i++)
×
433
    {
434
        QTreeWidgetItem *item = m_tree->topLevelItem(i);
×
435
        Q_ASSERT(item != NULL);
×
436

437
        item->setText(KColumnNumber,
×
438
                      QString("%1").arg(i + 1, 3, 10, QChar('0')));
×
439
    }
440
}
×
441

442
void EFXEditor::addFixtureItem(EFXFixture* ef)
×
443
{
444
    QTreeWidgetItem* item;
445
    Fixture* fxi;
446

447
    Q_ASSERT(ef != NULL);
×
448

449
    fxi = m_doc->fixture(ef->head().fxi);
×
450
    if (fxi == NULL)
×
451
        return;
×
452

453
    item = new QTreeWidgetItem(m_tree);
×
454

455
    if (fxi->heads() > 1)
×
456
    {
457
        item->setText(KColumnName, QString("%1 [%2]").arg(fxi->name()).arg(ef->head().head));
×
458
    }
459
    else
460
    {
461
        item->setText(KColumnName, fxi->name());
×
462
    }
463
    item->setData(0, Qt::UserRole, QVariant(reinterpret_cast<qulonglong> (ef)));
×
464
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
×
465

466
    if (ef->direction() == Function::Backward)
×
467
        item->setCheckState(KColumnReverse, Qt::Checked);
×
468
    else
469
        item->setCheckState(KColumnReverse, Qt::Unchecked);
×
470

471
    updateModeColumn(item, ef);
×
472
    updateStartOffsetColumn(item, ef);
×
473

474
    updateIndices(m_tree->indexOfTopLevelItem(item),
×
475
                  m_tree->topLevelItemCount() - 1);
×
476

477
    /* Select newly-added fixtures so that they can be moved quickly */
478
    m_tree->setCurrentItem(item);
×
479
}
480

481
void EFXEditor::updateModeColumn(QTreeWidgetItem* item, EFXFixture* ef)
×
482
{
483
    Q_ASSERT(item != NULL);
×
484
    Q_ASSERT(ef != NULL);
×
485

486
    if (m_tree->itemWidget(item, KColumnMode) == NULL)
×
487
    {
488
        QComboBox* combo = new QComboBox(m_tree);
×
489
        combo->setAutoFillBackground(true);
×
490
        combo->addItems(ef->modeList());
×
491
        combo->setProperty(PROPERTY_FIXTURE, (qulonglong) ef);
×
492
        m_tree->setItemWidget(item, KColumnMode, combo);
×
493

494
        const int index = combo->findText(ef->modeToString(ef->mode()));
×
495
        combo->setCurrentIndex(index);
×
496

497
        connect(combo, SIGNAL(currentIndexChanged(int)),
×
498
                this, SLOT(slotFixtureModeChanged(int)));
499
    }
500
}
×
501

502
void EFXEditor::updateStartOffsetColumn(QTreeWidgetItem* item, EFXFixture* ef)
×
503
{
504
    Q_ASSERT(item != NULL);
×
505
    Q_ASSERT(ef != NULL);
×
506

507
    if (m_tree->itemWidget(item, KColumnStartOffset) == NULL)
×
508
    {
509
        QSpinBox* spin = new QSpinBox(m_tree);
×
510
        spin->setAutoFillBackground(true);
×
511
        spin->setRange(0, 359);
×
512
        spin->setValue(ef->startOffset());
×
513
        spin->setSuffix(QChar(0x00b0)); // degree
×
514
        m_tree->setItemWidget(item, KColumnStartOffset, spin);
×
515
        spin->setProperty(PROPERTY_FIXTURE, (qulonglong) ef);
×
516
        connect(spin, SIGNAL(valueChanged(int)),
×
517
                this, SLOT(slotFixtureStartOffsetChanged(int)));
518
    }
519
}
×
520

521
void EFXEditor::removeFixtureItem(EFXFixture* ef)
×
522
{
523
    QTreeWidgetItem* item;
524
    int from;
525

526
    Q_ASSERT(ef != NULL);
×
527

528
    item = fixtureItem(ef);
×
529
    Q_ASSERT(item != NULL);
×
530

531
    from = m_tree->indexOfTopLevelItem(item);
×
532
    delete item;
×
533

534
    updateIndices(from, m_tree->topLevelItemCount() - 1);
×
535
    redrawPreview();
×
536

537
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
538
}
×
539

540
void EFXEditor::slotDialDestroyed(QObject *)
×
541
{
542
    m_speedDial->setChecked(false);
×
543
}
×
544

545
void EFXEditor::createSpeedDials()
×
546
{
547
    if (m_speedDials == NULL)
×
548
    {
549
        m_speedDials = new SpeedDialWidget(this);
×
550
        m_speedDials->setAttribute(Qt::WA_DeleteOnClose);
×
551
        connect(m_speedDials, SIGNAL(fadeInChanged(int)), this, SLOT(slotFadeInChanged(int)));
×
552
        connect(m_speedDials, SIGNAL(fadeOutChanged(int)), this, SLOT(slotFadeOutChanged(int)));
×
553
        connect(m_speedDials, SIGNAL(holdChanged(int)), this, SLOT(slotHoldChanged(int)));
×
554
        connect(m_speedDials, SIGNAL(destroyed(QObject*)), this, SLOT(slotDialDestroyed(QObject*)));
×
555
    }
556

557
    m_speedDials->show();
×
558
}
×
559

560
void EFXEditor::updateSpeedDials()
×
561
{
562
   if (m_speedDial->isChecked() == false)
×
563
        return;
×
564

565
    createSpeedDials();
×
566

567
    m_speedDials->setWindowTitle(m_efx->name());
×
568
    m_speedDials->setFadeInSpeed(m_efx->fadeInSpeed());
×
569
    m_speedDials->setFadeOutSpeed(m_efx->fadeOutSpeed());
×
570
    if ((int)m_efx->duration() < 0)
×
571
        m_speedDials->setDuration(m_efx->duration());
×
572
    else
573
        m_speedDials->setDuration(m_efx->duration() - m_efx->fadeInSpeed() - m_efx->fadeOutSpeed());
×
574
}
575

576
void EFXEditor::slotNameEdited(const QString &text)
×
577
{
578
    m_efx->setName(text);
×
579
    if (m_speedDials)
×
580
        m_speedDials->setWindowTitle(text);
×
581
}
×
582

583
void EFXEditor::slotSpeedDialToggle(bool state)
×
584
{
585
    if (state == true)
×
586
    {
587
        updateSpeedDials();
×
588
    }
589
    else
590
    {
591
        if (m_speedDials != NULL)
×
592
            m_speedDials->deleteLater();
×
593
        m_speedDials = NULL;
×
594
    }
595

596
    m_efx->setUiStateValue(UI_STATE_SHOW_DIAL, state);
×
597
}
×
598

599
void EFXEditor::slotFixtureItemChanged(QTreeWidgetItem* item, int column)
×
600
{
601
    if (column == KColumnReverse)
×
602
    {
603
        EFXFixture* ef = reinterpret_cast <EFXFixture*>
604
                         (item->data(0, Qt::UserRole).toULongLong());
×
605
        Q_ASSERT(ef != NULL);
×
606

607
        if (item->checkState(column) == Qt::Checked)
×
608
            ef->setDirection(Function::Backward);
×
609
        else
610
            ef->setDirection(Function::Forward);
×
611

612
        redrawPreview();
×
613
    }
614
}
×
615

616
void EFXEditor::slotFixtureModeChanged(int index)
×
617
{
NEW
618
    QComboBox *combo = qobject_cast<QComboBox*>(QObject::sender());
×
619
    Q_ASSERT(combo != NULL);
×
620

NEW
621
    EFXFixture *ef = (EFXFixture*) combo->property(PROPERTY_FIXTURE).toULongLong();
×
622
    Q_ASSERT(ef != NULL);
×
623

NEW
624
    ef->setMode(ef->stringToMode (combo->itemText(index)));
×
625

626
    // Restart the test after the latest mode change, delayed
627
    m_testTimer.start();
×
628
}
×
629

630
void EFXEditor::slotFixtureStartOffsetChanged(int startOffset)
×
631
{
NEW
632
    QSpinBox *spin = qobject_cast<QSpinBox*>(QObject::sender());
×
633
    Q_ASSERT(spin != NULL);
×
NEW
634
    EFXFixture *ef = (EFXFixture*) spin->property(PROPERTY_FIXTURE).toULongLong();
×
635
    Q_ASSERT(ef != NULL);
×
636
    ef->setStartOffset(startOffset);
×
637

638
    redrawPreview();
×
639

640
    // Restart the test after the latest offset change, delayed
641
    m_testTimer.start();
×
642
}
×
643

644
void EFXEditor::slotAddFixtureClicked()
×
645
{
646
    /* The following code is the original QLC+ code (EFX with only Pan-Tilt).
647
     * Now, with modes, the same fixture could be duplicated. */
648

649
    /* Put all fixtures already present into a list of fixtures that
650
       will be disabled in the fixture selection dialog */
651
    QList <GroupHead> disabled;
×
652
    QTreeWidgetItemIterator twit(m_tree);
×
653
    /*
654
    while (*twit != NULL)
655
    {
656
        EFXFixture* ef = reinterpret_cast <EFXFixture*>
657
                         ((*twit)->data(0, Qt::UserRole).toULongLong());
658
        Q_ASSERT(ef != NULL);
659

660
        disabled.append(ef->head());
661
        twit++;
662
    }
663
    */
664

665
    /* Disable all fixtures that don't have pan OR tilt, dimmer or RGB channels */
666
    /*
667
    QListIterator <Fixture*> fxit(m_doc->fixtures());
668
    while (fxit.hasNext() == true)
669
    {
670
        Fixture* fixture(fxit.next());
671
        Q_ASSERT(fixture != NULL);
672

673
        // If a channel with pan or tilt group exists, don't disable this fixture
674
        if (fixture->channel(QLCChannel::Pan) == QLCChannel::invalid() &&
675
            fixture->channel(QLCChannel::Tilt) == QLCChannel::invalid())
676
        {
677
            // Disable all fixtures without pan or tilt channels
678
            disabled << fixture->id();
679
        }
680
        else
681
        {
682
            QVector <QLCFixtureHead> const& heads = fixture->fixtureMode()->heads();
683
            for (int i = 0; i < heads.size(); ++i)
684
            {
685
                if (heads[i].panMsbChannel() == QLCChannel::invalid() &&
686
                    heads[i].tiltMsbChannel() == QLCChannel::invalid() &&
687
                    heads[i].panLsbChannel() == QLCChannel::invalid() &&
688
                    heads[i].tiltLsbChannel() == QLCChannel::invalid())
689
                {
690
                    // Disable heads without pan or tilt channels
691
                    disabled << GroupHead(fixture->id(), i);
692
                }
693
            }
694
        }
695
    }
696
    */
697

698
    FixtureSelection fs(this, m_doc);
×
699
    fs.setMultiSelection(true);
×
700
    fs.setSelectionMode(FixtureSelection::Heads);
×
701
    fs.setDisabledHeads(disabled);
×
702
    if (fs.exec() == QDialog::Accepted)
×
703
    {
704
        // Stop running while adding fixtures
705
        bool running = interruptRunning();
×
706

707
        QListIterator <GroupHead> it(fs.selectedHeads());
×
708
        while (it.hasNext() == true)
×
709
        {
710
            EFXFixture* ef = new EFXFixture(m_efx);
×
711
            ef->setHead(it.next());
×
712

713
            if (m_efx->addFixture(ef) == true)
×
714
                addFixtureItem(ef);
×
715
            else
716
                delete ef;
×
717
        }
718

719
        m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
720

721
        redrawPreview();
×
722

723
        // Continue running if appropriate
724
        continueRunning(running);
×
725
    }
726
}
×
727

728
void EFXEditor::slotRemoveFixtureClicked()
×
729
{
730
    int r = QMessageBox::question(
×
731
                this, tr("Remove fixtures"),
×
732
                tr("Do you want to remove the selected fixture(s)?"),
×
733
                QMessageBox::Yes, QMessageBox::No);
734

735
    if (r == QMessageBox::Yes)
×
736
    {
737
        // Stop running while removing fixtures
738
        bool running = interruptRunning();
×
739

740
        QListIterator <EFXFixture*> it(selectedFixtures());
×
741
        while (it.hasNext() == true)
×
742
        {
743
            EFXFixture* ef = it.next();
×
744
            Q_ASSERT(ef != NULL);
×
745

746
            removeFixtureItem(ef);
×
747
            if (m_efx->removeFixture(ef) == true)
×
748
                delete ef;
×
749
        }
750

751
        redrawPreview();
×
752

753
        // Continue if appropriate
754
        continueRunning(running);
×
755
    }
756
}
×
757

758
void EFXEditor::slotRaiseFixtureClicked()
×
759
{
760
    // Stop running while moving fixtures
761
    bool running = interruptRunning();
×
762

763
    QTreeWidgetItem* item = m_tree->currentItem();
×
764
    if (item != NULL)
×
765
    {
766
        int index = m_tree->indexOfTopLevelItem(item);
×
767
        if (index == 0)
×
768
            return;
×
769

770
        EFXFixture* ef = reinterpret_cast <EFXFixture*>
771
                         (item->data(0, Qt::UserRole).toULongLong());
×
772
        Q_ASSERT(ef != NULL);
×
773

774
        if (m_efx->raiseFixture(ef) == true)
×
775
        {
776
            item = m_tree->takeTopLevelItem(index);
×
777

778
            m_tree->insertTopLevelItem(index - 1, item);
×
779

780
            updateModeColumn(item, ef);
×
781
            updateStartOffsetColumn(item, ef);
×
782
            updateIndices(index - 1, index);
×
783
            m_tree->setCurrentItem(item);
×
784

785
            redrawPreview();
×
786
        }
787
    }
788

789
    // Continue running if appropriate
790
    continueRunning(running);
×
791
}
792

793
void EFXEditor::slotLowerFixtureClicked()
×
794
{
795
    // Stop running while moving fixtures
796
    bool running = interruptRunning();
×
797

798
    QTreeWidgetItem* item = m_tree->currentItem();
×
799
    if (item != NULL)
×
800
    {
801
        int index = m_tree->indexOfTopLevelItem(item);
×
802
        if (index == (m_tree->topLevelItemCount() - 1))
×
803
            return;
×
804

805
        EFXFixture* ef = reinterpret_cast <EFXFixture*>
806
                         (item->data(0, Qt::UserRole).toULongLong());
×
807
        Q_ASSERT(ef != NULL);
×
808

809
        if (m_efx->lowerFixture(ef) == true)
×
810
        {
811
            item = m_tree->takeTopLevelItem(index);
×
812
            m_tree->insertTopLevelItem(index + 1, item);
×
813

814
            updateModeColumn(item, ef);
×
815
            updateStartOffsetColumn(item, ef);
×
816
            updateIndices(index, index + 1);
×
817
            m_tree->setCurrentItem(item);
×
818

819
            redrawPreview();
×
820
        }
821
    }
822

823
    // Continue running if appropriate
824
    continueRunning(running);
×
825
}
826

827
void EFXEditor::slotParallelRadioToggled(bool state)
×
828
{
829
    Q_ASSERT(m_efx != NULL);
×
830
    if (state == true)
×
831
        m_efx->setPropagationMode(EFX::Parallel);
×
832
}
×
833

834
void EFXEditor::slotSerialRadioToggled(bool state)
×
835
{
836
    Q_ASSERT(m_efx != NULL);
×
837
    if (state == true)
×
838
        m_efx->setPropagationMode(EFX::Serial);
×
839
}
×
840

841
void EFXEditor::slotAsymmetricRadioToggled(bool state)
×
842
{
843
    Q_ASSERT(m_efx != NULL);
×
844
    if (state == true)
×
845
        m_efx->setPropagationMode(EFX::Asymmetric);
×
846
}
×
847

848
void EFXEditor::slotFadeInChanged(int ms)
×
849
{
850
    m_efx->setFadeInSpeed(ms);
×
851
    slotRestartTest();
×
852
}
×
853

854
void EFXEditor::slotFadeOutChanged(int ms)
×
855
{
856
    m_efx->setFadeOutSpeed(ms);
×
857
}
×
858

859
void EFXEditor::slotHoldChanged(int ms)
×
860
{
861
    uint duration = 0;
×
862
    if (ms < 0)
×
863
        duration = ms;
×
864
    else
865
        duration = m_efx->fadeInSpeed() + ms + m_efx->fadeOutSpeed();
×
866
    m_efx->setDuration(duration);
×
867
    redrawPreview();
×
868
}
×
869

870
void EFXEditor::slotFixtureRemoved()
×
871
{
872
    // EFX already catches fixture removals so just update the list
873
    updateFixtureTree();
×
874
    redrawPreview();
×
875
}
×
876

877
void EFXEditor::slotFixtureChanged()
×
878
{
879
    // Update the tree in case fixture's name changes
880
    updateFixtureTree();
×
881
}
×
882

883
/*****************************************************************************
884
 * Movement page
885
 *****************************************************************************/
886

887
void EFXEditor::slotAlgorithmSelected(const QString &text)
×
888
{
889
    Q_ASSERT(m_efx != NULL);
×
890

891
    EFX::Algorithm algo = EFX::stringToAlgorithm(text);
×
892
    m_efx->setAlgorithm(algo);
×
893

894
    if (m_efx->isFrequencyEnabled())
×
895
    {
896
        m_xFrequencyLabel->setEnabled(true);
×
897
        m_yFrequencyLabel->setEnabled(true);
×
898

899
        m_xFrequencySpin->setEnabled(true);
×
900
        m_yFrequencySpin->setEnabled(true);
×
901
    }
902
    else
903
    {
904
        m_xFrequencyLabel->setEnabled(false);
×
905
        m_yFrequencyLabel->setEnabled(false);
×
906

907
        m_xFrequencySpin->setEnabled(false);
×
908
        m_yFrequencySpin->setEnabled(false);
×
909
    }
910

911
    if (m_efx->isPhaseEnabled())
×
912
    {
913
        m_xPhaseLabel->setEnabled(true);
×
914
        m_yPhaseLabel->setEnabled(true);
×
915

916
        m_xPhaseSpin->setEnabled(true);
×
917
        m_yPhaseSpin->setEnabled(true);
×
918
    }
919
    else
920
    {
921
        m_xPhaseLabel->setEnabled(false);
×
922
        m_yPhaseLabel->setEnabled(false);
×
923

924
        m_xPhaseSpin->setEnabled(false);
×
925
        m_yPhaseSpin->setEnabled(false);
×
926
    }
927

928
    redrawPreview();
×
929
}
×
930

931
void EFXEditor::slotWidthSpinChanged(int value)
×
932
{
933
    Q_ASSERT(m_efx != NULL);
×
934
    m_efx->setWidth(value);
×
935
    redrawPreview();
×
936
}
×
937

938
void EFXEditor::slotHeightSpinChanged(int value)
×
939
{
940
    Q_ASSERT(m_efx != NULL);
×
941
    m_efx->setHeight(value);
×
942
    redrawPreview();
×
943
}
×
944

945
void EFXEditor::slotRotationSpinChanged(int value)
×
946
{
947
    Q_ASSERT(m_efx != NULL);
×
948
    m_efx->setRotation(value);
×
949
    redrawPreview();
×
950
}
×
951

952
void EFXEditor::slotStartOffsetSpinChanged(int value)
×
953
{
954
    Q_ASSERT(m_efx != NULL);
×
955
    m_efx->setStartOffset(value);
×
956
    redrawPreview();
×
957
}
×
958

959
void EFXEditor::slotIsRelativeCheckboxChanged(int value)
×
960
{
961
    Q_ASSERT(m_efx != NULL);
×
962
    m_efx->setIsRelative(value == Qt::Checked);
×
963
}
×
964

965
void EFXEditor::slotXOffsetSpinChanged(int value)
×
966
{
967
    Q_ASSERT(m_efx != NULL);
×
968
    m_efx->setXOffset(value);
×
969
    redrawPreview();
×
970
}
×
971

972
void EFXEditor::slotYOffsetSpinChanged(int value)
×
973
{
974
    Q_ASSERT(m_efx != NULL);
×
975
    m_efx->setYOffset(value);
×
976
    redrawPreview();
×
977
}
×
978

979
void EFXEditor::slotXFrequencySpinChanged(int value)
×
980
{
981
    Q_ASSERT(m_efx != NULL);
×
982
    m_efx->setXFrequency(value);
×
983
    redrawPreview();
×
984
}
×
985

986
void EFXEditor::slotYFrequencySpinChanged(int value)
×
987
{
988
    Q_ASSERT(m_efx != NULL);
×
989
    m_efx->setYFrequency(value);
×
990
    redrawPreview();
×
991
}
×
992

993
void EFXEditor::slotXPhaseSpinChanged(int value)
×
994
{
995
    Q_ASSERT(m_efx != NULL);
×
996
    m_efx->setXPhase(value);
×
997
    redrawPreview();
×
998
}
×
999

1000
void EFXEditor::slotYPhaseSpinChanged(int value)
×
1001
{
1002
    Q_ASSERT(m_efx != NULL);
×
1003
    m_efx->setYPhase(value);
×
1004
    redrawPreview();
×
1005
}
×
1006

1007
/*****************************************************************************
1008
 * Run order
1009
 *****************************************************************************/
1010

1011
void EFXEditor::slotLoopClicked()
×
1012
{
1013
    Q_ASSERT(m_efx != NULL);
×
1014
    m_efx->setRunOrder(Function::Loop);
×
1015
}
×
1016

1017
void EFXEditor::slotSingleShotClicked()
×
1018
{
1019
    Q_ASSERT(m_efx != NULL);
×
1020
    m_efx->setRunOrder(Function::SingleShot);
×
1021
}
×
1022

1023
void EFXEditor::slotPingPongClicked()
×
1024
{
1025
    Q_ASSERT(m_efx != NULL);
×
1026
    m_efx->setRunOrder(Function::PingPong);
×
1027
}
×
1028

1029
/*****************************************************************************
1030
 * Direction
1031
 *****************************************************************************/
1032

1033
void EFXEditor::slotForwardClicked()
×
1034
{
1035
    Q_ASSERT(m_efx != NULL);
×
1036
    m_efx->setDirection(Function::Forward);
×
1037
    redrawPreview();
×
1038
}
×
1039

1040
void EFXEditor::slotBackwardClicked()
×
1041
{
1042
    Q_ASSERT(m_efx != NULL);
×
1043
    m_efx->setDirection(Function::Backward);
×
1044
    redrawPreview();
×
1045
}
×
1046

1047
void EFXEditor::redrawPreview()
×
1048
{
1049
    if (m_previewArea == NULL)
×
1050
        return;
×
1051

1052
    QPolygonF polygon;
×
1053
    m_efx->preview(polygon);
×
1054

1055
    QVector <QPolygonF> fixturePoints;
×
1056
    m_efx->previewFixtures(fixturePoints);
×
1057

1058
    m_previewArea->setPolygon(polygon);
×
1059
    m_previewArea->setFixturePolygons(fixturePoints);
×
1060

1061
    m_previewArea->draw(m_efx->duration() / polygon.size());
×
1062
}
1063

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