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

mcallegari / qlcplus / 19144422256

06 Nov 2025 05:33PM UTC coverage: 34.256% (-0.1%) from 34.358%
19144422256

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 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
{
129
    /* Name */
130
    m_nameEdit->setText(m_matrix->name());
×
131
    m_nameEdit->setSelection(0, m_matrix->name().length());
×
132

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

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

160

161
    /* Blend mode */
162
    m_blendModeCombo->setCurrentIndex(m_matrix->blendMode());
×
163

164
    /* Color mode */
165
    m_controlModeCombo->setCurrentIndex(m_matrix->controlMode());
×
166

167
    /* Dimmer control */
168
    if (m_matrix->dimmerControl())
×
169
        m_dimmerControlCb->setChecked(m_matrix->dimmerControl());
×
170
    else
171
        m_intensityGroup->hide();
×
172

173
    fillPatternCombo();
×
174
    fillFixtureGroupCombo();
×
175
    fillAnimationCombo();
×
176
    fillImageAnimationCombo();
×
177

178
    QPixmap pm(50, 26);
×
179
    pm.fill(m_matrix->getColor(0));
×
180
    m_mtxColor1Button->setIcon(QIcon(pm));
×
181

182
    if (m_matrix->getColor(1).isValid())
×
183
        pm.fill(m_matrix->getColor(1));
×
184
    else
185
        pm.fill(Qt::transparent);
×
186
    m_mtxColor2Button->setIcon(QIcon(pm));
×
187

188
    if (m_matrix->getColor(2).isValid())
×
189
        pm.fill(m_matrix->getColor(2));
×
190
    else
191
        pm.fill(Qt::transparent);
×
192
    m_mtxColor3Button->setIcon(QIcon(pm));
×
193

194
    if (m_matrix->getColor(3).isValid())
×
195
        pm.fill(m_matrix->getColor(3));
×
196
    else
197
        pm.fill(Qt::transparent);
×
198
    m_mtxColor4Button->setIcon(QIcon(pm));
×
199

200
    if (m_matrix->getColor(4).isValid())
×
201
        pm.fill(m_matrix->getColor(4));
×
202
    else
203
        pm.fill(Qt::transparent);
×
204
    m_mtxColor5Button->setIcon(QIcon(pm));
×
205

206
    updateExtraOptions();
×
207
    updateSpeedDials();
×
208

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

260
    connect(m_loop, SIGNAL(clicked()), this, SLOT(slotLoopClicked()));
×
261
    connect(m_pingPong, SIGNAL(clicked()), this, SLOT(slotPingPongClicked()));
×
262
    connect(m_singleShot, SIGNAL(clicked()), this, SLOT(slotSingleShotClicked()));
×
263
    connect(m_forward, SIGNAL(clicked()), this, SLOT(slotForwardClicked()));
×
264
    connect(m_backward, SIGNAL(clicked()), this, SLOT(slotBackwardClicked()));
×
265
    connect(m_dimmerControlCb, SIGNAL(clicked()), this, SLOT(slotDimmerControlClicked()));
×
266

267
    // Test slots
268
    connect(m_testButton, SIGNAL(clicked(bool)),
×
269
            this, SLOT(slotTestClicked()));
270

271
    m_preview->setScene(m_scene);
×
272
    if (createPreviewItems() == true)
×
273
        m_previewTimer->start(MasterTimer::tick());
×
274
}
×
275

