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

mcallegari / qlcplus / 16450929051

22 Jul 2025 05:09PM UTC coverage: 34.174% (-0.1%) from 34.286%
16450929051

Pull #1782

github

web-flow
Merge f80a306ab into 8a22b7b84
Pull Request #1782: Feature: Control RGB Matrix script properties with VC Knobs in animation widget

7 of 189 new or added lines in 6 files covered. (3.7%)

9 existing lines in 4 files now uncovered.

17704 of 51806 relevant lines covered (34.17%)

19373.32 hits per line

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

0.0
/ui/src/rgbmatrixeditor.cpp
1
/*
2
  Q Light Controller
3
  rgbmatrixeditor.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 <QGraphicsEllipseItem>
21
#include <QGraphicsRectItem>
22
#include <QGraphicsEffect>
23
#include <QGraphicsScene>
24
#include <QGraphicsView>
25
#include <QColorDialog>
26
#include <QFileDialog>
27
#include <QFontDialog>
28
#include <QGradient>
29
#include <QSettings>
30
#include <QComboBox>
31
#include <QLineEdit>
32
#include <QSpinBox>
33
#include <QLabel>
34
#include <QTimer>
35
#include <QDebug>
36
#include <QMutex>
37

38
#include "fixtureselection.h"
39
#include "speeddialwidget.h"
40
#include "rgbmatrixeditor.h"
41
#include "qlcfixturehead.h"
42
#include "qlcmacros.h"
43
#include "rgbimage.h"
44
#include "sequence.h"
45
#include "rgbitem.h"
46
#include "rgbtext.h"
47
#include "scene.h"
48

49
#define SETTINGS_GEOMETRY "rgbmatrixeditor/geometry"
50
#define RECT_SIZE 30
51
#define RECT_PADDING 0
52
#define ITEM_SIZE 28
53
#define ITEM_PADDING 2
54

55
/****************************************************************************
56
 * Initialization
57
 ****************************************************************************/
58

59
RGBMatrixEditor::RGBMatrixEditor(QWidget* parent, RGBMatrix* mtx, Doc* doc)
×
60
    : QWidget(parent)
61
    , m_doc(doc)
×
62
    , m_matrix(mtx)
×
63
    , m_previewHandler(new RGBMatrixStep())
×
64
    , m_speedDials(NULL)
×
65
    , m_scene(new QGraphicsScene(this))
×
66
    , m_previewTimer(new QTimer(this))
×
67
    , m_previewIterator(0)
×
68
{
69
    Q_ASSERT(doc != NULL);
×
70
    Q_ASSERT(mtx != NULL);
×
71

72
    setupUi(this);
×
73

74
    // Set a nice gradient backdrop
75
    m_scene->setBackgroundBrush(Qt::darkGray);
×
76
    QLinearGradient gradient(200, 200, 200, 2000);
×
77
    gradient.setSpread(QGradient::ReflectSpread);
×
78
    m_scene->setBackgroundBrush(gradient);
×
79

80
    connect(m_previewTimer, SIGNAL(timeout()), this, SLOT(slotPreviewTimeout()));
×
81
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)), this, SLOT(slotModeChanged(Doc::Mode)));
×
82
    connect(m_doc, SIGNAL(fixtureGroupAdded(quint32)), this, SLOT(slotFixtureGroupAdded()));
×
83
    connect(m_doc, SIGNAL(fixtureGroupRemoved(quint32)), this, SLOT(slotFixtureGroupRemoved()));
×
84
    connect(m_doc, SIGNAL(fixtureGroupChanged(quint32)), this, SLOT(slotFixtureGroupChanged(quint32)));
×
85

86
    init();
×
87

88
    slotModeChanged(m_doc->mode());
×
89

90
    // Set focus to the editor
91
    m_nameEdit->setFocus();
×
92
}
×
93

94
RGBMatrixEditor::~RGBMatrixEditor()
×
95
{
96
    m_previewTimer->stop();
×
97

98
    if (m_testButton->isChecked() == true)
×
99
        m_matrix->stopAndWait();
×
100

101
    delete m_previewHandler;
×
102

103
    qDeleteAll(m_previewHash);
×
104
}
×
105

106
void RGBMatrixEditor::stopTest()
×
107
{
108
    if (m_testButton->isChecked() == true)
×
109
        m_testButton->click();
×
110
}
×
111

112
void RGBMatrixEditor::slotFunctionManagerActive(bool active)
×
113
{
114
    if (active == true)
×
115
    {
116
        if (m_speedDials == NULL)
×
117
            updateSpeedDials();
×
118
    }
119
    else
120
    {
121
        if (m_speedDials != NULL)
×
122
            m_speedDials->deleteLater();
×
123
        m_speedDials = NULL;
×
124
    }
125
}
×
126

