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

mcallegari / qlcplus / 18357067171

08 Oct 2025 08:16PM UTC coverage: 34.26% (+2.2%) from 32.066%
18357067171

push

github

mcallegari
Merge branch 'master' into filedialog

1282 of 4424 new or added lines in 152 files covered. (28.98%)

1342 existing lines in 152 files now uncovered.

17704 of 51675 relevant lines covered (34.26%)

19430.31 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)
UNCOV
61
    , m_doc(doc)
×
UNCOV
62
    , m_matrix(mtx)
×
63
    , m_previewHandler(new RGBMatrixStep())
×
UNCOV
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

NEW
103
    qDeleteAll(m_previewHash);
×
UNCOV
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);
×
NEW
179
    pm.fill(m_matrix->getColor(0));
×
NEW
180
    m_mtxColor1Button->setIcon(QIcon(pm));
×
181

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

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

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

NEW
200
    if (m_matrix->getColor(4).isValid())
×
NEW
201
        pm.fill(m_matrix->getColor(4));
×
202
    else
203
        pm.fill(Qt::transparent);
×
NEW
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)));
NEW
217
    connect(m_patternCombo, SIGNAL(activated(int)),
×
218
            this, SLOT(slotPatternActivated(int)));
UNCOV
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)));
NEW
225
    connect(m_mtxColor1Button, SIGNAL(clicked()),
×
226
            this, SLOT(slotMtxColor1ButtonClicked()));
NEW
227
    connect(m_mtxColor2Button, SIGNAL(clicked()),
×
228
            this, SLOT(slotMtxColor2ButtonClicked()));
NEW
229
    connect(m_resetMtxColor2Button, SIGNAL(clicked()),
×
230
            this, SLOT(slotResetMtxColor2ButtonClicked()));
NEW
231
    connect(m_mtxColor3Button, SIGNAL(clicked()),
×
232
            this, SLOT(slotMtxColor3ButtonClicked()));
NEW
233
    connect(m_resetMtxColor3Button, SIGNAL(clicked()),
×
234
            this, SLOT(slotResetMtxColor3ButtonClicked()));
NEW
235
    connect(m_mtxColor4Button, SIGNAL(clicked()),
×
236
            this, SLOT(slotMtxColor4ButtonClicked()));
NEW
237
    connect(m_resetMtxColor4Button, SIGNAL(clicked()),
×
238
            this, SLOT(slotResetMtxColor4ButtonClicked()));
NEW
239
    connect(m_mtxColor5Button, SIGNAL(clicked()),
×
240
            this, SLOT(slotMtxColor5ButtonClicked()));
NEW
241
    connect(m_resetMtxColor5Button, SIGNAL(clicked()),
×
242
            this, SLOT(slotResetMtxColor5ButtonClicked()));
UNCOV
243
    connect(m_textEdit, SIGNAL(textEdited(const QString&)),
×
244
            this, SLOT(slotTextEdited(const QString&)));
245
    connect(m_fontButton, SIGNAL(clicked()),
×
246
            this, SLOT(slotFontButtonClicked()));
NEW
247
    connect(m_animationCombo, SIGNAL(activated(int)),
×
248
            this, SLOT(slotAnimationActivated(int)));
UNCOV
249
    connect(m_imageEdit, SIGNAL(editingFinished()),
×
250
            this, SLOT(slotImageEdited()));
251
    connect(m_imageButton, SIGNAL(clicked()),
×
252
            this, SLOT(slotImageButtonClicked()));
NEW
253
    connect(m_imageAnimationCombo, SIGNAL(activated(int)),
×
254
            this, SLOT(slotImageAnimationActivated(int)));
UNCOV
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
{
UNCOV
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

NEW
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

NEW
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

NEW
399
    updateColorOptions();
×
NEW
400
}
×
401

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

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

NEW
418
        m_blendModeLabel->setVisible(accColors == 0 ? false : true);