276
void RGBMatrixEditor::updateSpeedDials()
×
277
{
278
    if (m_speedDialButton->isChecked() == false)
×
279
        return;
×
280

281
    if (m_speedDials != NULL)
×
282
        return;
×
283

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

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

312
void RGBMatrixEditor::fillFixtureGroupCombo()
×
313
{
314
    m_fixtureGroupCombo->clear();
×
315
    m_fixtureGroupCombo->addItem(tr("None"));
×
316

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

328
void RGBMatrixEditor::fillAnimationCombo()
×
329
{
330
    m_animationCombo->addItems(RGBText::animationStyles());
×
331
}
×
332

333
void RGBMatrixEditor::fillImageAnimationCombo()
×
334
{
335
    m_imageAnimationCombo->addItems(RGBImage::animationStyles());
×
336
}
×
337

338
void RGBMatrixEditor::updateExtraOptions()
×
339
{
340
    resetProperties(m_propertiesLayout->layout());
×
341
    m_propertiesGroup->hide();
×
342

343
    if (m_matrix->algorithm() == NULL ||
×
344
        m_matrix->algorithm()->type() == RGBAlgorithm::Script ||
×
345
        m_matrix->algorithm()->type() == RGBAlgorithm::Audio)
×
346
    {
347
        m_textGroup->hide();
×
348
        m_imageGroup->hide();
×
349
        m_offsetGroup->hide();
×
350

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

369
        RGBImage *image = static_cast<RGBImage*> (m_matrix->algorithm());
×
370
        Q_ASSERT(image != NULL);
×
371
        m_imageEdit->setText(image->filename());
×
372

373
        int index = m_imageAnimationCombo->findText(RGBImage::animationStyleToString(image->animationStyle()));
×
374
        if (index != -1)
×
375
            m_imageAnimationCombo->setCurrentIndex(index);
×
376

377
        m_xOffsetSpin->setValue(image->xOffset());
×
378
        m_yOffsetSpin->setValue(image->yOffset());
×
379

380
    }
381
    else if (m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
382
    {
383
        m_textGroup->show();
×
384
        m_offsetGroup->show();
×
385
        m_imageGroup->hide();
×
386

387
        RGBText *text = static_cast<RGBText*> (m_matrix->algorithm());
×
388
        Q_ASSERT(text != NULL);
×
389
        m_textEdit->setText(text->text());
×
390

391
        int index = m_animationCombo->findText(RGBText::animationStyleToString(text->animationStyle()));
×
392
        if (index != -1)
×
393
            m_animationCombo->setCurrentIndex(index);
×
394

395
        m_xOffsetSpin->setValue(text->xOffset());
×
396
        m_yOffsetSpin->setValue(text->yOffset());
×
397
    }
398

399
    updateColorOptions();
×
400
}
×
401

402
void RGBMatrixEditor::updateColorOptions()
×
403
{
404
    if (m_matrix->algorithm() != NULL)
×
405
    {
406
        int accColors = m_matrix->algorithm()->acceptColors();
×
407

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

418
        m_blendModeLabel->setVisible(accColors == 0 ? false : true);
×
419
        m_blendModeCombo->setVisible(accColors == 0 ? false : true);
×
420
    }
421
}
×
422

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

443
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
444
                        m_matrix->algorithm());
×
445

446
                QPixmap pm(50, 26);
×
447
                pm.fill(Qt::white);
×
448
                m_mtxColor1Button->setIcon(QIcon(pm));
×
449

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

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

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

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

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

522
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
523
                        m_matrix->algorithm());
×
524
            }
×
525
            else 
526
            {
527
                QPixmap pm(50, 26);
×
528
                pm.fill(m_matrix->getColor(0));
×
529
                m_mtxColor1Button->setIcon(QIcon(pm));
×
530

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

539
                if (m_matrix->getColor(2) == QColor())
×
540
                    pm.fill(Qt::transparent);
×
541
                else
542
                    pm.fill(m_matrix->getColor(2));
×
543
                m_mtxColor3Button->setIcon(QIcon(pm));
×
544

545
                if (m_matrix->getColor(3) == QColor())
×
546
                    pm.fill(Qt::transparent);
×
547
                else
548
                    pm.fill(m_matrix->getColor(3));
×
549
                m_mtxColor4Button->setIcon(QIcon(pm));
×
550

551
                if (m_matrix->getColor(4) == QColor())
×
552
                    pm.fill(Qt::transparent);
×
553
                else
554
                    pm.fill(m_matrix->getColor(4));
×
555
                m_mtxColor5Button->setIcon(QIcon(pm));
×
556

557
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
558
                        m_matrix->algorithm());
×
559
            }
×
560
        }
561
    }
562
}
×
563

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