127
void RGBMatrixEditor::init()
×
128
{
NEW
129
    QSizePolicy sp = scrollArea->widget()->sizePolicy();
×
NEW
130
    sp.setHorizontalPolicy(QSizePolicy::Ignored);
×
NEW
131
    scrollArea->widget()->setSizePolicy(sp);
×
132

133
    /* Name */
134
    m_nameEdit->setText(m_matrix->name());
×
135
    m_nameEdit->setSelection(0, m_matrix->name().length());
×
136

137
    /* Running order */
138
    switch (m_matrix->runOrder())
×
139
    {
140
        default:
×
141
        case Function::Loop:
142
            m_loop->setChecked(true);
×
143
        break;
×
144
        case Function::PingPong:
×
145
            m_pingPong->setChecked(true);
×
146
        break;
×
147
        case Function::SingleShot:
×
148
            m_singleShot->setChecked(true);
×
149
        break;
×
150
    }
151

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

164

165
    /* Blend mode */
166
    m_blendModeCombo->setCurrentIndex(m_matrix->blendMode());
×
167

168
    /* Color mode */
169
    m_controlModeCombo->setCurrentIndex(m_matrix->controlMode());
×
170

171
    /* Dimmer control */
172
    if (m_matrix->dimmerControl())
×
173
        m_dimmerControlCb->setChecked(m_matrix->dimmerControl());
×
174
    else
175
        m_intensityGroup->hide();
×
176

177
    fillPatternCombo();
×
178
    fillFixtureGroupCombo();
×
179
    fillAnimationCombo();
×
180
    fillImageAnimationCombo();
×
181

182
    QPixmap pm(50, 26);
×
183
    pm.fill(m_matrix->getColor(0));
×
184
    m_mtxColor1Button->setIcon(QIcon(pm));
×
185

186
    if (m_matrix->getColor(1).isValid())
×
187
        pm.fill(m_matrix->getColor(1));
×
188
    else
189
        pm.fill(Qt::transparent);
×
190
    m_mtxColor2Button->setIcon(QIcon(pm));
×
191

192
    if (m_matrix->getColor(2).isValid())
×
193
        pm.fill(m_matrix->getColor(2));
×
194
    else
195
        pm.fill(Qt::transparent);
×
196
    m_mtxColor3Button->setIcon(QIcon(pm));
×
197

198
    if (m_matrix->getColor(3).isValid())
×
199
        pm.fill(m_matrix->getColor(3));
×
200
    else
201
        pm.fill(Qt::transparent);
×
202
    m_mtxColor4Button->setIcon(QIcon(pm));
×
203

204
    if (m_matrix->getColor(4).isValid())
×
205
        pm.fill(m_matrix->getColor(4));
×
206
    else
207
        pm.fill(Qt::transparent);
×
208
    m_mtxColor5Button->setIcon(QIcon(pm));
×
209

210
    updateExtraOptions();
×
211
    updateSpeedDials();
×
212

213
    connect(m_nameEdit, SIGNAL(textEdited(const QString&)),
×
214
            this, SLOT(slotNameEdited(const QString&)));
215
    connect(m_speedDialButton, SIGNAL(toggled(bool)),
×
216
            this, SLOT(slotSpeedDialToggle(bool)));
217
    connect(m_saveToSequenceButton, SIGNAL(clicked()),
×
218
            this, SLOT(slotSaveToSequenceClicked()));
219
    connect(m_shapeButton, SIGNAL(toggled(bool)),
×
220
            this, SLOT(slotShapeToggle(bool)));
221
    connect(m_patternCombo, SIGNAL(activated(int)),
×
222
            this, SLOT(slotPatternActivated(int)));
223
    connect(m_fixtureGroupCombo, SIGNAL(activated(int)),
×
224
            this, SLOT(slotFixtureGroupActivated(int)));
225
    connect(m_blendModeCombo, SIGNAL(activated(int)),
×
226
            this, SLOT(slotBlendModeChanged(int)));
227
    connect(m_controlModeCombo, SIGNAL(activated(int)),
×
228
            this, SLOT(slotControlModeChanged(int)));
229
    connect(m_mtxColor1Button, SIGNAL(clicked()),
×
230
            this, SLOT(slotMtxColor1ButtonClicked()));
231
    connect(m_mtxColor2Button, SIGNAL(clicked()),
×
232
            this, SLOT(slotMtxColor2ButtonClicked()));
233
    connect(m_resetMtxColor2Button, SIGNAL(clicked()),
×
234
            this, SLOT(slotResetMtxColor2ButtonClicked()));
235
    connect(m_mtxColor3Button, SIGNAL(clicked()),
×
236
            this, SLOT(slotMtxColor3ButtonClicked()));
237
    connect(m_resetMtxColor3Button, SIGNAL(clicked()),
×
238
            this, SLOT(slotResetMtxColor3ButtonClicked()));
239
    connect(m_mtxColor4Button, SIGNAL(clicked()),
×
240
            this, SLOT(slotMtxColor4ButtonClicked()));
241
    connect(m_resetMtxColor4Button, SIGNAL(clicked()),
×
242
            this, SLOT(slotResetMtxColor4ButtonClicked()));
243
    connect(m_mtxColor5Button, SIGNAL(clicked()),
×
244
            this, SLOT(slotMtxColor5ButtonClicked()));
245
    connect(m_resetMtxColor5Button, SIGNAL(clicked()),
×
246
            this, SLOT(slotResetMtxColor5ButtonClicked()));
247
    connect(m_textEdit, SIGNAL(textEdited(const QString&)),
×
248
            this, SLOT(slotTextEdited(const QString&)));
249
    connect(m_fontButton, SIGNAL(clicked()),
×
250
            this, SLOT(slotFontButtonClicked()));
251
    connect(m_animationCombo, SIGNAL(activated(int)),
×
252
            this, SLOT(slotAnimationActivated(int)));
253
    connect(m_imageEdit, SIGNAL(editingFinished()),
×
254
            this, SLOT(slotImageEdited()));
255
    connect(m_imageButton, SIGNAL(clicked()),
×
256
            this, SLOT(slotImageButtonClicked()));
257
    connect(m_imageAnimationCombo, SIGNAL(activated(int)),
×
258
            this, SLOT(slotImageAnimationActivated(int)));
259
    connect(m_xOffsetSpin, SIGNAL(valueChanged(int)),
×
260
            this, SLOT(slotOffsetSpinChanged()));
261
    connect(m_yOffsetSpin, SIGNAL(valueChanged(int)),
×
262
            this, SLOT(slotOffsetSpinChanged()));
263

264
    connect(m_loop, SIGNAL(clicked()), this, SLOT(slotLoopClicked()));
×
265
    connect(m_pingPong, SIGNAL(clicked()), this, SLOT(slotPingPongClicked()));
×
266
    connect(m_singleShot, SIGNAL(clicked()), this, SLOT(slotSingleShotClicked()));
×
267
    connect(m_forward, SIGNAL(clicked()), this, SLOT(slotForwardClicked()));
×
268
    connect(m_backward, SIGNAL(clicked()), this, SLOT(slotBackwardClicked()));
×
269
    connect(m_dimmerControlCb, SIGNAL(clicked()), this, SLOT(slotDimmerControlClicked()));
×
270

271
    // Test slots
272
    connect(m_testButton, SIGNAL(clicked(bool)),
×
273
            this, SLOT(slotTestClicked()));
274

275
    m_preview->setScene(m_scene);
×
276
    if (createPreviewItems() == true)
×
277
        m_previewTimer->start(MasterTimer::tick());
×
278
}
×
279

280
void RGBMatrixEditor::updateSpeedDials()
×
281
{
282
    if (m_speedDialButton->isChecked() == false)
×
283
        return;
×
284

285
    if (m_speedDials != NULL)
×
286
        return;
×
287

288
    m_speedDials = new SpeedDialWidget(this);
×
289
    m_speedDials->setAttribute(Qt::WA_DeleteOnClose);
×
290
    m_speedDials->setWindowTitle(m_matrix->name());
×
291
    m_speedDials->show();
×
292
    m_speedDials->setFadeInSpeed(m_matrix->fadeInSpeed());
×
293
    m_speedDials->setFadeOutSpeed(m_matrix->fadeOutSpeed());
×
294
    if ((int)m_matrix->duration() < 0)
×
295
        m_speedDials->setDuration(m_matrix->duration());
×
296
    else
297
        m_speedDials->setDuration(m_matrix->duration() - m_matrix->fadeInSpeed());
×
298
    connect(m_speedDials, SIGNAL(fadeInChanged(int)), this, SLOT(slotFadeInChanged(int)));
×
299
    connect(m_speedDials, SIGNAL(fadeOutChanged(int)), this, SLOT(slotFadeOutChanged(int)));
×
300
    connect(m_speedDials, SIGNAL(holdChanged(int)), this, SLOT(slotHoldChanged(int)));
×
301
    connect(m_speedDials, SIGNAL(holdTapped()), this, SLOT(slotDurationTapped()));
×
302
    connect(m_speedDials, SIGNAL(destroyed(QObject*)), this, SLOT(slotDialDestroyed(QObject*)));
×
303
}
304

305
void RGBMatrixEditor::fillPatternCombo()
×
306
{
307
    m_patternCombo->addItems(RGBAlgorithm::algorithms(m_doc));
×
308
    if (m_matrix->algorithm() != NULL)
×
309
    {
310
        int index = m_patternCombo->findText(m_matrix->algorithm()->name());
×
311
        if (index >= 0)
×
312
            m_patternCombo->setCurrentIndex(index);
×
313
    }
314
}
×
315

316
void RGBMatrixEditor::fillFixtureGroupCombo()
×
317
{
318
    m_fixtureGroupCombo->clear();
×
319
    m_fixtureGroupCombo->addItem(tr("None"));
×
320

321
    QListIterator <FixtureGroup*> it(m_doc->fixtureGroups());
×
322
    while (it.hasNext() == true)
×
323
    {
324
        FixtureGroup* grp(it.next());
×
325
        Q_ASSERT(grp != NULL);
×
326
        m_fixtureGroupCombo->addItem(grp->name(), grp->id());
×
327
        if (m_matrix->fixtureGroup() == grp->id())
×
328
            m_fixtureGroupCombo->setCurrentIndex(m_fixtureGroupCombo->count() - 1);
×
329
    }
330
}
×
331

332
void RGBMatrixEditor::fillAnimationCombo()
×
333
{
334
    m_animationCombo->addItems(RGBText::animationStyles());
×
335
}
×
336

337
void RGBMatrixEditor::fillImageAnimationCombo()
×
338
{
339
    m_imageAnimationCombo->addItems(RGBImage::animationStyles());
×
340
}
×
341

