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

mcallegari / qlcplus / 6919781282

19 Nov 2023 10:03AM UTC coverage: 32.007% (-0.004%) from 32.011%
6919781282

push

github

mcallegari
vc/animation: fix last signals not fired

0 of 35 new or added lines in 1 file covered. (0.0%)

2 existing lines in 1 file now uncovered.

15109 of 47206 relevant lines covered (32.01%)

23535.46 hits per line

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

0.0
/ui/src/virtualconsole/vcmatrix.cpp
1
/*
2
  Q Light Controller Plus
3
  vcmatrix.cpp
4

5
  Copyright (c) Massimo Callegari
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 <QXmlStreamReader>
21
#include <QXmlStreamWriter>
22
#include <QWidgetAction>
23
#include <QComboBox>
24
#include <QSettings>
25
#include <QLayout>
26
#include <QDebug>
27
#include <QTimer>
28
#include <QLabel>
29
#include <QMenu>
30
#include <math.h>
31

32
#include "vcmatrixproperties.h"
33
#include "vcpropertieseditor.h"
34
#include "clickandgoslider.h"
35
#include "clickandgowidget.h"
36
#include "knobwidget.h"
37
#include "qlcmacros.h"
38
#include "rgbalgorithm.h"
39
#include "flowlayout.h"
40
#include "rgbmatrix.h"
41
#include "vcmatrix.h"
42
#include "function.h"
43
#include "rgbtext.h"
44
#include "doc.h"
45

46
#define UPDATE_TIMEOUT 50
47

48
static const QString controlBtnSS = "QPushButton { background-color: %1; height: 32px; border: 2px solid #6A6A6A; border-radius: 5px; }"
49
                                    "QPushButton:pressed { border: 2px solid #0000FF; }"
50
                                    "QPushButton:disabled { border: 2px solid #BBBBBB; color: #8f8f8f }";
51

52
const QSize VCMatrix::defaultSize(QSize(160, 120));
53

54
VCMatrix::VCMatrix(QWidget *parent, Doc *doc)
×
55
    : VCWidget(parent, doc)
56
    , m_sliderExternalMovement(false)
57
    , m_matrixID(Function::invalidId())
×
58
    , m_instantApply(true)
59
    , m_visibilityMask(VCMatrix::defaultVisibilityMask())
×
60
{
61
    /* Set the class name "VCMatrix" as the object name as well */
62
    setObjectName(VCMatrix::staticMetaObject.className());
×
63
    setFrameStyle(KVCFrameStyleSunken);
×
64

65
    QHBoxLayout *hBox = new QHBoxLayout(this);
×
66
    //hBox->setContentsMargins(3, 3, 3, 10);
67
    //hBox->setSpacing(5);
68

69
    m_slider = new ClickAndGoSlider();
×
70
    m_slider->setSliderStyleSheet(CNG_DEFAULT_STYLE);
×
71
    m_slider->setFixedWidth(32);
×
72
    m_slider->setRange(0, 255);
×
73
    m_slider->setPageStep(1);
×
74
    m_slider->setInvertedAppearance(false);
×
75
    hBox->addWidget(m_slider);
×
76

77
    connect(m_slider, SIGNAL(valueChanged(int)),
×
78
            this, SLOT(slotSliderMoved(int)));
79

80
    QVBoxLayout *vbox = new QVBoxLayout();
×
81

82
    m_startColorButton = new QToolButton(this);
×
83
    m_startColorButton->setFixedSize(48, 48);
×
84
    m_startColorButton->setIconSize(QSize(42, 42));
×
85

86
    QWidgetAction* scAction = new QWidgetAction(this);
×
87
    m_scCnGWidget = new ClickAndGoWidget();
×
88
    m_scCnGWidget->setType(ClickAndGoWidget::RGB, NULL);
×
89
    scAction->setDefaultWidget(m_scCnGWidget);
×
90
    QMenu *startColorMenu = new QMenu();
×
91
    startColorMenu->addAction(scAction);
×
92
    m_startColorButton->setMenu(startColorMenu);
×
93
    m_startColorButton->setPopupMode(QToolButton::InstantPopup);
×
94

95
    connect(m_scCnGWidget, SIGNAL(colorChanged(QRgb)),
×
96
            this, SLOT(slotStartColorChanged(QRgb)));
97

98
    m_endColorButton = new QToolButton(this);
×
99
    m_endColorButton->setFixedSize(48, 48);
×
100
    m_endColorButton->setIconSize(QSize(42, 42));
×
101

102
    QWidgetAction* ecAction = new QWidgetAction(this);
×
103
    m_ecCnGWidget = new ClickAndGoWidget();
×
104
    m_ecCnGWidget->setType(ClickAndGoWidget::RGB, NULL);
×
105
    ecAction->setDefaultWidget(m_ecCnGWidget);
×
106
    QMenu *endColorMenu = new QMenu();
×
107
    endColorMenu->addAction(ecAction);
×
108
    m_endColorButton->setMenu(endColorMenu);
×
109
    m_endColorButton->setPopupMode(QToolButton::InstantPopup);
×
110

111
    connect(m_ecCnGWidget, SIGNAL(colorChanged(QRgb)),
×
112
            this, SLOT(slotEndColorChanged(QRgb)));
113

114
    m_label = new QLabel(this);
×
115
    m_label->setAlignment(Qt::AlignCenter);
×
116
    m_label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
×
117
    vbox->addWidget(m_label);
×
118