578
void RGBMatrixEditor::displayProperties(RGBScript *script)
×
579
{
580
    if (script == NULL)
×
581
        return;
×
582

583
    int gridRowIdx = 0;
×
584

585
    QList<RGBScriptProperty> properties = script->properties();
×
586
    if (properties.count() > 0)
×
587
        m_propertiesGroup->show();
×
588

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

703
bool RGBMatrixEditor::createPreviewItems()
×
704
{
705
    qDeleteAll(m_previewHash);
×
706
    m_previewHash.clear();
×
707
    m_scene->clear();
×
708

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

718
    m_previewHandler->initializeDirection(m_matrix->direction(), m_matrix->getColor(0),
×
719
                                      m_matrix->getColor(1), m_matrix->stepsCount(),
×
720
                                      m_matrix->algorithm());
×
721

722
    m_matrix->previewMap(m_previewHandler->currentStepIndex(), m_previewHandler);
×
723

724
    if (m_previewHandler->m_map.isEmpty())
×
725
        return false;
×
726

727
    for (int x = 0; x < grp->size().width(); x++)
×
728
    {
729
        for (int y = 0; y < grp->size().height(); y++)
×
730
        {
731
            QLCPoint pt(x, y);
×
732

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

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

767
void RGBMatrixEditor::slotPreviewTimeout()
×
768
{
769
    if (m_matrix->duration() <= 0)
×
770
        return;
×
771

772
    m_previewIterator += MasterTimer::tick();
×
773
    uint elapsed = 0;
×
774
    while (m_previewIterator >= MAX(m_matrix->duration(), MasterTimer::tick()))
×
775
    {
776
        m_previewHandler->checkNextStep(m_matrix->runOrder(), m_matrix->getColor(0),
×
777
                                        m_matrix->getColor(1), m_matrix->stepsCount());
×
778

779
        m_matrix->previewMap(m_previewHandler->currentStepIndex(), m_previewHandler);
×
780

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

795
                if (shape->color() == QColor(Qt::black).rgb())
×
796
                    shape->draw(elapsed, m_matrix->fadeOutSpeed());
×
797
                else
798
                    shape->draw(elapsed, m_matrix->fadeInSpeed());
×
799
            }
800
        }
801
    }
802
}
803

804
void RGBMatrixEditor::slotNameEdited(const QString& text)
×
805
{
806
    m_matrix->setName(text);
×
807
    if (m_speedDials != NULL)
×
808
        m_speedDials->setWindowTitle(text);
×
809
}
×
810

811
void RGBMatrixEditor::slotSpeedDialToggle(bool state)
×
812
{
813
    if (state == true)
×
814
        updateSpeedDials();
×
815
    else
816
    {
817
        if (m_speedDials != NULL)
×
818
            m_speedDials->deleteLater();
×
819
        m_speedDials = NULL;
×
820
    }
821
}
×
822

823
void RGBMatrixEditor::slotDialDestroyed(QObject *)
×
824
{
825
    m_speedDialButton->setChecked(false);
×
826
}
×
827

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

851
    slotRestartTest();
×
852
}
×
853

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

870
void RGBMatrixEditor::slotBlendModeChanged(int index)
×
871
{
872
    m_matrix->setBlendMode(Universe::BlendMode(index));
×
873

874
    if (index == Universe::MaskBlend)
×
875
    {
876
        m_mtxColor1Button->setEnabled(false);
×
877
    }
878
    else
879
    {
880
        m_mtxColor1Button->setEnabled(true);
×
881
    }
882
    updateExtraOptions();
×
883
    updateColors();
×
884
    slotRestartTest();
×
885
}
×
886

887
void RGBMatrixEditor::slotControlModeChanged(int index)
×
888
{
889
    RGBMatrix::ControlMode mode = RGBMatrix::ControlMode(index);
×
890
    m_matrix->setControlMode(mode);
×
891
    updateColors();
×
892
    slotRestartTest();
×
893
}
×
894

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

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

917
void RGBMatrixEditor::slotResetMtxColor2ButtonClicked()
×
918
{
919
    m_matrix->setColor(1, QColor());
×
920
    updateColors();
×
921
    slotRestartTest();
×
922
}
×
923

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

935
void RGBMatrixEditor::slotResetMtxColor3ButtonClicked()
×
936
{
937
    m_matrix->setColor(2, QColor());
×
938
    updateColors();
×
939
    slotRestartTest();
×
940
}
×
941

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

953
void RGBMatrixEditor::slotResetMtxColor4ButtonClicked()
×
954
{
955
    m_matrix->setColor(3, QColor());
×
956
    updateColors();
×
957
    slotRestartTest();
×
958
}
×
959

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

971
void RGBMatrixEditor::slotResetMtxColor5ButtonClicked()
×
972
{
973
    m_matrix->setColor(4, QColor());
×
974
    updateColors();
×
975
    slotRestartTest();
×
976
}
×
977

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

992
void RGBMatrixEditor::slotFontButtonClicked()
×
993
{
994
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
995
    {
996
        RGBText *algo = static_cast<RGBText*> (m_matrix->algorithm());
×
997
        Q_ASSERT(algo != NULL);
×
998

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

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

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

1041
void RGBMatrixEditor::slotImageButtonClicked()
×
1042
{
1043
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1044
    {
1045
        RGBImage *algo = static_cast<RGBImage*> (m_matrix->algorithm());
×
1046
        Q_ASSERT(algo != NULL);
×
1047

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

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

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

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

1107
void RGBMatrixEditor::slotLoopClicked()
×
1108
{
1109
    m_matrix->setRunOrder(Function::Loop);
×
1110
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1111
            m_matrix->algorithm());
×
1112
    slotRestartTest();
×
1113
}
×
1114

1115
void RGBMatrixEditor::slotPingPongClicked()
×
1116
{
1117
    m_matrix->setRunOrder(Function::PingPong);
×
1118
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1119
            m_matrix->algorithm());
×
1120
    slotRestartTest();
×
1121
}
×
1122

1123
void RGBMatrixEditor::slotSingleShotClicked()
×
1124
{
1125
    m_matrix->setRunOrder(Function::SingleShot);
×
1126
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1127
            m_matrix->algorithm());
×
1128
    slotRestartTest();
×
1129
}
×
1130

1131
void RGBMatrixEditor::slotForwardClicked()
×
1132
{
1133
    m_matrix->setDirection(Function::Forward);
×
1134
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1135
            m_matrix->algorithm());
×
1136
    slotRestartTest();
×
1137
}
×
1138

1139
void RGBMatrixEditor::slotBackwardClicked()
×
1140
{
1141
    m_matrix->setDirection(Function::Backward);
×
1142
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
1143
            m_matrix->algorithm());
×
1144
    slotRestartTest();
×
1145
}
×
1146