342
void RGBMatrixEditor::updateExtraOptions()
×
343
{
344
    resetProperties(m_propertiesLayout->layout());
×
345
    m_propertiesGroup->hide();
×
346

347
    if (m_matrix->algorithm() == NULL ||
×
348
        m_matrix->algorithm()->type() == RGBAlgorithm::Script ||
×
349
        m_matrix->algorithm()->type() == RGBAlgorithm::Audio)
×
350
    {
351
        m_textGroup->hide();
×
352
        m_imageGroup->hide();
×
353
        m_offsetGroup->hide();
×
354

355
        if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Script)
×
356
        {
357
            RGBScript *script = static_cast<RGBScript*> (m_matrix->algorithm());
×
358
            displayProperties(script);
×
359
        }
360
    }
361
    else if (m_matrix->algorithm()->type() == RGBAlgorithm::Plain)
×
362
    {
363
        m_textGroup->hide();
×
364
        m_imageGroup->hide();
×
365
        m_offsetGroup->hide();
×
366
    }
367
    else if (m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
368
    {
369
        m_textGroup->hide();
×
370
        m_imageGroup->show();
×
371
        m_offsetGroup->show();
×
372

373
        RGBImage *image = static_cast<RGBImage*> (m_matrix->algorithm());
×
374
        Q_ASSERT(image != NULL);
×
375
        m_imageEdit->setText(image->filename());
×
376

377
        int index = m_imageAnimationCombo->findText(RGBImage::animationStyleToString(image->animationStyle()));
×
378
        if (index != -1)
×
379
            m_imageAnimationCombo->setCurrentIndex(index);
×
380

381
        m_xOffsetSpin->setValue(image->xOffset());
×
382
        m_yOffsetSpin->setValue(image->yOffset());
×
383

384
    }
385
    else if (m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
386
    {
387
        m_textGroup->show();
×
388
        m_offsetGroup->show();
×
389
        m_imageGroup->hide();
×
390

391
        RGBText *text = static_cast<RGBText*> (m_matrix->algorithm());
×
392
        Q_ASSERT(text != NULL);
×
393
        m_textEdit->setText(text->text());
×
394

395
        int index = m_animationCombo->findText(RGBText::animationStyleToString(text->animationStyle()));
×
396
        if (index != -1)
×
397
            m_animationCombo->setCurrentIndex(index);
×
398

399
        m_xOffsetSpin->setValue(text->xOffset());
×
400
        m_yOffsetSpin->setValue(text->yOffset());
×
401
    }
402

403
    updateColorOptions();
×
404
}
×
405

406
void RGBMatrixEditor::updateColorOptions()
×
407
{
408
    if (m_matrix->algorithm() != NULL)
×
409
    {
410
        int accColors = m_matrix->algorithm()->acceptColors();
×
411

412
        m_mtxColor1Button->setVisible(accColors == 0 ? false : true);
×
413
        m_mtxColor2Button->setVisible(accColors > 1 ? true : false);
×
414
        m_resetMtxColor2Button->setVisible(accColors > 1 ? true : false);
×
415
        m_mtxColor3Button->setVisible(accColors > 2 ? true : false);
×
416
        m_resetMtxColor3Button->setVisible(accColors > 2 ? true : false);
×
417
        m_mtxColor4Button->setVisible(accColors > 3 ? true : false);
×
418
        m_resetMtxColor4Button->setVisible(accColors > 3 ? true : false);
×
419
        m_mtxColor5Button->setVisible(accColors > 4 ? true : false);
×
420
        m_resetMtxColor5Button->setVisible(accColors > 4 ? true : false);
×
421

422
        m_blendModeLabel->setVisible(accColors == 0 ? false : true);
×
423
        m_blendModeCombo->setVisible(accColors == 0 ? false : true);
×
424
    }
425
}
×
426

427
void RGBMatrixEditor::updateColors()
×
428
{
429
    if (m_matrix->algorithm() != NULL)
×
430
    {
431
        int accColors = m_matrix->algorithm()->acceptColors();
×
432
        if (accColors > 0)
×
433
        {
434
            if (m_matrix->blendMode() == Universe::MaskBlend)
×
435
            {
436
                m_matrix->setColor(0, Qt::white);
×
437
                // Overwrite more colors only if applied.
438
                if (accColors <= 2)
×
439
                    m_matrix->setColor(1, QColor());
×
440
                if (accColors <= 3)
×
441
                    m_matrix->setColor(2, QColor());
×
442
                if (accColors <= 4)
×
443
                    m_matrix->setColor(3, QColor());
×
444
                if (accColors <= 5)
×
445
                    m_matrix->setColor(4, QColor());
×
446

447
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
448
                        m_matrix->algorithm());
×
449

450
                QPixmap pm(50, 26);
×
451
                pm.fill(Qt::white);
×
452
                m_mtxColor1Button->setIcon(QIcon(pm));
×
453

454
                pm.fill(Qt::transparent);
×
455
                m_mtxColor2Button->setIcon(QIcon(pm));
×
456
                m_mtxColor3Button->setIcon(QIcon(pm));
×
457
                m_mtxColor4Button->setIcon(QIcon(pm));
×
458
                m_mtxColor5Button->setIcon(QIcon(pm));
×
459
            }
×
460
            else if (m_controlModeCombo->currentIndex() != RGBMatrix::ControlModeRgb)
×
461
            {
462
                // Convert color 1 to grayscale for single color modes
463
                uchar gray = qGray(m_matrix->getColor(0).rgb());
×
464
                m_matrix->setColor(0, QColor(gray, gray, gray));
×
465
                QPixmap pm(50, 26);
×
466
                pm.fill(QColor(gray, gray, gray));
×
467
                m_mtxColor1Button->setIcon(QIcon(pm));
×
468

469
                // Convert color 2 and following to grayscale for single color modes
470
                if (accColors < 2)
×
471
                    m_matrix->setColor(1, QColor());
×
472
                if (m_matrix->getColor(1) == QColor())
×
473
                {
474
                    pm.fill(Qt::transparent);
×
475
                }
476
                else
477
                {
478
                    gray = qGray(m_matrix->getColor(1).rgb());
×
479
                    m_matrix->setColor(1, QColor(gray, gray, gray));
×
480
                    pm.fill(QColor(gray, gray, gray));
×
481
                }
482
                m_mtxColor2Button->setIcon(QIcon(pm));
×
483

484
                if (accColors < 3)
×
485
                    m_matrix->setColor(2, QColor());
×
486
                if (m_matrix->getColor(2) == QColor())
×
487
                {
488
                    pm.fill(Qt::transparent);
×
489
                }
490
                else
491
                {
492
                    gray = qGray(m_matrix->getColor(2).rgb());
×
493
                    m_matrix->setColor(2, QColor(gray, gray, gray));
×
494
                    pm.fill(QColor(gray, gray, gray));
×
495
                }
496
                m_mtxColor3Button->setIcon(QIcon(pm));
×
497

498
                if (accColors < 4)
×
499
                    m_matrix->setColor(3, QColor());
×
500
                if (m_matrix->getColor(3) == QColor())
×
501
                {
502
                    pm.fill(Qt::transparent);
×
503
                }
504
                else
505
                {
506
                    gray = qGray(m_matrix->getColor(3).rgb());
×
507
                    m_matrix->setColor(3, QColor(gray, gray, gray));
×
508
                    pm.fill(QColor(gray, gray, gray));
×
509
                }
510
                m_mtxColor4Button->setIcon(QIcon(pm));
×
511

512
                if (accColors < 5)
×
513
                    m_matrix->setColor(4, QColor());
×
514
                if (m_matrix->getColor(4) == QColor())
×
515
                {
516
                    pm.fill(Qt::transparent);
×
517
                }
518
                else
519
                {
520
                    gray = qGray(m_matrix->getColor(4).rgb());
×
521
                    m_matrix->setColor(4, QColor(gray, gray, gray));
×
522
                    pm.fill(QColor(gray, gray, gray));
×
523
                }
524
                m_mtxColor5Button->setIcon(QIcon(pm));
×
525

526
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
527
                        m_matrix->algorithm());
×
528
            }
×
529
            else 
530
            {
531
                QPixmap pm(50, 26);
×
532
                pm.fill(m_matrix->getColor(0));
×
533
                m_mtxColor1Button->setIcon(QIcon(pm));
×
534

535
                // Preserve the colors (do not set them to QColor().
536
                // RGBMatrixStep::calculateColorDelta will ensure correct color application
537
                if (m_matrix->getColor(1) == QColor())
×
538
                    pm.fill(Qt::transparent);
×
539
                else
540
                    pm.fill(m_matrix->getColor(1));
×
541
                m_mtxColor2Button->setIcon(QIcon(pm));
×
542

543
                if (m_matrix->getColor(2) == QColor())
×
544
                    pm.fill(Qt::transparent);
×
545
                else
546
                    pm.fill(m_matrix->getColor(2));
×
547
                m_mtxColor3Button->setIcon(QIcon(pm));
×
548

549
                if (m_matrix->getColor(3) == QColor())
×
550
                    pm.fill(Qt::transparent);
×
551
                else
552
                    pm.fill(m_matrix->getColor(3));
×
553
                m_mtxColor4Button->setIcon(QIcon(pm));
×
554

555
                if (m_matrix->getColor(4) == QColor())
×
556
                    pm.fill(Qt::transparent);
×
557
                else
558
                    pm.fill(m_matrix->getColor(4));
×
559
                m_mtxColor5Button->setIcon(QIcon(pm));
×
560

561
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
562
                        m_matrix->algorithm());
×
563
            }
×
564
        }