119
    QHBoxLayout *btnHbox = new QHBoxLayout();
×
120

121
    btnHbox->addWidget(m_startColorButton);
×
122
    btnHbox->addWidget(m_endColorButton);
×
123

124
    vbox->addLayout(btnHbox);
×
125

126
    m_presetCombo = new QComboBox(this);
×
127
    //m_presetCombo->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
128
    m_presetCombo->addItems(RGBAlgorithm::algorithms(m_doc));
×
129
    connect(m_presetCombo, SIGNAL(currentIndexChanged(QString)),
×
130
            this, SLOT(slotAnimationChanged(QString)));
131
    vbox->addWidget(m_presetCombo);
×
132

133
    hBox->addLayout(vbox);
×
134

135
    m_controlsLayout = new FlowLayout();
×
136
    vbox->addLayout(m_controlsLayout);
×
137

138
    setType(VCWidget::AnimationWidget);
×
139
    setCaption(QString());
×
140
    /* Initial size */
141
    QSettings settings;
×
142
    QVariant var = settings.value(SETTINGS_RGBMATRIX_SIZE);
×
143
    if (var.isValid() == true)
×
144
        resize(var.toSize());
×
145
    else
146
        resize(defaultSize);
×
147

148
    /* Update timer */
149
    m_updateTimer = new QTimer(this);
×
150
    connect(m_updateTimer, SIGNAL(timeout()),
×
151
            this, SLOT(slotUpdate()));
152
    m_updateTimer->setSingleShot(true);
×
153

154
    /* Update the slider according to current mode */
155
    slotModeChanged(m_doc->mode());
×
156
    setLiveEdit(m_liveEdit);
×
157
}
×
158

159
VCMatrix::~VCMatrix()
×
160
{
161
    foreach(VCMatrixControl* control, m_controls)
×
162
    {
163
        delete control;
×
164
    }
165
}
×
166

167
void VCMatrix::setID(quint32 id)
×
168
{
169
    VCWidget::setID(id);
×
170

171
    if (caption().isEmpty())
×
172
        setCaption(tr("Animation %1").arg(id));
×
173
}
×
174

175
/*********************************************************************
176
 * Clipboard
177
 *********************************************************************/
178

179
VCWidget *VCMatrix::createCopy(VCWidget *parent)
×
180
{
181
    Q_ASSERT(parent != NULL);
×
182

183
    VCMatrix* matrix = new VCMatrix(parent, m_doc);
×
184
    if (matrix->copyFrom(this) == false)
×
185
    {
186
        delete matrix;
×
187
        matrix = NULL;
×
188
    }
189

190
    return matrix;
×
191
}
192

193
bool VCMatrix::copyFrom(const VCWidget* widget)
×
194
{
195
    const VCMatrix* matrix = qobject_cast <const VCMatrix*> (widget);
×
196
    if (matrix == NULL)
×
197
        return false;
×
198

199
    /* Copy vcmatrix-specific stuff */
200
    setFunction(matrix->function());
×
201
    setInstantChanges(matrix->instantChanges());
×
202
    setVisibilityMask(matrix->visibilityMask());
×
203

204
    resetCustomControls();
×
205
    foreach (VCMatrixControl const* control, matrix->customControls())
×
206
    {
207
        addCustomControl(*control);
×
208
    }
209

210
    /* Copy common stuff */
211
    return VCWidget::copyFrom(widget);
×
212
}
213

214
/*********************************************************************
215
 * GUI
216
 *********************************************************************/
217

218
void VCMatrix::setCaption(const QString &text)
×
219
{
220
    VCWidget::setCaption(text);
×
221
    m_label->setText(text);
×
222
}
×
223

224
void VCMatrix::enableWidgetUI(bool enable)
×
225
{
226
    m_slider->setEnabled(enable);
×
227
    m_startColorButton->setEnabled(enable);
×
228
    m_endColorButton->setEnabled(enable);
×
229
    m_presetCombo->setEnabled(enable);
×
230

231
    foreach(QWidget *ctlBtn, m_controls.keys())
×
232
        ctlBtn->setEnabled(enable);
×
233

234
    // Update buttons state
235
    if (enable)
×
236
        slotUpdate();
×
237
}
×
238

239
void VCMatrix::slotSetSliderValue(int value)
×
240
{
241
    m_slider->setValue(value);
×
242
    slotSliderMoved(value);
×
243
}
×
244

245
void VCMatrix::slotSliderMoved(int value)
×
246
{
247
    Function* function = m_doc->function(m_matrixID);
×
248
    if (function == NULL || mode() == Doc::Design)
×
249
        return;
×
250

251
    if (m_sliderExternalMovement)
×
252
        return;
×
253

254
    if (value == 0)
×
255
    {
256
        // Make sure we ignore the fade out time
257
        adjustFunctionIntensity(function, 0);
×
258
        if (function->stopped() == false)
×
259
        {
260
            function->stop(functionParent());
×
261
            resetIntensityOverrideAttribute();
×
262
        }
263
    }
264
    else
265
    {
266
        qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
267
        emit functionStarting(m_matrixID, pIntensity);
×
268
        adjustFunctionIntensity(function, pIntensity * intensity());
×
269
        if (function->stopped() == true)
×
270
        {
271
            // TODO once #758 is fixed: function started by a fader -> override fade in time
272
            function->start(m_doc->masterTimer(), functionParent());
×
273
        }
274
    }
275

276
    emit sliderValueChanged(value);
×
277
}
278