×
NEW
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
            {
NEW
432
                m_matrix->setColor(0, Qt::white);
×
433
                // Overwrite more colors only if applied.
NEW
434
                if (accColors <= 2)
×
NEW
435
                    m_matrix->setColor(1, QColor());
×
NEW
436
                if (accColors <= 3)
×
NEW
437
                    m_matrix->setColor(2, QColor());
×
NEW
438
                if (accColors <= 4)
×
NEW
439
                    m_matrix->setColor(3, QColor());
×
NEW
440
                if (accColors <= 5)
×
NEW
441
                    m_matrix->setColor(4, QColor());
×
442

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

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

NEW
450
                pm.fill(Qt::transparent);
×
NEW
451
                m_mtxColor2Button->setIcon(QIcon(pm));
×
NEW
452
                m_mtxColor3Button->setIcon(QIcon(pm));
×
NEW
453
                m_mtxColor4Button->setIcon(QIcon(pm));
×
NEW
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
NEW
459
                uchar gray = qGray(m_matrix->getColor(0).rgb());
×
NEW
460
                m_matrix->setColor(0, QColor(gray, gray, gray));
×
461
                QPixmap pm(50, 26);
×
462
                pm.fill(QColor(gray, gray, gray));
×
NEW
463
                m_mtxColor1Button->setIcon(QIcon(pm));
×
464

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

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

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

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

NEW
522
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
NEW
523
                        m_matrix->algorithm());
×
UNCOV
524
            }
×
525
            else 
526
            {
527
                QPixmap pm(50, 26);
×
NEW
528
                pm.fill(m_matrix->getColor(0));
×
NEW
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
NEW
533
                if (m_matrix->getColor(1) == QColor())
×
NEW
534
                    pm.fill(Qt::transparent);
×
535
                else
NEW
536
                    pm.fill(m_matrix->getColor(1));
×
NEW
537
                m_mtxColor2Button->setIcon(QIcon(pm));
×
538

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

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

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

NEW
557
                m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
NEW
558
                        m_matrix->algorithm());
×
UNCOV
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

NEW
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);
×
NEW
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())
×
UNCOV
614
                            propCombo->setCurrentText(pValue);
×
615
                    }
UNCOV
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
                    }
UNCOV
641
                }
×
642
                gridRowIdx++;
×
643
            }
644
            break;
×
NEW
645
            case RGBScriptProperty::Float:
×
646
            {
NEW
647
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
NEW
648
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
NEW
649
                QDoubleSpinBox *propSpin = new QDoubleSpinBox(this);
×
NEW
650
                propSpin->setDecimals(3);
×
NEW
651
                propSpin->setRange(-1000000, 1000000);
×
NEW
652
                propSpin->setProperty("pName", prop.m_name);
×
NEW
653
                connect(propSpin, SIGNAL(valueChanged(double)),
×
654
                        this, SLOT(slotPropertyDoubleSpinChanged(double)));
NEW
655
                m_propertiesLayout->addWidget(propSpin, gridRowIdx, 1);
×
NEW
656
                if (m_matrix != NULL)
×
657
                {
NEW
658
                    QString pValue = m_matrix->property(prop.m_name);
×
NEW
659
                    if (!pValue.isEmpty())
×
NEW
660
                        propSpin->setValue(pValue.toDouble());
×
661
                    else
662
                    {
NEW
663
                        pValue = script->property(prop.m_name);
×
NEW
664
                        if (!pValue.isEmpty())
×
NEW
665
                            propSpin->setValue(pValue.toDouble());
×
666
                    }
NEW
667
                }
×
NEW
668
                gridRowIdx++;
×
669
            }
NEW
670
            break;
×
NEW
671
            case RGBScriptProperty::String:
×
672
            {
NEW
673
                QLabel *propLabel = new QLabel(prop.m_displayName);
×
NEW
674
                m_propertiesLayout->addWidget(propLabel, gridRowIdx, 0);
×
NEW
675
                QLineEdit *propEdit = new QLineEdit(this);
×
NEW
676
                propEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
×
NEW
677
                propEdit->setProperty("pName", prop.m_name);
×
NEW
678
                connect(propEdit, SIGNAL(textEdited(QString)),
×
679
                        this, SLOT(slotPropertyEditChanged(QString)));
NEW
680
                m_propertiesLayout->addWidget(propEdit, gridRowIdx, 1);
×
NEW
681
                if (m_matrix != NULL)
×
682
                {
NEW
683
                    QString pValue = m_matrix->property(prop.m_name);
×
NEW
684
                    if (!pValue.isEmpty())
×
NEW
685
                        propEdit->setText(pValue);
×
686
                    else
687
                    {
NEW
688
                        pValue = script->property(prop.m_name);
×
NEW
689
                        if (!pValue.isEmpty())
×
NEW
690
                            propEdit->setText(pValue);
×
691
                    }
NEW
692
                }
×
NEW
693
                gridRowIdx++;
×
694
            }
NEW
695
            break;
×
696
            default:
×
697
                qWarning() << "Type" << prop.m_type << "not handled yet";
×
698
            break;