565
    }
566
}
×
567

568
/**
569
 * Helper function. Deletes all child widgets of the given layout @a item.
570
 */
571
void RGBMatrixEditor::resetProperties(QLayoutItem *item)
×
572
{
573
    if (item->layout()) 
×
574
    {
575
        // Process all child items recursively.
576
        for (int i = item->layout()->count() - 1; i >= 0; i--)
×
577
            resetProperties(item->layout()->itemAt(i));
×
578
    }
579
    delete item->widget();
×
580
}
×
581

582
void RGBMatrixEditor::displayProperties(RGBScript *script)
×
583
{
584
    if (script == NULL)
×
585
        return;
×
586

587
    int gridRowIdx = 0;
×
588

589
    QList<RGBScriptProperty> properties = script->properties();
×
590
    if (properties.count() > 0)
×
591
        m_propertiesGroup->show();
×
592

593
    foreach (RGBScriptProperty prop, properties)
×
594
    {
595
        switch(prop.m_type)
×
596
        {
597
            case RGBScriptProperty::List:
×
598
            {
599
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
600
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
601
                QComboBox *propCombo = new QComboBox(this);
×
602
                propCombo->addItems(prop.m_listValues);
×
603
                propCombo->setProperty("pName", prop.m_name);
×
604
                connect(propCombo, SIGNAL(currentIndexChanged(int)),
×
605
                        this, SLOT(slotPropertyComboChanged(int)));
606
                m_propertiesLayout->addWidget(propCombo, gridRowIdx, 1);
×
607
                if (m_matrix != NULL)
×
608
                {
609
                    QString pValue = m_matrix->property(prop.m_name);
×
610
                    if (!pValue.isEmpty())
×
611
                    {
612
                        propCombo->setCurrentText(pValue);
×
613
                    }
614
                    else
615
                    {
616
                        pValue = script->property(prop.m_name);
×
617
                        if (!pValue.isEmpty())
×
618
                            propCombo->setCurrentText(pValue);
×
619
                    }
620
                }
×
621
                gridRowIdx++;
×
622
            }
623
            break;
×
624
            case RGBScriptProperty::Range:
×
625
            {
626
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
627
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
628
                QSpinBox *propSpin = new QSpinBox(this);
×
629
                propSpin->setRange(prop.m_rangeMinValue, prop.m_rangeMaxValue);
×
630
                propSpin->setProperty("pName", prop.m_name);
×
631
                connect(propSpin, SIGNAL(valueChanged(int)),
×
632
                        this, SLOT(slotPropertySpinChanged(int)));
633
                m_propertiesLayout->addWidget(propSpin, gridRowIdx, 1);
×
634
                if (m_matrix != NULL)
×
635
                {
636
                    QString pValue = m_matrix->property(prop.m_name);
×
637
                    if (!pValue.isEmpty())
×
638
                        propSpin->setValue(pValue.toInt());
×
639
                    else
640
                    {
641
                        pValue = script->property(prop.m_name);
×
642
                        if (!pValue.isEmpty())
×
643
                            propSpin->setValue(pValue.toInt());
×
644
                    }
645
                }
×
646
                gridRowIdx++;
×
647
            }
648
            break;
×
649
            case RGBScriptProperty::Float:
×
650
            {
651
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
652
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
653
                QDoubleSpinBox *propSpin = new QDoubleSpinBox(this);
×
654
                propSpin->setDecimals(3);
×
655
                propSpin->setRange(-1000000, 1000000);
×
656
                propSpin->setProperty("pName", prop.m_name);
×
657
                connect(propSpin, SIGNAL(valueChanged(double)),
×
658
                        this, SLOT(slotPropertyDoubleSpinChanged(double)));
659
                m_propertiesLayout->addWidget(propSpin, gridRowIdx, 1);
×
660
                if (m_matrix != NULL)
×
661
                {
662
                    QString pValue = m_matrix->property(prop.m_name);
×
663
                    if (!pValue.isEmpty())
×
664
                        propSpin->setValue(pValue.toDouble());
×
665
                    else
666
                    {
667
                        pValue = script->property(prop.m_name);
×
668
                        if (!pValue.isEmpty())
×
669
                            propSpin->setValue(pValue.toDouble());
×
670
                    }
671
                }
×
672
                gridRowIdx++;
×
673
            }
674
            break;
×
675
            case RGBScriptProperty::String:
×
676
            {
677
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
678
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
679
                QLineEdit *propEdit = new QLineEdit(this);
×
NEW
680
                propEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
×
681
                propEdit->setProperty("pName", prop.m_name);
×
682
                connect(propEdit, SIGNAL(textEdited(QString)),
×
683
                        this, SLOT(slotPropertyEditChanged(QString)));
684
                m_propertiesLayout->addWidget(propEdit, gridRowIdx, 1);
×
685
                if (m_matrix != NULL)
×
686
                {
687
                    QString pValue = m_matrix->property(prop.m_name);
×
688
                    if (!pValue.isEmpty())
×
689
                        propEdit->setText(pValue);
×
690
                    else
691
                    {
692
                        pValue = script->property(prop.m_name);
×
693
                        if (!pValue.isEmpty())
×
694
                            propEdit->setText(pValue);
×
695
                    }
696
                }
×
697
                gridRowIdx++;
×
698
            }
699
            break;
×
700
            default:
×
701
                qWarning() << "Type" << prop.m_type << "not handled yet";
×
702
            break;
×
703
        }
704
    }
×
705
}
×
706