279
int VCMatrix::sliderValue()
×
280
{
281
    return m_slider->value();
×
282
}
283

284
void VCMatrix::slotSetStartColor(QColor color)
×
285
{
286
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
287
    if (matrix == NULL)
×
288
        return;
×
289

290
    if (matrix->startColor() != color)
×
291
    {
292
        matrix->setStartColor(color);
×
293
        emit startColorChanged();
×
294
    }
295
}
296

297
QColor VCMatrix::startColor()
×
298
{
299
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
300
    if (matrix == NULL)
×
301
        return QColor();
×
302

303
    return matrix->startColor();
×
304
}
305

306
void VCMatrix::slotStartColorChanged(QRgb color)
×
307
{
308
    QColor col(color);
×
309
    slotSetStartColor(col);
×
310
    QPixmap px(42, 42);
×
311
    px.fill(col);
×
312
    m_startColorButton->setIcon(px);
×
313

314
    RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
315
    if (matrix == NULL || mode() == Doc::Design)
×
316
        return;
×
317

318
    matrix->setStartColor(col);
×
319
    if (instantChanges() == true)
×
320
        matrix->updateColorDelta();
×
321
}
322

323
void VCMatrix::slotSetEndColor(QColor color)
×
324
{
325
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
326
    if (matrix == NULL)
×
327
        return;
×
328

329
    if (matrix->endColor() != color)
×
330
    {
331
        matrix->setEndColor(color);
×
332
        emit endColorChanged();
×
333
    }
334
}
335

336
QColor VCMatrix::endColor()
×
337
{
338
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
339
    if (matrix == NULL)
×
340
        return QColor();
×
341

342
    return matrix->endColor();
×
343
}
344

345
void VCMatrix::slotEndColorChanged(QRgb color)
×
346
{
347
    QColor col(color);
×
348
    slotSetEndColor(col);
×
349
    QPixmap px(42, 42);
×
350
    px.fill(col);
×
351
    m_endColorButton->setIcon(px);
×
352

353
    RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
354
    if (matrix == NULL || mode() == Doc::Design)
×
355
        return;
×
356

357
    matrix->setEndColor(col);
×
358
    if (instantChanges() == true)
×
359
        matrix->updateColorDelta();
×
360
}
361

362
void VCMatrix::slotSetAnimationValue(QString name)
×
363
{
364
    m_presetCombo->setCurrentText(name);
×
365
    slotAnimationChanged(name);
×
366
}
×
367

368
void VCMatrix::slotAnimationChanged(QString name)
×
369
{
370
    emit animationValueChanged(name);
×
371
    RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
372
    if (matrix == NULL || mode() == Doc::Design)
×
373
        return;
×
374

375
    RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, name);
×
376
    matrix->setAlgorithm(algo);
×
377
    if (instantChanges() == true)
×
378
        matrix->updateColorDelta();
×
379
}
380

381
QString VCMatrix::animationValue()
×
382
{
383
    return m_presetCombo->currentText();
×
384
}
385

386
void VCMatrix::setVisibilityMask(quint32 mask)
×
387
{
388
    if (mask & ShowSlider) m_slider->show();
×
389
    else m_slider->hide();
×
390

391
    if (mask & ShowLabel) m_label->show();
×
392
    else m_label->hide();
×
393

394
    if (mask & ShowStartColorButton) m_startColorButton->show();
×
395
    else m_startColorButton->hide();
×
396

397
    if (mask & ShowEndColorButton) m_endColorButton->show();
×
398
    else m_endColorButton->hide();
×
399

400
    if (mask & ShowPresetCombo) m_presetCombo->show();
×
401
    else m_presetCombo->hide();
×
402

403
    m_visibilityMask = mask;
×
404
}
×
405

406
quint32 VCMatrix::visibilityMask() const
×
407
{
408
    return m_visibilityMask;
×
409
}
410

411
quint32 VCMatrix::defaultVisibilityMask()
×
412
{
413
    return ShowSlider
414
        | ShowLabel
415
        | ShowStartColorButton
416
        | ShowEndColorButton
417
        | ShowPresetCombo
×
418
        ;
419
}
420

421
/*********************************************************************
422
 * Properties
423
 *********************************************************************/
424

425
void VCMatrix::editProperties()
×
426
{
427
    VCMatrixProperties prop(this, m_doc);
×
428
    if (prop.exec() == QDialog::Accepted)
×
429
        m_doc->setModified();
×
430
}
×
431

432
/*************************************************************************
433
 * VCWidget-inherited
434
 *************************************************************************/
435

436
void VCMatrix::adjustIntensity(qreal val)
×
437
{
438
    VCWidget::adjustIntensity(val);
×
439
    this->slotSliderMoved(this->m_slider->value());
×
440
}
×
441

442
/*********************************************************************
443
 * Function attachment
444
 *********************************************************************/
445

446
void VCMatrix::setFunction(quint32 id)
×
447
{
448
    Function *old = m_doc->function(m_matrixID);
×
449
    if (old != NULL)
×
450
    {
451
        disconnect(old, SIGNAL(stopped(quint32)),
×
452
                this, SLOT(slotFunctionStopped()));
453
        disconnect(old, SIGNAL(changed(quint32)),
×
454
                this, SLOT(slotFunctionChanged()));
455
    }
456

457
    RGBMatrix* matrix = qobject_cast<RGBMatrix*> (m_doc->function(id));
×
458

459
    if (matrix == NULL)
×
460
        m_matrixID = Function::invalidId();
×
461
    else
462
    {
463
        m_matrixID = id;
×
464
        connect(matrix, SIGNAL(stopped(quint32)),
×
465
                this, SLOT(slotFunctionStopped()));
466
        connect(matrix, SIGNAL(changed(quint32)),
×
467
                this, SLOT(slotFunctionChanged()));
468
    }
469

470
    slotUpdate();
×
471
}
×
472