1147
void RGBMatrixEditor::slotDimmerControlClicked()
×
1148
{
1149
    m_matrix->setDimmerControl(m_dimmerControlCb->isChecked());
×
1150
    if (m_dimmerControlCb->isChecked() == false)
×
1151
        m_dimmerControlCb->setEnabled(false);
×
1152
}
×
1153

1154
void RGBMatrixEditor::slotFadeInChanged(int ms)
×
1155
{
1156
    m_matrix->setFadeInSpeed(ms);
×
1157
    uint duration = Function::speedAdd(ms, m_speedDials->duration());
×
1158
    m_matrix->setDuration(duration);
×
1159
}
×
1160

1161
void RGBMatrixEditor::slotFadeOutChanged(int ms)
×
1162
{
1163
    m_matrix->setFadeOutSpeed(ms);
×
1164
}
×
1165

1166
void RGBMatrixEditor::slotHoldChanged(int ms)
×
1167
{
1168
    uint duration = Function::speedAdd(m_matrix->fadeInSpeed(), ms);
×
1169
    m_matrix->setDuration(duration);
×
1170
}
×
1171

1172
void RGBMatrixEditor::slotDurationTapped()
×
1173
{
1174
    m_matrix->tap();
×
1175
}
×
1176

1177
void RGBMatrixEditor::slotTestClicked()
×
1178
{
1179
    if (m_testButton->isChecked() == true)
×
1180
        m_matrix->start(m_doc->masterTimer(), functionParent());
×
1181
    else
1182
        m_matrix->stopAndWait();
×
1183
}
×
1184

1185
void RGBMatrixEditor::slotRestartTest()
×
1186
{
1187
    m_previewTimer->stop();
×
1188

1189
    if (m_testButton->isChecked() == true)
×
1190
    {
1191
        // Toggle off, toggle on. Duh.
1192
        m_testButton->click();
×
1193
        m_testButton->click();
×
1194
    }
1195

1196
    if (createPreviewItems() == true)
×
1197
        m_previewTimer->start(MasterTimer::tick());
×
1198

1199
}
×
1200

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

1216
void RGBMatrixEditor::slotFixtureGroupAdded()
×
1217
{
1218
    fillFixtureGroupCombo();
×
1219
}
×
1220

1221
void RGBMatrixEditor::slotFixtureGroupRemoved()
×
1222
{
1223
    fillFixtureGroupCombo();
×
1224
    slotFixtureGroupActivated(m_fixtureGroupCombo->currentIndex());
×
1225
}
×
1226

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