707
bool RGBMatrixEditor::createPreviewItems()
×
708
{
709
    qDeleteAll(m_previewHash);
×
710
    m_previewHash.clear();
×
711
    m_scene->clear();
×
712

713
    FixtureGroup* grp = m_doc->fixtureGroup(m_matrix->fixtureGroup());
×
714
    if (grp == NULL)
×
715
    {
716
        QGraphicsTextItem* text = new QGraphicsTextItem(tr("No fixture group to control"));
×
717
        text->setDefaultTextColor(Qt::white);
×
718
        m_scene->addItem(text);
×
719
        return false;
×
720
    }
721

722
    m_previewHandler->initializeDirection(m_matrix->direction(), m_matrix->getColor(0),
×
723
                                      m_matrix->getColor(1), m_matrix->stepsCount(),
×
724
                                      m_matrix->algorithm());
×
725

726
    m_matrix->previewMap(m_previewHandler->currentStepIndex(), m_previewHandler);
×
727

728
    if (m_previewHandler->m_map.isEmpty())
×
729
        return false;
×
730

731
    for (int x = 0; x < grp->size().width(); x++)
×
732
    {
733
        for (int y = 0; y < grp->size().height(); y++)
×
734
        {
735
            QLCPoint pt(x, y);
×
736

737
            if (grp->headsMap().contains(pt) == true)
×
738
            {
739
                RGBItem *item;
740
                if (m_shapeButton->isChecked() == false)
×
741
                {
742
                    QGraphicsEllipseItem* circleItem = new QGraphicsEllipseItem();
×
743
                    circleItem->setRect(
×
744
                            x * RECT_SIZE + RECT_PADDING + ITEM_PADDING,
×
745
                            y * RECT_SIZE + RECT_PADDING + ITEM_PADDING,
×
746
                            ITEM_SIZE - (2 * ITEM_PADDING),
747
                            ITEM_SIZE - (2 * ITEM_PADDING));
748
                    item = new RGBItem(circleItem);
×
749
                }
750
                else
751
                {
752
                    QGraphicsRectItem *rectItem = new QGraphicsRectItem();
×
753
                    rectItem->setRect(
×
754
                            x * RECT_SIZE + RECT_PADDING + ITEM_PADDING,
×
755
                            y * RECT_SIZE + RECT_PADDING + ITEM_PADDING,
×
756
                            ITEM_SIZE - (2 * ITEM_PADDING),
757
                            ITEM_SIZE - (2 * ITEM_PADDING));
758
                    item = new RGBItem(rectItem);
×
759
                }
760

761
                item->setColor(m_previewHandler->m_map[y][x]);
×
762
                item->draw(0, 0);
×
763
                m_scene->addItem(item->graphicsItem());
×
764
                m_previewHash[pt] = item;
×
765
            }
766
        }
767
    }
768
    return true;
×
769
}
770

771
void RGBMatrixEditor::slotPreviewTimeout()
×
772
{
773
    if (m_matrix->duration() <= 0)
×
774
        return;
×
775

776
    m_previewIterator += MasterTimer::tick();
×
777
    uint elapsed = 0;
×
778
    while (m_previewIterator >= MAX(m_matrix->duration(), MasterTimer::tick()))
×
779
    {
780
        m_previewHandler->checkNextStep(m_matrix->runOrder(), m_matrix->getColor(0),
×
781
                                        m_matrix->getColor(1), m_matrix->stepsCount());
×
782

783
        m_matrix->previewMap(m_previewHandler->currentStepIndex(), m_previewHandler);
×
784

785
        m_previewIterator -= MAX(m_matrix->duration(), MasterTimer::tick());
×
786
        elapsed += MAX(m_matrix->duration(), MasterTimer::tick());
×
787
    }
788
    for (int y = 0; y < m_previewHandler->m_map.size(); y++)
×
789
    {
790
        for (int x = 0; x < m_previewHandler->m_map[y].size(); x++)
×
791
        {
792
            QLCPoint pt(x, y);
×
793
            RGBItem* shape = m_previewHash.value(pt, NULL);
×
794
            if (shape)
×
795
            {
796
                if (shape->color() != QColor(m_previewHandler->m_map[y][x]).rgb())
×
797
                    shape->setColor(m_previewHandler->m_map[y][x]);
×
798

799
                if (shape->color() == QColor(Qt::black).rgb())
×
800
                    shape->draw(elapsed, m_matrix->fadeOutSpeed());
×
801
                else
802
                    shape->draw(elapsed, m_matrix->fadeInSpeed());
×
803
            }
804
        }
805
    }
806
}
807

808
void RGBMatrixEditor::slotNameEdited(const QString& text)
×
809
{
810
    m_matrix->setName(text);
×
811
    if (m_speedDials != NULL)
×
812
        m_speedDials->setWindowTitle(text);
×
813
}
×
814

815
void RGBMatrixEditor::slotSpeedDialToggle(bool state)
×
816
{
817
    if (state == true)
×
818
        updateSpeedDials();
×
819
    else
820
    {
821
        if (m_speedDials != NULL)
×
822
            m_speedDials->deleteLater();
×
823
        m_speedDials = NULL;
×
824
    }
825
}
×
826

827
void RGBMatrixEditor::slotDialDestroyed(QObject *)
×
828
{
829
    m_speedDialButton->setChecked(false);
×
830
}
×
831

832
void RGBMatrixEditor::slotPatternActivated(int patternIndex)
×
833
{
834
    QString algoName = m_patternCombo->itemText(patternIndex);
×
835
    RGBAlgorithm *algo = RGBAlgorithm::algorithm(m_doc, algoName);
×
836
    m_matrix->setAlgorithm(algo);
×
837
    if (algo != NULL) {
×
838
        updateColors();
×
839
#if (5 != RGBAlgorithmColorDisplayCount)
840
#error "Further colors need to be displayed."
841
#endif
842
        QVector<QColor> colors = {
843
            m_matrix->getColor(0),
×
844
            m_matrix->getColor(1),
×
845
            m_matrix->getColor(2),
×
846
            m_matrix->getColor(3),
×
847
            m_matrix->getColor(4)
×
848
        };
×
849
        algo->setColors(colors);
×
850
        m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
851
                                              m_matrix->algorithm());
×
852
    }
×
853
    updateExtraOptions();
×
854

855
    slotRestartTest();
×
856
}
×
857

858
void RGBMatrixEditor::slotFixtureGroupActivated(int index)
×
859
{
860
    QVariant var = m_fixtureGroupCombo->itemData(index);
×
861
    if (var.isValid() == true)
×
862
    {
863
        m_matrix->setFixtureGroup(var.toUInt());
×
864
        slotRestartTest();
×
865
    }
866
    else
867
    {
868
        m_matrix->setFixtureGroup(FixtureGroup::invalidId());
×
869
        m_previewTimer->stop();
×
870
        m_scene->clear();
×
871
    }
872
}
×
873

874
void RGBMatrixEditor::slotBlendModeChanged(int index)
×
875
{
876
    m_matrix->setBlendMode(Universe::BlendMode(index));
×
877

878
    if (index == Universe::MaskBlend)
×
879
    {
880
        m_mtxColor1Button->setEnabled(false);
×
881
    }
882
    else
883
    {
884
        m_mtxColor1Button->setEnabled(true);
×
885
    }
886
    updateExtraOptions();
×
887
    updateColors();
×
888
    slotRestartTest();
×
889
}
×
890

891
void RGBMatrixEditor::slotControlModeChanged(int index)
×
892
{
893
    RGBMatrix::ControlMode mode = RGBMatrix::ControlMode(index);
×
894
    m_matrix->setControlMode(mode);
×
895
    updateColors();
×
896
    slotRestartTest();
×
897
}
×
898

899
void RGBMatrixEditor::slotMtxColor1ButtonClicked()
×
900
{
901
    QColor col = QColorDialog::getColor(m_matrix->getColor(0));
×
902
    if (col.isValid() == true)
×
903
    {
904
        m_matrix->setColor(0, col);
×
905
        updateColors();
×
906
        slotRestartTest();
×
907
    }
908
}
×
909

910
void RGBMatrixEditor::slotMtxColor2ButtonClicked()
×
911
{
912
    QColor col = QColorDialog::getColor(m_matrix->getColor(1));
×
913
    if (col.isValid() == true)
×
914
    {
915
        m_matrix->setColor(1, col);
×
916
        updateColors();
×
917
        slotRestartTest();
×
918
    }
919
}
×
920

921
void RGBMatrixEditor::slotResetMtxColor2ButtonClicked()
×
922
{
923
    m_matrix->setColor(1, QColor());
×
924
    updateColors();
×
925
    slotRestartTest();
×
926
}
×
927

928
void RGBMatrixEditor::slotMtxColor3ButtonClicked()
×
929
{
930
    QColor col = QColorDialog::getColor(m_matrix->getColor(2));
×
931
    if (col.isValid() == true)
×
932
    {
933
        m_matrix->setColor(2, col);
×
934
        updateColors();
×
935
        slotRestartTest();
×
936
    }
937
}
×
938