473
quint32 VCMatrix::function() const
×
474
{
475
    return m_matrixID;
×
476
}
477

478
void VCMatrix::notifyFunctionStarting(quint32 fid, qreal functionIntensity)
×
479
{
480
    if (mode() == Doc::Design)
×
481
        return;
×
482

483
    if (fid == m_matrixID)
×
484
        return;
×
485

486
    int value = SCALE(1.0 - functionIntensity,
×
487
            0, 1.0,
488
            m_slider->minimum(), m_slider->maximum());
489
    if (m_slider->value() > value)
×
490
    {
491
        m_sliderExternalMovement = true;
×
492
        m_slider->setValue(value);
×
493
        m_sliderExternalMovement = false;
×
494

495
        Function* function = m_doc->function(m_matrixID);
×
496
        if (function != NULL)
×
497
        {
498
            qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
499
            adjustFunctionIntensity(function, pIntensity * intensity());
×
500
            if (value == 0 && !function->stopped())
×
501
            {
502
                function->stop(functionParent());
×
503
                resetIntensityOverrideAttribute();
×
504
            }
505
        }
506
    }
507
}
508

509
void VCMatrix::slotFunctionStopped()
×
510
{
511
    m_slider->blockSignals(true);
×
512
    m_slider->setValue(0);
×
513
    resetIntensityOverrideAttribute();
×
514
    m_slider->blockSignals(false);
×
515
}
×
516

517
void VCMatrix::slotFunctionChanged()
×
518
{
519
    m_updateTimer->start(UPDATE_TIMEOUT);
×
520
}
×
521

522
void VCMatrix::slotUpdate()
×
523
{
524
    if (m_matrixID == Function::invalidId())
×
525
        return;
×
526

NEW
527
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
528
    if (matrix == NULL)
×
529
        return;
×
530

531
    QColor startColor = matrix->startColor();
×
532
    QColor endColor = matrix->endColor();
×
533
    QString algorithmName;
×
534
    RGBAlgorithm::Type algorithmType = RGBAlgorithm::Plain;
×
535
    QHash<QString, QString> algorithmProperties;
×
536
    QString algorithmText;
×
537

538
    {
539
        QMutexLocker(&matrix->algorithmMutex());
×
540

NEW
541
        RGBAlgorithm *algo = matrix->algorithm();
×
542
        if (algo != NULL)
×
543
        {
544
            algorithmName = algo->name();
×
545
            algorithmType = algo->type();
×
546
            if (algorithmType == RGBAlgorithm::Script)
×
547
            {
548
                algorithmProperties = reinterpret_cast<RGBScript*>(algo)->propertiesAsStrings();
×
549
            }
550
            else if (algorithmType == RGBAlgorithm::Text)
×
551
            {
552
                algorithmText = reinterpret_cast<RGBText*>(algo)->text();
×
553
            }
554
        }
555
    }
556

557
    // Start / End color buttons
558
    QPixmap px(42, 42);
×
559
    px.fill(startColor);
×
560
    m_startColorButton->setIcon(px);
×
561
    slotSetStartColor(startColor);
×
562

NEW
563
    px.fill(endColor == QColor() ? Qt::transparent : endColor);
×
564
    m_endColorButton->setIcon(px);
×
565
    slotSetEndColor(endColor);
×
566

567
    // Algo combo box
568
    if (algorithmName != QString())
×
569
    {
570
        m_presetCombo->blockSignals(true);
×
571
        m_presetCombo->setCurrentText(algorithmName);
×
572
        m_presetCombo->blockSignals(false);
×
573
    }
574

575
    // Custom Buttons
576
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
577
            it != m_controls.end(); ++it)