×
699
        }
UNCOV
700
    }
×
UNCOV
701
}
×
702

703
bool RGBMatrixEditor::createPreviewItems()
×
704
{
NEW
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

NEW
718
    m_previewHandler->initializeDirection(m_matrix->direction(), m_matrix->getColor(0),
×
NEW
719
                                      m_matrix->getColor(1), m_matrix->stepsCount(),
×
NEW
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
    {
NEW
776
        m_previewHandler->checkNextStep(m_matrix->runOrder(), m_matrix->getColor(0),
×
NEW
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);
×
NEW
789
            RGBItem* shape = m_previewHash.value(pt, NULL);
×
NEW
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

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

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

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

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

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

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

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

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

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

NEW
971
void RGBMatrixEditor::slotResetMtxColor5ButtonClicked()
×
972
{
NEW
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
    {
NEW
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);
×
UNCOV
987
        }
×
988
        slotRestartTest();
×
989
    }
990
}
×
991

992
void RGBMatrixEditor::slotFontButtonClicked()
×
993
{
994
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
995
    {
NEW
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);
×
UNCOV
1006
            }
×
1007
            slotRestartTest();
×
1008
        }
UNCOV
1009
    }
×
1010
}
×
1011

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

1027
void RGBMatrixEditor::slotImageEdited()
×
1028
{
1029
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1030
    {
NEW
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());
×
UNCOV
1036
        }
×
1037
        slotRestartTest();
×
1038
    }
1039
}
×
1040

1041
void RGBMatrixEditor::slotImageButtonClicked()
×
1042
{
1043
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1044
    {
NEW
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);
×
UNCOV
1058
            }
×
1059
            m_imageEdit->setText(path);
×
1060
            slotRestartTest();
×
1061
        }
UNCOV
1062
    }
×
1063
}
×
1064

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

1080
void RGBMatrixEditor::slotOffsetSpinChanged()
×
1081
{
1082
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Text)
×
1083
    {
NEW
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());
×
UNCOV
1090
        }
×
1091
        slotRestartTest();
×
1092
    }
1093

1094
    if (m_matrix->algorithm() != NULL && m_matrix->algorithm()->type() == RGBAlgorithm::Image)
×
1095
    {
NEW
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());
×
UNCOV
1102
        }
×
1103
        slotRestartTest();
×
1104
    }
1105
}
×
1106

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

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

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

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

1139
void RGBMatrixEditor::slotBackwardClicked()
×
1140
{
1141
    m_matrix->setDirection(Function::Backward);
×
NEW
1142
    m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
NEW
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
                    }
UNCOV
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();
×
UNCOV
1317
                }
×
1318

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

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

1330
        if (m_matrix->direction() == Function::Backward)
×
1331
        {
1332
            currentStep = totalSteps - 1;
×
1333
            increment = -1;
×
NEW
1334
            if (m_matrix->getColor(1).isValid())
×
NEW
1335
                m_previewHandler->setStepColor(m_matrix->getColor(1));
×
1336
        }
NEW
1337
        m_previewHandler->calculateColorDelta(m_matrix->getColor(0), m_matrix->getColor(1),
×
NEW
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
                        }
UNCOV
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();
×
UNCOV
1427
                        }
×
1428

1429
                        if (channel != QLCChannel::invalid())
×
1430
                            step.values.append(SceneValue(head.fxi, channel, RGBMatrix::rgbToGrey(col)));
×
1431
                    }
UNCOV
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;
×
NEW
1440
            if (currentStep == totalSteps)
×
1441
            {
NEW
1442
                if (m_matrix->runOrder() == RGBMatrix::PingPong)
×
1443
                {
NEW
1444
                    currentStep = totalSteps - 2;
×
NEW
1445
                    increment = -1;
×
1446
                }
1447
                else
1448
                {
NEW
1449
                    currentStep = 0;
×
1450
                }
1451
            }
NEW
1452
            m_previewHandler->updateStepColor(currentStep, m_matrix->getColor(0), m_matrix->stepsCount());
×
UNCOV
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());
×
UNCOV
1461
    }
×
1462
}
1463

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

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

NEW
1480
        updateColorOptions();
×
NEW
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
    {
NEW
1491
        QSpinBox *spin = qobject_cast<QSpinBox *>(sender());
×
1492
        QString pName = spin->property("pName").toString();
×
1493
        m_matrix->setProperty(pName, QString::number(value));
×
UNCOV
1494
    }
×
1495
}
×
1496

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

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

UNCOV
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