939
void RGBMatrixEditor::slotResetMtxColor3ButtonClicked()
×
940
{
941
    m_matrix->setColor(2, QColor());
×
942
    updateColors();
×
943
    slotRestartTest();
×
944
}
×
945

946
void RGBMatrixEditor::slotMtxColor4ButtonClicked()
×
947
{
948
    QColor col = QColorDialog::getColor(m_matrix->getColor(3));
×
949
    if (col.isValid() == true)
×
950
    {
951
        m_matrix->setColor(3, col);
×
952
        updateColors();
×
953
        slotRestartTest();
×
954
    }
955
}
×
956

957
void RGBMatrixEditor::slotResetMtxColor4ButtonClicked()
×
958
{
959
    m_matrix->setColor(3, QColor());
×
960
    updateColors();
×
961
    slotRestartTest();
×
962
}
×
963

964
void RGBMatrixEditor::slotMtxColor5ButtonClicked()
×
965
{
966
    QColor col = QColorDialog::getColor(m_matrix->getColor(4));
×
967
    if (col.isValid() == true)
×
968
    {
969
        m_matrix->setColor(4, col);
×
970
        updateColors();
×
971
        slotRestartTest();
×
972
    }
973
}
×
974

975
void RGBMatrixEditor::slotResetMtxColor5ButtonClicked()
×
976
{
977
    m_matrix->setColor(4, QColor());
×
978
    updateColors();
×
979
    slotRestartTest();
×
980
}
×
981

982
void RGBMatrixEditor::slotTextEdited(const QString& text)
×
983
{
984
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
985
    {
986
        RGBText *algo = static_cast<RGBText*> (m_matrix->algorithm());
×
987
        Q_ASSERT(algo != NULL);
×
988
        {
989
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
990
            algo->setText(text);
×
991
        }
×
992
        slotRestartTest();
×
993
    }
994
}
×
995

996
void RGBMatrixEditor::slotFontButtonClicked()
×
997
{
998
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
999
    {
1000
        RGBText *algo = static_cast<RGBText*> (m_matrix->algorithm());
×
1001
        Q_ASSERT(algo != NULL);
×
1002

1003
        bool ok = false;
×
1004
        QFont font = QFontDialog::getFont(&ok, algo->font(), this);
×
1005
        if (ok == true)
×
1006
        {
1007
            {
1008
                QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1009
                algo->setFont(font);
×
1010
            }
×
1011
            slotRestartTest();
×
1012
        }
1013
    }
×
1014
}
×
1015

1016
void RGBMatrixEditor::slotAnimationActivated(int index)
×
1017
{
1018
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
1019
    {
1020
        RGBText *algo = static_cast<RGBText*> (m_matrix->algorithm());
×
1021
        Q_ASSERT(algo != NULL);
×
1022
        {
1023
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1024
            QString text = m_animationCombo->itemText(index);
×
1025
            algo->setAnimationStyle(RGBText::stringToAnimationStyle(text));
×
1026
        }
×
1027
        slotRestartTest();
×
1028
    }
1029
}
×
1030

1031
void RGBMatrixEditor::slotImageEdited()
×
1032
{
1033
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1034
    {
1035
        RGBImage *algo = static_cast<RGBImage*> (m_matrix->algorithm());
×
1036
        Q_ASSERT(algo != NULL);
×
1037
        {
1038
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1039
            algo->setFilename(m_imageEdit->text());
×
1040
        }
×
1041
        slotRestartTest();
×
1042
    }
1043
}
×
1044

1045
void RGBMatrixEditor::slotImageButtonClicked()
×
1046
{
1047
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1048
    {
1049
        RGBImage *algo = static_cast<RGBImage*> (m_matrix->algorithm());
×
1050
        Q_ASSERT(algo != NULL);
×
1051

1052
        QString path = algo->filename();
×
1053
        path = QFileDialog::getOpenFileName(this,
×
1054
                                            tr("Select image"),
×
1055
                                            path,
1056
                                            QString("%1 (*.png *.bmp *.jpg *.jpeg *.gif)").arg(tr("Images")));
×
1057
        if (path.isEmpty() == false)
×
1058
        {
1059
            {
1060
                QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1061
                algo->setFilename(path);
×
1062
            }
×
1063
            m_imageEdit->setText(path);
×
1064
            slotRestartTest();
×
1065
        }
1066
    }
×
1067
}
×
1068

1069
void RGBMatrixEditor::slotImageAnimationActivated(int index)
×
1070
{
1071
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1072
    {
1073
        RGBImage *algo = static_cast<RGBImage*> (m_matrix->algorithm());
×
1074
        Q_ASSERT(algo != NULL);
×
1075
        {
1076
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1077
            QString text = m_imageAnimationCombo->itemText(index);
×
1078
            algo->setAnimationStyle(RGBImage::stringToAnimationStyle(text));
×
1079
        }
×
1080
        slotRestartTest();
×
1081
    }
1082
}
×
1083

1084
void RGBMatrixEditor::slotOffsetSpinChanged()
×
1085
{
1086
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
1087
    {
1088
        RGBText *algo = static_cast<RGBText*> (m_matrix->algorithm());
×
1089
        Q_ASSERT(algo != NULL);
×
1090
        {
1091
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1092
            algo->setXOffset(m_xOffsetSpin->value());
×
1093
            algo->setYOffset(m_yOffsetSpin->value());
×
1094
        }
×
1095
        slotRestartTest();
×
1096
    }
1097

1098
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1099
    {
1100
        RGBImage *algo = static_cast<RGBImage*> (m_matrix->algorithm());
×
1101
        Q_ASSERT(algo != NULL);
×
1102
        {
1103
            QMutexLocker algorithmLocker(&m_matrix->algorithmMutex());
×
1104
            algo->setXOffset(m_xOffsetSpin->value());
×
1105
            algo->setYOffset(m_yOffsetSpin->value());
×
1106
        }
×
1107
        slotRestartTest();
×
1108
    }
1109
}
×
1110

1111
void RGBMatrixEditor::slotLoopClicked()
×
1112
{
1113
    m_matrix->setRunOrder(Function::Loop);
×
1114
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1115
            m_matrix->algorithm());
×
1116
    slotRestartTest();
×
1117
}
×
1118

1119
void RGBMatrixEditor::slotPingPongClicked()
×
1120
{
1121
    m_matrix->setRunOrder(Function::PingPong);
×
1122
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1123
            m_matrix->algorithm());
×
1124
    slotRestartTest();
×
1125
}
×
1126

1127
void RGBMatrixEditor::slotSingleShotClicked()
×
1128
{
1129
    m_matrix->setRunOrder(Function::SingleShot);
×
1130
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1131
            m_matrix->algorithm());
×
1132
    slotRestartTest();
×
1133
}
×
1134

1135
void RGBMatrixEditor::slotForwardClicked()
×
1136
{
1137
    m_matrix->setDirection(Function::Forward);
×
1138
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1139
            m_matrix->algorithm());
×
1140
    slotRestartTest();
×
1141
}
×
1142

1143
void RGBMatrixEditor::slotBackwardClicked()
×
1144
{
1145
    m_matrix->setDirection(Function::Backward);
×
1146
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1147
            m_matrix->algorithm());
×
1148
    slotRestartTest();
×
1149
}
×
1150

1151
void RGBMatrixEditor::slotDimmerControlClicked()
×
1152
{
1153
    m_matrix->setDimmerControl(m_dimmerControlCb->isChecked());
×
1154
    if (m_dimmerControlCb->isChecked() == false)
×
1155
        m_dimmerControlCb->setEnabled(false);
×
1156
}
×
1157

1158
void RGBMatrixEditor::slotFadeInChanged(int ms)
×
1159
{
1160
    m_matrix->setFadeInSpeed(ms);
×
1161
    uint duration = Function::speedAdd(ms, m_speedDials->duration());
×
1162
    m_matrix->setDuration(duration);
×
1163
}
×
1164