×
578
    {
NEW
579
        QWidget *widget = it.key();
×
NEW
580
        VCMatrixControl *control = it.value();
×
581

582
        if (control->m_type == VCMatrixControl::StartColorKnob)
×
583
        {
NEW
584
            KnobWidget *knob = reinterpret_cast<KnobWidget*>(widget);
×
NEW
585
            int val = control->rgbToValue(startColor.rgb());
×
NEW
586
            if (knob->value() != val)
×
587
            {
NEW
588
                knob->blockSignals(true);
×
NEW
589
                knob->setValue(val);
×
NEW
590
                emit matrixControlKnobValueChanged(control->m_id, val);
×
NEW
591
                knob->blockSignals(false);
×
592
            }
593
        }
594
        else if (control->m_type == VCMatrixControl::EndColorKnob)
×
595
        {
NEW
596
            KnobWidget *knob = reinterpret_cast<KnobWidget*>(widget);
×
NEW
597
            int val = control->rgbToValue(endColor.rgb());
×
NEW
598
            if (knob->value() != val)
×
599
            {
NEW
600
                knob->blockSignals(true);
×
NEW
601
                knob->setValue(val);
×
NEW
602
                emit matrixControlKnobValueChanged(control->m_id, val);
×
NEW
603
                knob->blockSignals(false);
×
604
            }
605
        }
606
        else if (control->m_type == VCMatrixControl::StartColor)
×
607
        {
NEW
608
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
609
            button->setDown(startColor == control->m_color);
×
610
        }
611
        else if (control->m_type == VCMatrixControl::EndColor)
×
612
        {
NEW
613
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
614
            button->setDown(endColor == control->m_color);
×
615
        }
616
        else if (control->m_type == VCMatrixControl::Animation)
×
617
        {
618
            bool on = false;
×
NEW
619
            if (algorithmType == RGBAlgorithm::Script &&
×
NEW
620
                algorithmName == control->m_resource)
×
621
            {
NEW
622
                on = true;
×
NEW
623
                for (QHash<QString, QString>::const_iterator it = control->m_properties.begin();
×
NEW
624
                        it != control->m_properties.end(); ++it)
×
625
                {
NEW
626
                    if (algorithmProperties.value(it.key(), QString()) != it.value())
×
NEW
627
                        on = false;
×
628
                }
629
            }
630

NEW
631
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
UNCOV
632
            button->setDown(on);
×
633
        }
634
        else if (control->m_type == VCMatrixControl::Text)
×
635
        {
636
            bool on = false;
×
NEW
637
            if (algorithmType == RGBAlgorithm::Text &&
×
NEW
638
                algorithmText == control->m_resource)
×
639
            {
NEW
640
                on = true;
×
641
            }
642

NEW
643
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
UNCOV
644
            button->setDown(on);
×
645
        }
646
    }
647

648
    updateFeedback();
×
649
}
650

651
FunctionParent VCMatrix::functionParent() const
×
652
{
653
    return FunctionParent(FunctionParent::ManualVCWidget, id());
×
654
}
655

656
/*********************************************************************
657
 * Instant changes apply
658
 *********************************************************************/
659

660
void VCMatrix::setInstantChanges(bool instantly)
×
661
{
662
    m_instantApply = instantly;
×
663
}
×
664

665
bool VCMatrix::instantChanges() const
×
666
{
667
    return m_instantApply;
×
668
}
669

670
/*********************************************************************
671
 * Custom controls
672
 *********************************************************************/
673

674
void VCMatrix::addCustomControl(VCMatrixControl const& control)
×
675
{
676
    QWidget *controlWidget = NULL;
×
677

678
    if (control.m_type == VCMatrixControl::StartColor)
×
679
    {
680
        QPushButton *controlButton = new QPushButton(this);
×
681
        controlWidget = controlButton;
×
682
        controlButton->setStyleSheet(controlBtnSS.arg(control.m_color.name()));
×
683
        controlButton->setFixedWidth(36);
×
684
        controlButton->setFocusPolicy(Qt::TabFocus);
×
685
        controlButton->setText("S");
×
686
    }
687
    else if (control.m_type == VCMatrixControl::EndColor)
×
688
    {
689
        QPushButton *controlButton = new QPushButton(this);
×
690
        controlWidget = controlButton;
×
691
        controlButton->setStyleSheet(controlBtnSS.arg(control.m_color.name()));
×
692
        controlButton->setFixedWidth(36);
×
693
        controlButton->setFocusPolicy(Qt::TabFocus);
×
694
        controlButton->setText("E");
×
695
    }
696
    else if (control.m_type == VCMatrixControl::ResetEndColor)
×
697
    {
698
        QPushButton *controlButton = new QPushButton(this);
×
699
        controlWidget = controlButton;
×
700
        controlButton->setStyleSheet(controlBtnSS.arg("#BBBBBB"));
×
701
        controlButton->setMinimumWidth(36);
×
702
        controlButton->setMaximumWidth(80);
×
703
        controlButton->setFocusPolicy(Qt::TabFocus);
×
704
        QString btnLabel = tr("End Color Reset");
×
705
        controlButton->setToolTip(btnLabel);
×
706
        controlButton->setText(fontMetrics().elidedText(btnLabel, Qt::ElideRight, 72));
×
707
    }
708
    else if (control.m_type == VCMatrixControl::Animation ||
×
709
             control.m_type == VCMatrixControl::Text)
×
710
    {
711
        QPushButton *controlButton = new QPushButton(this);
×
712
        controlWidget = controlButton;
×
713
        controlButton->setStyleSheet(controlBtnSS.arg("#BBBBBB"));
×
714
        controlButton->setMinimumWidth(36);
×
715
        controlButton->setMaximumWidth(80);
×
716
        controlButton->setFocusPolicy(Qt::TabFocus);
×
717
        QString btnLabel = control.m_resource;
×
718
        if (!control.m_properties.isEmpty())
×
719
        {
720
            btnLabel += " (";
×
721
            QHashIterator<QString, QString> it(control.m_properties);
×
722
            while(it.hasNext())
×
723
            {
724
                it.next();
×
725
                btnLabel += it.value();
×
726
                if (it.hasNext())
×
727
                    btnLabel += ",";
×
728
            }
729
            btnLabel += ")";
×
730
        }
731
        controlButton->setToolTip(btnLabel);
×
732
        controlButton->setText(fontMetrics().elidedText(btnLabel, Qt::ElideRight, 72));
×
733
    }
734
    else if (control.m_type == VCMatrixControl::StartColorKnob)
×
735
    {
736
        KnobWidget *controlKnob = new KnobWidget(this);
×
737
        controlWidget = controlKnob;
×
738
        controlKnob->setColor(control.m_color);
×
739
        controlKnob->setFixedWidth(36);
×
740
        controlKnob->setFixedHeight(36);
×
741
        QString knobLabel;
×
742
        if (control.m_color == Qt::red)
×
743
            knobLabel = tr("Start color Red component");
×
744
        else if (control.m_color == Qt::green)
×
745
            knobLabel = tr("Start color Green component");
×
746
        else if (control.m_color == Qt::blue)
×
747
            knobLabel = tr("Start color Blue component");
×
748
        controlKnob->setToolTip(knobLabel);
×
749
    }
750
    else if (control.m_type == VCMatrixControl::EndColorKnob)
×
751
    {
752
        KnobWidget *controlKnob = new KnobWidget(this);
×
753
        controlWidget = controlKnob;
×
754
        controlKnob->setColor(control.m_color.darker(250));
×
755
        controlKnob->setFixedWidth(36);
×
756
        controlKnob->setFixedHeight(36);
×
757
        QString knobLabel;
×
758
        if (control.m_color == Qt::red)
×
759
            knobLabel = tr("End color Red component");
×
760
        else if (control.m_color == Qt::green)
×
761
            knobLabel = tr("End color Green component");
×
762
        else if (control.m_color == Qt::blue)
×
763
            knobLabel = tr("End color Blue component");
×
764
        controlKnob->setToolTip(knobLabel);
×
765
    }
766

767
    Q_ASSERT(controlWidget != NULL);
×
768

769
    if (control.widgetType() == VCMatrixControl::Knob)
×
770
    {
771
        connect(reinterpret_cast<KnobWidget*>(controlWidget), SIGNAL(valueChanged(int)),
×
772
                this, SLOT(slotCustomControlValueChanged()));
773
    }
774
    else
775
    {
776
        connect(reinterpret_cast<QPushButton*>(controlWidget), SIGNAL(clicked()),
×
777
                this, SLOT(slotCustomControlClicked()));
778
    }
779

780

781
    if (mode() == Doc::Design)
×
782
        controlWidget->setEnabled(false);
×
783

784
    VCMatrixControl *c_control = new VCMatrixControl(control);
×
785
    m_controls[controlWidget] = c_control;
×
786
    m_widgets[c_control] = controlWidget;
×
787

788
    m_controlsLayout->addWidget(controlWidget);
×
789

790
    if (m_controls[controlWidget]->m_inputSource != NULL)
×
791
    {
792
        setInputSource(m_controls[controlWidget]->m_inputSource, m_controls[controlWidget]->m_id);
×
793
    }
794

795
    slotFunctionChanged(); // Start update timer
×
796
}
×
797