1247
void RGBMatrixEditor::slotSaveToSequenceClicked()
×
1248
{
1249
    if (m_matrix == NULL || m_matrix->fixtureGroup() == FixtureGroup::invalidId())
×
1250
        return;
×
1251

1252
    FixtureGroup* grp = m_doc->fixtureGroup(m_matrix->fixtureGroup());
×
1253
    if (grp != NULL && m_matrix->algorithm() != NULL)
×
1254
    {
1255
        bool testRunning = false;
×
1256

1257
        if (m_testButton->isChecked() == true)
×
1258
        {
1259
            m_testButton->click();
×
1260
            testRunning = true;
×
1261
        }
1262
        else
1263
            m_previewTimer->stop();
×
1264

1265
        Scene *grpScene = new Scene(m_doc);
×
1266
        grpScene->setName(grp->name());
×
1267
        grpScene->setVisible(false);
×
1268

1269
        QList<GroupHead> headList = grp->headList();
×
1270
        foreach (GroupHead head, headList)
×
1271
        {
1272
            Fixture *fxi = m_doc->fixture(head.fxi);
×
1273
            if (fxi == NULL)
×
1274
                continue;
×
1275

1276
            if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeRgb)
×
1277
            {
1278

1279
                    QVector <quint32> rgb = fxi->rgbChannels(head.head);
×
1280

1281
                    // in case of CMY, dump those channels
1282
                    if (rgb.count() == 0)
×
1283
                        rgb = fxi->cmyChannels(head.head);
×
1284

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

1296
                if (channel == QLCChannel::invalid())
×
1297
                    channel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head.head);
×
1298

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

1319
                if (channel != QLCChannel::invalid())
×
1320
                    grpScene->setValue(head.fxi, channel, 0);
×
1321
            }
1322
        }
×
1323
        m_doc->addFunction(grpScene);
×
1324

1325
        int totalSteps = m_matrix->stepsCount();
×
1326
        int increment = 1;
×
1327
        int currentStep = 0;
×
1328
        m_previewHandler->setStepColor(m_matrix->getColor(0));
×
1329

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

1340
        if (m_matrix->runOrder() == RGBMatrix::PingPong)
×
1341
            totalSteps = (totalSteps * 2) - 1;
×
1342

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

1349
        if (m_matrix->fadeInSpeed() != 0)
×
1350
        {
1351
            sequence->setFadeInMode(Chaser::PerStep);
×
1352
            sequence->setFadeInSpeed(m_matrix->fadeInSpeed());
×
1353
        }
1354
        if (m_matrix->fadeOutSpeed() != 0)
×
1355
        {
1356
            sequence->setFadeOutMode(Chaser::PerStep);
×
1357
            sequence->setFadeOutSpeed(m_matrix->fadeOutSpeed());
×
1358
        }
1359

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

1370
            for (int y = 0; y < m_previewHandler->m_map.size(); y++)
×
1371
            {
1372
                for (int x = 0; x < m_previewHandler->m_map[y].size(); x++)
×
1373
                {
1374
                    uint col = m_previewHandler->m_map[y][x];
×
1375
                    GroupHead head = grp->head(QLCPoint(x, y));
×
1376

1377
                    Fixture *fxi = m_doc->fixture(head.fxi);
×
1378
                    if (fxi == NULL)
×
1379
                        continue;
×
1380

1381
                    if (m_controlModeCombo->currentIndex() == RGBMatrix::ControlModeRgb)
×
1382
                    {
1383
                        QVector <quint32> rgb = fxi->rgbChannels(head.head);
×
1384
                        QVector <quint32> cmy = fxi->cmyChannels(head.head);
×
1385

1386
                        if (rgb.count() == 3)
×
1387
                        {
1388
                            step.values.append(SceneValue(head.fxi, rgb.at(0), qRed(col)));
×
1389
                            step.values.append(SceneValue(head.fxi, rgb.at(1), qGreen(col)));
×
1390
                            step.values.append(SceneValue(head.fxi, rgb.at(2), qBlue(col)));
×
1391
                        }
1392

1393
                        if (cmy.count() == 3)
×
1394
                        {
1395
                            QColor cmyCol(col);
×
1396

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

1406
                        if (channel == QLCChannel::invalid())
×
1407
                            channel = fxi->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, head.head);
×
1408

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

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

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

1455
        m_doc->addFunction(sequence);
×
1456

1457
        if (testRunning == true)
×
1458
            m_testButton->click();
×
1459
        else if (createPreviewItems() == true)
×
1460
            m_previewTimer->start(MasterTimer::tick());
×
1461
    }
×
1462
}
1463

1464
void RGBMatrixEditor::slotShapeToggle(bool)
×
1465
{
1466
    createPreviewItems();
×
1467
}
×
1468

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

1480
        updateColorOptions();
×
1481
        updateColors();
×
1482
    }
×
1483
}
×
1484

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

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

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

1521
FunctionParent RGBMatrixEditor::functionParent() const
×
1522
{
1523
    return FunctionParent::master();
×
1524
}
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