1165
void RGBMatrixEditor::slotFadeOutChanged(int ms)
×
1166
{
1167
    m_matrix->setFadeOutSpeed(ms);
×
1168
}
×
1169

1170
void RGBMatrixEditor::slotHoldChanged(int ms)
×
1171
{
1172
    uint duration = Function::speedAdd(m_matrix->fadeInSpeed(), ms);
×
1173
    m_matrix->setDuration(duration);
×
1174
}
×
1175

1176
void RGBMatrixEditor::slotDurationTapped()
×
1177
{
1178
    m_matrix->tap();
×
1179
}
×
1180

1181
void RGBMatrixEditor::slotTestClicked()
×
1182
{
1183
    if (m_testButton->isChecked() == true)
×
1184
        m_matrix->start(m_doc->masterTimer(), functionParent());
×
1185
    else
1186
        m_matrix->stopAndWait();
×
1187
}
×
1188

1189
void RGBMatrixEditor::slotRestartTest()
×
1190
{
1191
    m_previewTimer->stop();
×
1192

1193
    if (m_testButton->isChecked() == true)
×
1194
    {
1195
        // Toggle off, toggle on. Duh.
1196
        m_testButton->click();
×
1197
        m_testButton->click();
×
1198
    }
1199

1200
    if (createPreviewItems() == true)
×
1201
        m_previewTimer->start(MasterTimer::tick());
×
1202

1203
}
×
1204

1205
void RGBMatrixEditor::slotModeChanged(Doc::Mode mode)
×
1206
{
1207
    if (mode == Doc::Operate)
×
1208
    {
1209
        if (m_testButton->isChecked() == true)
×
1210
            m_matrix->stopAndWait();
×
1211
        m_testButton->setChecked(false);
×
1212
        m_testButton->setEnabled(false);
×
1213
    }
1214
    else
1215
    {
1216
        m_testButton->setEnabled(true);
×
1217
    }
1218
}
×
1219

1220
void RGBMatrixEditor::slotFixtureGroupAdded()
×
1221
{
1222
    fillFixtureGroupCombo();
×
1223
}
×
1224

1225
void RGBMatrixEditor::slotFixtureGroupRemoved()
×
1226
{
1227
    fillFixtureGroupCombo();
×
1228
    slotFixtureGroupActivated(m_fixtureGroupCombo->currentIndex());
×
1229
}
×
1230

1231
void RGBMatrixEditor::slotFixtureGroupChanged(quint32 id)
×
1232
{
1233
    if (id == m_matrix->fixtureGroup())
×
1234
    {
1235
        // Update the whole chain -> maybe the fixture layout has changed
1236
        fillFixtureGroupCombo();
×
1237
        slotFixtureGroupActivated(m_fixtureGroupCombo->currentIndex());
×
1238
    }
1239
    else
1240
    {
1241
        // Just change the name of the group, nothing else is interesting at this point
1242
        int index = m_fixtureGroupCombo->findData(id);
×
1243
        if (index != -1)
×
1244
        {
1245
            FixtureGroup* grp = m_doc->fixtureGroup(id);
×
1246
            m_fixtureGroupCombo->setItemText(index, grp->name());
×
1247
        }
1248
    }
1249
}
×
1250

1251
void RGBMatrixEditor::slotSaveToSequenceClicked()
×
1252
{
1253
    if (m_matrix == NULL || m_matrix->fixtureGroup() == FixtureGroup::invalidId())
×
1254
        return;
×
1255

1256
    FixtureGroup* grp = m_doc->fixtureGroup(m_matrix->fixtureGroup());
×
1257
    if (grp != NULL && m_matrix->algorithm() != NULL)
×
1258
    {
1259
        bool testRunning = false;
×
1260

1261
        if (m_testButton->isChecked() == true)
×
1262
        {
1263
            m_testButton->click();
×
1264
            testRunning = true;
×
1265
        }
1266
        else
1267
            m_previewTimer->stop();
×
1268

1269
        Scene *grpScene = new Scene(m_doc);
×
1270
        grpScene->setName(grp->name());
×
1271
        grpScene->setVisible(false);
×
1272

1273
        QList<GroupHead> headList = grp->headList();
×
1274
        foreach (GroupHead head, headList)
×
1275
        {
1276
            Fixture *fxi = m_doc->fixture(head.fxi);
×
1277
            if (fxi == NULL)
×
1278
                continue;
×
1279

1280
            if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeRgb)
×
1281
            {
1282

1283
                    QVector <quint32> rgb = fxi->rgbChannels(head.head);
×
1284

1285
                    // in case of CMY, dump those channels
1286
                    if (rgb.count() == 0)
×
1287
                        rgb = fxi->cmyChannels(head.head);
×
1288

1289
                    if (rgb.count() == 3)
×
1290
                    {
1291
                        grpScene->setValue(head.fxi, rgb.at(0), 0);
×
1292
                        grpScene->setValue(head.fxi, rgb.at(1), 0);
×
1293
                        grpScene->setValue(head.fxi, rgb.at(2), 0);
×
1294
                    }
1295
            }
×
1296
            else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeDimmer)
×
1297
            {
1298
                quint32 channel = fxi->masterIntensityChannel();
×
1299

1300
                if (channel == QLCChannel::invalid())
×
1301
                    channel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head.head);
×
1302

1303
                if (channel != QLCChannel::invalid())
×
1304
                    grpScene->setValue(head.fxi, channel, 0);
×
1305
            }
1306
            else
1307
            {
1308
                quint32 channel = QLCChannel::invalid();
×
1309
                if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeWhite)
×
1310
                    channel = fxi->channelNumber(QLCChannel::White, QLCChannel::MSB, head.head);
×
1311
                else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeAmber)
×
1312
                    channel = fxi->channelNumber(QLCChannel::Amber, QLCChannel::MSB, head.head);
×
1313
                else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeUV)
×
1314
                    channel = fxi->channelNumber(QLCChannel::UV, QLCChannel::MSB, head.head);
×
1315
                else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeShutter)
×
1316
                {
1317
                    QLCFixtureHead fHead = fxi->head(head.head);
×
1318
                    QVector <quint32> shutters = fHead.shutterChannels();
×
1319
                    if (shutters.count())
×
1320
                        channel = shutters.first();
×
1321
                }
×
1322

1323
                if (channel != QLCChannel::invalid())
×
1324
                    grpScene->setValue(head.fxi, channel, 0);
×
1325
            }
1326
        }
×
1327
        m_doc->addFunction(grpScene);
×
1328

1329
        int totalSteps = m_matrix->stepsCount();
×
1330
        int increment = 1;
×
1331
        int currentStep = 0;
×
1332
        m_previewHandler->setStepColor(m_matrix->getColor(0));
×
1333

1334
        if (m_matrix->direction() == Function::Backward)
×
1335
        {
1336
            currentStep = totalSteps - 1;
×
1337
            increment = -1;
×
1338
            if (m_matrix->getColor(1).isValid())
×
1339
                m_previewHandler->setStepColor(m_matrix->getColor(1));
×
1340
        }
1341
        m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1342
                m_matrix->algorithm());
×
1343

1344
        if (m_matrix->runOrder() == RGBMatrix::PingPong)
×
1345
            totalSteps = (totalSteps * 2) - 1;
×
1346

1347
        Sequence *sequence = new Sequence(m_doc);
×
1348
        sequence->setName(QString("%1 %2").arg(m_matrix->name()).arg(tr("Sequence")));
×
1349
        sequence->setBoundSceneID(grpScene->id());
×
1350
        sequence->setDurationMode(Chaser::PerStep);
×
1351
        sequence->setDuration(m_matrix->duration());
×
1352

1353
        if (m_matrix->fadeInSpeed() != 0)
×
1354
        {
1355
            sequence->setFadeInMode(Chaser::PerStep);
×
1356
            sequence->setFadeInSpeed(m_matrix->fadeInSpeed());
×
1357
        }