798
void VCMatrix::resetCustomControls()
×
799
{
800
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
801
            it != m_controls.end(); ++it)
×
802
    {
803
        QWidget* widget = it.key();
×
804
        m_controlsLayout->removeWidget(widget);
×
805
        delete widget;
×
806

807
        VCMatrixControl* control = it.value();
×
808
        if (!control->m_inputSource.isNull())
×
809
            setInputSource(QSharedPointer<QLCInputSource>(), control->m_id);
×
810
        delete control;
×
811
    }
812
    m_controls.clear();
×
813
    m_widgets.clear();
×
814
}
×
815

816
QList<VCMatrixControl *> VCMatrix::customControls() const
×
817
{
818
    QList<VCMatrixControl*> controls = m_controls.values();
×
819
    std::sort(controls.begin(), controls.end(), VCMatrixControl::compare);
×
820
    return controls;
×
821
}
822

823
QWidget *VCMatrix::getWidget(VCMatrixControl* control) const
×
824
{
825
    return m_widgets[control];
×
826
}
827

828
void VCMatrix::slotCustomControlClicked()
×
829
{
830
    QPushButton *btn = qobject_cast<QPushButton*>(sender());
×
831
    VCMatrixControl *control = m_controls[btn];
×
832
    if (control != NULL)
×
833
    {
834
        RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
835
        if (matrix == NULL || mode() == Doc::Design)
×
836
            return;
×
837

838
        if (control->m_type == VCMatrixControl::StartColor)
×
839
        {
840
            matrix->setStartColor(control->m_color);
×
841
            if (instantChanges() == true)
×
842
                matrix->updateColorDelta();
×
843
            btn->setDown(true);
×
844
            emit startColorChanged();
×
845
        }
846
        else if (control->m_type == VCMatrixControl::EndColor)
×
847
        {
848
            matrix->setEndColor(control->m_color);
×
849
            if (instantChanges() == true)
×
850
                matrix->updateColorDelta();
×
851
            btn->setDown(true);
×
852
            emit endColorChanged();
×
853
        }
854
        else if (control->m_type == VCMatrixControl::ResetEndColor)
×
855
        {
856
            matrix->setEndColor(QColor());
×
857
            if (instantChanges() == true)
×
858
                matrix->updateColorDelta();
×
859
            emit endColorChanged();
×
860
        }
861
        else if (control->m_type == VCMatrixControl::Animation)
×
862
        {
863
            RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, control->m_resource);
×
864
            if (!control->m_properties.isEmpty())
×
865
            {
866
                RGBScript *script = static_cast<RGBScript*> (algo);
×
867
                QHashIterator<QString, QString> it(control->m_properties);
×
868
                while(it.hasNext())
×
869
                {
870
                    it.next();
×
871
                    script->setProperty(it.key(), it.value());
×
872
                    matrix->setProperty(it.key(), it.value());
×
873
                }
874
            }
875
            matrix->setAlgorithm(algo);
×
876
            if (instantChanges() == true)
×
877
                matrix->updateColorDelta();
×
878
            btn->setDown(true);
×
879
        }
880
        else if (control->m_type == VCMatrixControl::Text)
×
881
        {
882
            RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, "Text");
×
883
            RGBText* text = static_cast<RGBText*> (algo);
×
884
            text->setText(control->m_resource);
×
885
            matrix->setAlgorithm(algo);
×
886
            if (instantChanges() == true)
×
887
                matrix->updateColorDelta();
×
888
            btn->setDown(true);
×
889
        }
