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

mcallegari / qlcplus / 8613265809

09 Apr 2024 09:13AM UTC coverage: 32.08% (-0.004%) from 32.084%
8613265809

push

github

mcallegari
Fix build with Qt 6.7

9 of 16 new or added lines in 2 files covered. (56.25%)

5 existing lines in 2 files now uncovered.

15389 of 47971 relevant lines covered (32.08%)

22931.4 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

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
    {
NEW
539
        QMutexLocker locker(&matrix->algorithmMutex());
×
540

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

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
    {
579
        QWidget *widget = it.key();
×
580
        VCMatrixControl *control = it.value();
×
581

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

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

643
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
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();
×
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();
×
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->setValue(value);
×
945
                break;
×
946
            }
947
        }
948
    }
949
}
×
950

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

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

972
    VCWidget::slotModeChanged(mode);
×
973
}
×
974

975
/*********************************************************************
976
 * External input
977
 *********************************************************************/
978

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

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

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

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

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

1030
    quint32 pagedCh = (page() << 16) | channel;
×
1031

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

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

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

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

1070
    /* Widget commons */
1071
    loadXMLCommon(root);
×
1072

1073
    // Sorted list for new controls
1074
    QList<VCMatrixControl> newControls;
×
1075

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

1120
    foreach (VCMatrixControl const& control, newControls)
×
1121
        addCustomControl(control);
×
1122

1123
    return true;
×
1124
}
1125

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

1130
    /* VC button entry */
1131
    doc->writeStartElement(KXMLQLCVCMatrix);
×
1132

1133
    saveXMLCommon(doc);
×
1134

1135
    /* Window state */
1136
    saveXMLWindowState(doc);
×
1137

1138
    /* Appearance */
1139
    saveXMLAppearance(doc);
×
1140

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

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

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

1153
    /* Slider External input */
1154
    saveXMLInput(doc);
×
1155

1156
    foreach (VCMatrixControl *control, customControls())
×
1157
        control->saveXML(doc);
×
1158

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

1162
    return true;
×
1163
}
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