1358
        if (m_matrix->fadeOutSpeed() != 0)
×
1359
        {
1360
            sequence->setFadeOutMode(Chaser::PerStep);
×
1361
            sequence->setFadeOutSpeed(m_matrix->fadeOutSpeed());
×
1362
        }
1363

1364
        for (int i = 0; i < totalSteps; i++)
×
1365
        {
1366
            m_matrix->previewMap(currentStep, m_previewHandler);
×
1367
            ChaserStep step;
×
1368
            step.fid = grpScene->id();
×
1369
            step.hold = m_matrix->duration() - m_matrix->fadeInSpeed();
×
1370
            step.duration = m_matrix->duration();
×
1371
            step.fadeIn = m_matrix->fadeInSpeed();
×
1372
            step.fadeOut = m_matrix->fadeOutSpeed();
×
1373

1374
            for (int y = 0; y < m_previewHandler->m_map.size(); y++)
×
1375
            {
1376
                for (int x = 0; x < m_previewHandler->m_map[y].size(); x++)
×
1377
                {
1378
                    uint col = m_previewHandler->m_map[y][x];
×
1379
                    GroupHead head = grp->head(QLCPoint(x, y));
×
1380

1381
                    Fixture *fxi = m_doc->fixture(head.fxi);
×
1382
                    if (fxi == NULL)
×
1383
                        continue;
×
1384

1385
                    if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeRgb)
×
1386
                    {
1387
                        QVector <quint32> rgb = fxi->rgbChannels(head.head);
×
1388
                        QVector <quint32> cmy = fxi->cmyChannels(head.head);
×
1389

1390
                        if (rgb.count() == 3)
×
1391
                        {
1392
                            step.values.append(SceneValue(head.fxi, rgb.at(0), qRed(col)));
×
1393
                            step.values.append(SceneValue(head.fxi, rgb.at(1), qGreen(col)));
×
1394
                            step.values.append(SceneValue(head.fxi, rgb.at(2), qBlue(col)));
×
1395
                        }
1396

1397
                        if (cmy.count() == 3)
×
1398
                        {
1399
                            QColor cmyCol(col);
×
1400

1401
                            step.values.append(SceneValue(head.fxi, cmy.at(0), cmyCol.cyan()));
×
1402
                            step.values.append(SceneValue(head.fxi, cmy.at(1), cmyCol.magenta()));
×
1403
                            step.values.append(SceneValue(head.fxi, cmy.at(2), cmyCol.yellow()));
×
1404
                        }
1405
                    }
×
1406
                    else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeDimmer)
×
1407
                    {
1408
                        quint32 channel = fxi->masterIntensityChannel();
×
1409

1410
                        if (channel == QLCChannel::invalid())
×
1411
                            channel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head.head);
×
1412

1413
                        if (channel != QLCChannel::invalid())
×
1414
                            step.values.append(SceneValue(head.fxi, channel, RGBMatrix::rgbToGrey(col)));
×
1415
                    }
1416
                    else
1417
                    {
1418
                        quint32 channel = QLCChannel::invalid();
×
1419
                        if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeWhite)
×
1420
                            channel = fxi->channelNumber(QLCChannel::White, QLCChannel::MSB, head.head);
×
1421
                        else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeAmber)
×
1422
                            channel = fxi->channelNumber(QLCChannel::Amber, QLCChannel::MSB, head.head);
×
1423
                        else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeUV)
×
1424
                            channel = fxi->channelNumber(QLCChannel::UV, QLCChannel::MSB, head.head);
×
1425
                        else if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeShutter)
×
1426
                        {
1427
                            QLCFixtureHead fHead = fxi->head(head.head);
×
1428
                            QVector <quint32> shutters = fHead.shutterChannels();
×
1429
                            if (shutters.count())
×
1430
                                channel = shutters.first();
×
1431
                        }
×
1432

1433
                        if (channel != QLCChannel::invalid())
×
1434
                            step.values.append(SceneValue(head.fxi, channel, RGBMatrix::rgbToGrey(col)));
×
1435
                    }
1436
                }
×
1437
            }
1438
            // !! Important !! matrix's heads can be displaced randomly but in a sequence
1439
            // we absolutely need ordered values. So do it now !
1440
            std::sort(step.values.begin(), step.values.end());
×
1441

1442
            sequence->addStep(step);
×
1443
            currentStep += increment;
×
1444
            if (currentStep == totalSteps)
×
1445
            {
1446
                if (m_matrix->runOrder() == RGBMatrix::PingPong)
×
1447
                {
1448
                    currentStep = totalSteps - 2;
×
1449
                    increment = -1;
×
1450
                }
1451
                else
1452
                {
1453
                    currentStep = 0;
×
1454
                }
1455
            }
1456
            m_previewHandler->updateStepColor(currentStep, m_matrix->getColor(0), m_matrix->stepsCount());
×
1457
        }
×
1458

1459
        m_doc->addFunction(sequence);
×
1460

1461
        if (testRunning == true)
×
1462
            m_testButton->click();
×
1463
        else if (createPreviewItems() == true)
×
1464
            m_previewTimer->start(MasterTimer::tick());
×
1465
    }
×
1466
}
1467

1468
void RGBMatrixEditor::slotShapeToggle(bool)
×
1469
{
1470
    createPreviewItems();
×
1471
}
×
1472

1473
void RGBMatrixEditor::slotPropertyComboChanged(int index)
×
1474
{
1475
    if (m_matrix->algorithm() == NULL ||
×
1476
        m_matrix->algorithm()->type() == RGBAlgorithm::Script)
×
1477
    {
1478
        QComboBox *combo = qobject_cast<QComboBox *>(sender());
×
1479
        QString pName = combo->property("pName").toString();
×
1480
        QString pValue = combo->itemText(index);
×
1481
        qDebug() << "Property combo changed to" << pValue;
×
1482
        m_matrix->setProperty(pName, pValue);
×
1483

1484
        updateColorOptions();
×
1485
        updateColors();
×
1486
    }
×
1487
}
×
1488

1489
void RGBMatrixEditor::slotPropertySpinChanged(int value)
×
1490
{
1491
    qDebug() << "Property spin changed to" << value;
×
1492
    if (m_matrix->algorithm() == NULL ||
×
1493
        m_matrix->algorithm()->type() == RGBAlgorithm::Script)
×
1494
    {
1495
        QSpinBox *spin = qobject_cast<QSpinBox *>(sender());
×
1496
        QString pName = spin->property("pName").toString();
×
1497
        m_matrix->setProperty(pName, QString::number(value));
×
1498
    }
×
1499
}
×
1500

1501
void RGBMatrixEditor::slotPropertyDoubleSpinChanged(double value)
×
1502
{
1503
    qDebug() << "Property float changed to" << value;
×
1504
    if (m_matrix->algorithm() == NULL ||
×
1505
        m_matrix->algorithm()->type() == RGBAlgorithm::Script)
×
1506
    {
1507
        QDoubleSpinBox *spin = qobject_cast<QDoubleSpinBox *>(sender());
×
1508
        QString pName = spin->property("pName").toString();
×
1509
        m_matrix->setProperty(pName, QString::number(value));
×
1510
    }
×
1511
}
×
1512

1513
void RGBMatrixEditor::slotPropertyEditChanged(QString text)
×
1514
{
1515
    qDebug() << "Property string changed to" << text;
×
1516
    if (m_matrix->algorithm() == NULL ||
×
1517
        m_matrix->algorithm()->type() == RGBAlgorithm::Script)
×
1518
    {
1519
        QLineEdit *edit = qobject_cast<QLineEdit *>(sender());
×
1520
        QString pName = edit->property("pName").toString();
×
1521
        m_matrix->setProperty(pName, text);
×
1522
    }
×
1523
}
×
1524

1525
FunctionParent RGBMatrixEditor::functionParent() const
×
1526
{
1527
    return FunctionParent::master();
×
1528
}
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