890
    }
891
}
892

893
void VCMatrix::slotCustomControlValueChanged()
×
894
{
895
    KnobWidget *knob = qobject_cast<KnobWidget*>(sender());
×
896
    VCMatrixControl *control = m_controls[knob];
×
897
    if (control != NULL)
×
898
    {
899
        RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
900
        if (matrix == NULL || mode() == Doc::Design)
×
901
            return;
×
902

903
        if (control->m_type == VCMatrixControl::StartColorKnob)
×
904
        {
905
            QRgb color = matrix->startColor().rgb();
×
906
            QRgb knobValueColor = control->valueToRgb(knob->value());
×
907
            color = (color & ~control->m_color.rgb()) | (knobValueColor & control->m_color.rgb());
×
908

909
            matrix->setStartColor(color);
×
910
            if (instantChanges() == true)
×
911
                matrix->updateColorDelta();
×
NEW
912
            emit startColorChanged();
×
913
        }
914
        else if (control->m_type == VCMatrixControl::EndColorKnob)
×
915
        {
916
            QRgb color = matrix->endColor().rgb();
×
917
            QRgb knobValueColor = control->valueToRgb(knob->value());
×
918
            color = (color & ~control->m_color.rgb()) | (knobValueColor & control->m_color.rgb());
×
919

920
            matrix->setEndColor(color);
×
921
            if (instantChanges() == true)
×
922
                matrix->updateColorDelta();
×
NEW
923
            emit endColorChanged();
×
924
        }
925
        else
926
        {
927
            // We are not supposed to be here
928
            Q_ASSERT(false);
×
929
        }
930
        emit matrixControlKnobValueChanged(control->m_id, knob->value());
×
931
    }
932
}
933

934
void VCMatrix::slotMatrixControlKnobValueChanged(int controlID, int value)
×
935
{
936
    QList<VCMatrixControl *> customControls = this->customControls();
×
937
    for (int i = 0; i < customControls.length(); i++)
×
938
    {
939
        if (customControls[i]->m_id == controlID)
×
940
        {
941
            if (customControls[i]->m_type == VCMatrixControl::StartColorKnob || customControls[i]->m_type == VCMatrixControl::EndColorKnob)
×
942
            {
943
                KnobWidget *knob = qobject_cast<KnobWidget*>(this->getWidget(customControls[i]));
×
944
                knob->blockSignals(true);
×
945
                knob->setValue(value);
×
946
                knob->blockSignals(false);
×
947
                break;
×
948
            }
949
        }
950
    }
951
}
×
952

953
void VCMatrix::slotMatrixControlPushButtonClicked(int controlID)
×
954
{
955
    QList<VCMatrixControl *> customControls = this->customControls();
×
956
    for (int i = 0; i < customControls.length(); i++)
×
957
    {
958
        if (customControls[i]->m_id == controlID)
×
959
        {
960
            QPushButton *btn = qobject_cast<QPushButton*>(this->getWidget(customControls[i]));
×
961
            btn->click();
×
962
            break;
×
963
        }
964
    }
965
}
×
966

967
void VCMatrix::slotModeChanged(Doc::Mode mode)
×
968
{
969
    if (mode == Doc::Operate)
×
970
        enableWidgetUI(true);
×
971
    else
972
        enableWidgetUI(false);
×
973

974
    VCWidget::slotModeChanged(mode);
×
975
}
×
976

977
/*********************************************************************
978
 * External input
979
 *********************************************************************/
980

981
void VCMatrix::slotKeyPressed(const QKeySequence &keySequence)
×
982
{
983
    if (acceptsInput() == false)
×
984
        return;
×
985

986
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
987
            it != m_controls.end(); ++it)
×
988
    {
989
        VCMatrixControl *control = it.value();
×
990
        if (control->m_keySequence == keySequence &&
×
991
                control->widgetType() == VCMatrixControl::Button) // Only for buttons
×
992
        {
993
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
994
            button->click();
×
995
        }
996
    }
997
}
998

999
void VCMatrix::updateFeedback()
×
1000
{
1001
    sendFeedback(m_slider->value());
×
1002

1003
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
1004
            it != m_controls.end(); ++it)
×
1005
    {
1006
        VCMatrixControl *control = it.value();
×
1007
        if (control->m_inputSource != NULL)
×
1008
        {
1009
            if (control->widgetType() == VCMatrixControl::Knob)
×
1010
            {
1011
                KnobWidget* knob = reinterpret_cast<KnobWidget*>(it.key());
×
1012
                sendFeedback(knob->value(), control->m_inputSource);
×
1013
            }
1014
            else // if (control->widgetType() == VCMatrixControl::Button)
1015
            {
1016
                QPushButton* button = reinterpret_cast<QPushButton*>(it.key());
×
1017
                sendFeedback(button->isDown() ?
×
1018
                                 control->m_inputSource->upperValue() :
×
1019
                                 control->m_inputSource->lowerValue(),
×
1020
                                 control->m_inputSource);
×
1021
            }
1022
        }
1023
    }
1024
}
×
1025

1026
void VCMatrix::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
1027
{
1028
    /* Don't let input data through in design mode or if disabled */
1029
    if (acceptsInput() == false)
×
1030
        return;
×
1031

1032
    quint32 pagedCh = (page() << 16) | channel;
×
1033

1034
    if (checkInputSource(universe, pagedCh, value, sender()))
×
1035
    {
1036
        m_slider->setValue((int) value);
×
1037
        return;
×
1038
    }
1039

1040
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
1041
            it != m_controls.end(); ++it)
×
1042
    {
1043
        VCMatrixControl *control = it.value();
×
1044
        if (control->m_inputSource != NULL &&
×
1045
                control->m_inputSource->universe() == universe &&
×
1046
                control->m_inputSource->channel() == pagedCh)
×
1047
        {
1048
            if (control->widgetType() == VCMatrixControl::Knob)
×
1049
            {
1050
                KnobWidget* knob = reinterpret_cast<KnobWidget*>(it.key());
×
1051
                knob->setValue(value);
×
1052
            }
1053
            else
1054
            {
1055
                QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
1056
                button->click();
×
1057
            }
1058
        }
1059
    }
1060
}
1061

1062
bool VCMatrix::loadXML(QXmlStreamReader &root)
×
1063
{
1064
    QString str;
×
1065

1066
    if (root.name() != KXMLQLCVCMatrix)
×
1067
    {
1068
        qWarning() << Q_FUNC_INFO << "Matrix node not found";
×
1069
        return false;
×
1070
    }
1071

1072
    /* Widget commons */
1073
    loadXMLCommon(root);
×
1074

1075
    // Sorted list for new controls
1076
    QList<VCMatrixControl> newControls;
×
1077

1078
    /* Children */
1079
    while (root.readNextStartElement())
×
1080
    {
1081
        if (root.name() == KXMLQLCWindowState)
×
1082
        {
1083
            bool visible = false;
×
1084
            int x = 0, y = 0, w = 0, h = 0;
×
1085
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
1086
            setGeometry(x, y, w, h);
×
1087
        }
1088
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
1089
        {
1090
            loadXMLAppearance(root);
×
1091
        }
1092
        else if (root.name() == KXMLQLCVCMatrixFunction)
×
1093
        {
1094
            QXmlStreamAttributes attrs = root.attributes();
×
1095
            str = attrs.value(KXMLQLCVCMatrixFunctionID).toString();
×
1096
            setFunction(str.toUInt());
×
1097
            if (attrs.hasAttribute(KXMLQLCVCMatrixInstantApply))
×
1098
                setInstantChanges(true);
×
1099
            root.skipCurrentElement();
×
1100
        }
1101
        else if (root.name() == KXMLQLCVCWidgetInput)
×
1102
        {
1103
            loadXMLInput(root);
×
1104
        }
1105
        else if(root.name() == KXMLQLCVCMatrixControl)
×
1106
        {
1107
            VCMatrixControl control(0xff);
×
1108
            if (control.loadXML(root))
×
1109
                newControls.insert(std::lower_bound(newControls.begin(), newControls.end(), control), control);
×
1110
        }
1111
        else if (root.name() == KXMLQLCVCMatrixVisibilityMask)
×
1112
        {
1113
            setVisibilityMask(root.readElementText().toUInt());
×
1114
        }
1115
        else
1116
        {
1117
            qWarning() << Q_FUNC_INFO << "Unknown VCMatrix tag:" << root.name().toString();
×
1118
            root.skipCurrentElement();
×
1119
        }
1120
    }
1121

1122
    foreach (VCMatrixControl const& control, newControls)
×
1123
        addCustomControl(control);
×
1124

1125
    return true;
×
1126
}
1127

1128
bool VCMatrix::saveXML(QXmlStreamWriter *doc)
×
1129
{
1130
    Q_ASSERT(doc != NULL);
×
1131

1132
    /* VC button entry */
1133
    doc->writeStartElement(KXMLQLCVCMatrix);
×
1134

1135
    saveXMLCommon(doc);
×
1136

1137
    /* Window state */
1138
    saveXMLWindowState(doc);
×
1139

1140
    /* Appearance */
1141
    saveXMLAppearance(doc);
×
1142

1143
    /* Function */
1144
    doc->writeStartElement(KXMLQLCVCMatrixFunction);
×
1145
    doc->writeAttribute(KXMLQLCVCMatrixFunctionID, QString::number(function()));
×
1146

1147
    if (instantChanges() == true)
×
1148
        doc->writeAttribute(KXMLQLCVCMatrixInstantApply, "true");
×
1149
    doc->writeEndElement();
×
1150

1151
    /* Default controls visibility  */
1152
    if (m_visibilityMask != VCMatrix::defaultVisibilityMask())
×
1153
        doc->writeTextElement(KXMLQLCVCMatrixVisibilityMask, QString::number(m_visibilityMask));
×
1154

1155
    /* Slider External input */
1156
    saveXMLInput(doc);
×
1157

1158
    foreach(VCMatrixControl *control, customControls())
×
1159
        control->saveXML(doc);
×
1160

1161
    /* End the <Matrix> tag */
1162
    doc->writeEndElement();
×
1163

1164
    return true;
×
1165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc