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

mcallegari / qlcplus / 10982433547

22 Sep 2024 03:44PM UTC coverage: 31.991% (-0.004%) from 31.995%
10982433547

push

github

mcallegari
ui: more Qt6 deprecation fixes

0 of 18 new or added lines in 3 files covered. (0.0%)

9 existing lines in 4 files now uncovered.

14032 of 43863 relevant lines covered (31.99%)

27064.29 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));
×
NEW
129
    connect(m_presetCombo, SIGNAL(currentIndexChanged(int)),
×
130
            this, SLOT(slotAnimationChanged(int)));
UNCOV
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
{
NEW
364
    for (int i = 0; i < m_presetCombo->count(); i++)
×
365
    {
NEW
366
        if (name == m_presetCombo->itemText(i))
×
367
        {
NEW
368
            m_presetCombo->setCurrentIndex(i);
×
NEW
369
            slotAnimationChanged(i);
×
NEW
370
            return;
×
371
        }
372
    }
373
}
374

NEW
375
void VCMatrix::slotAnimationChanged(int index)
×
376
{
377
    RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
378
    if (matrix == NULL || mode() == Doc::Design)
×
379
        return;
×
380

NEW
381
    QString pValue = m_presetCombo->itemText(index);
×
NEW
382
    RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, pValue);
×
383
    matrix->setAlgorithm(algo);
×
384
    if (instantChanges() == true)
×
385
        matrix->updateColorDelta();
×
386

NEW
387
    emit animationValueChanged(pValue);
×
388
}
389

390
QString VCMatrix::animationValue()
×
391
{
392
    return m_presetCombo->currentText();
×
393
}
394

395
void VCMatrix::setVisibilityMask(quint32 mask)
×
396
{
397
    if (mask & ShowSlider) m_slider->show();
×
398
    else m_slider->hide();
×
399

400
    if (mask & ShowLabel) m_label->show();
×
401
    else m_label->hide();
×
402

403
    if (mask & ShowStartColorButton) m_startColorButton->show();
×
404
    else m_startColorButton->hide();
×
405

406
    if (mask & ShowEndColorButton) m_endColorButton->show();
×
407
    else m_endColorButton->hide();
×
408

409
    if (mask & ShowPresetCombo) m_presetCombo->show();
×
410
    else m_presetCombo->hide();
×
411

412
    m_visibilityMask = mask;
×
413
}
×
414

415
quint32 VCMatrix::visibilityMask() const
×
416
{
417
    return m_visibilityMask;
×
418
}
419

420
quint32 VCMatrix::defaultVisibilityMask()
×
421
{
422
    return ShowSlider
423
        | ShowLabel
424
        | ShowStartColorButton
425
        | ShowEndColorButton
426
        | ShowPresetCombo
×
427
        ;
428
}
429

430
/*********************************************************************
431
 * Properties
432
 *********************************************************************/
433

434
void VCMatrix::editProperties()
×
435
{
436
    VCMatrixProperties prop(this, m_doc);
×
437
    if (prop.exec() == QDialog::Accepted)
×
438
        m_doc->setModified();
×
439
}
×
440

441
/*************************************************************************
442
 * VCWidget-inherited
443
 *************************************************************************/
444

445
void VCMatrix::adjustIntensity(qreal val)
×
446
{
447
    VCWidget::adjustIntensity(val);
×
448
    this->slotSliderMoved(this->m_slider->value());
×
449
}
×
450

451
/*********************************************************************
452
 * Function attachment
453
 *********************************************************************/
454

455
void VCMatrix::setFunction(quint32 id)
×
456
{
457
    Function *old = m_doc->function(m_matrixID);
×
458
    if (old != NULL)
×
459
    {
460
        disconnect(old, SIGNAL(stopped(quint32)),
×
461
                this, SLOT(slotFunctionStopped()));
462
        disconnect(old, SIGNAL(changed(quint32)),
×
463
                this, SLOT(slotFunctionChanged()));
464
    }
465

466
    RGBMatrix* matrix = qobject_cast<RGBMatrix*> (m_doc->function(id));
×
467

468
    if (matrix == NULL)
×
469
        m_matrixID = Function::invalidId();
×
470
    else
471
    {
472
        m_matrixID = id;
×
473
        connect(matrix, SIGNAL(stopped(quint32)),
×
474
                this, SLOT(slotFunctionStopped()));
475
        connect(matrix, SIGNAL(changed(quint32)),
×
476
                this, SLOT(slotFunctionChanged()));
477
    }
478

479
    slotUpdate();
×
480
}
×
481

482
quint32 VCMatrix::function() const
×
483
{
484
    return m_matrixID;
×
485
}
486

487
void VCMatrix::notifyFunctionStarting(quint32 fid, qreal functionIntensity)
×
488
{
489
    if (mode() == Doc::Design)
×
490
        return;
491

492
    if (fid == m_matrixID)
×
493
        return;
494

495
    int value = SCALE(1.0 - functionIntensity,
×
496
            0, 1.0,
497
            m_slider->minimum(), m_slider->maximum());
498
    if (m_slider->value() > value)
×
499
    {
500
        m_sliderExternalMovement = true;
×
501
        m_slider->setValue(value);
×
502
        m_sliderExternalMovement = false;
×
503

504
        Function* function = m_doc->function(m_matrixID);
×
505
        if (function != NULL)
×
506
        {
507
            qreal pIntensity = qreal(value) / qreal(UCHAR_MAX);
×
508
            adjustFunctionIntensity(function, pIntensity * intensity());
×
509
            if (value == 0 && !function->stopped())
×
510
            {
511
                function->stop(functionParent());
×
512
                resetIntensityOverrideAttribute();
×
513
            }
514
        }
515
    }
516
}
517

518
void VCMatrix::slotFunctionStopped()
×
519
{
520
    m_slider->blockSignals(true);
×
521
    m_slider->setValue(0);
×
522
    resetIntensityOverrideAttribute();
×
523
    m_slider->blockSignals(false);
×
524
}
×
525

526
void VCMatrix::slotFunctionChanged()
×
527
{
528
    m_updateTimer->start(UPDATE_TIMEOUT);
×
529
}
×
530

531
void VCMatrix::slotUpdate()
×
532
{
533
    if (m_matrixID == Function::invalidId())
×
534
        return;
×
535

536
    RGBMatrix *matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
537
    if (matrix == NULL)
×
538
        return;
539

540
    QColor startColor = matrix->startColor();
×
541
    QColor endColor = matrix->endColor();
×
542
    QString algorithmName;
×
543
    RGBAlgorithm::Type algorithmType = RGBAlgorithm::Plain;
544
    QHash<QString, QString> algorithmProperties;
×
545
    QString algorithmText;
×
546

547
    {
548
        QMutexLocker locker(&matrix->algorithmMutex());
×
549

550
        RGBAlgorithm *algo = matrix->algorithm();
×
551
        if (algo != NULL)
×
552
        {
553
            algorithmName = algo->name();
×
554
            algorithmType = algo->type();
×
555
            if (algorithmType == RGBAlgorithm::Script)
×
556
            {
557
                algorithmProperties = reinterpret_cast<RGBScript*>(algo)->propertiesAsStrings();
×
558
            }
559
            else if (algorithmType == RGBAlgorithm::Text)
×
560
            {
561
                algorithmText = reinterpret_cast<RGBText*>(algo)->text();
×
562
            }
563
        }
564
    }
565

566
    // Start / End color buttons
567
    QPixmap px(42, 42);
×
568
    px.fill(startColor);
×
569
    m_startColorButton->setIcon(px);
×
570
    slotSetStartColor(startColor);
×
571

572
    px.fill(endColor == QColor() ? Qt::transparent : endColor);
×
573
    m_endColorButton->setIcon(px);
×
574
    slotSetEndColor(endColor);
×
575

576
    // Algo combo box
577
    if (algorithmName != QString())
×
578
    {
579
        m_presetCombo->blockSignals(true);
×
580
        m_presetCombo->setCurrentText(algorithmName);
×
581
        m_presetCombo->blockSignals(false);
×
582
    }
583

584
    // Custom Buttons
585
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
586
            it != m_controls.end(); ++it)
×
587
    {
588
        QWidget *widget = it.key();
×
589
        VCMatrixControl *control = it.value();
×
590

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

640
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
641
            button->setDown(on);
×
642
        }
643
        else if (control->m_type == VCMatrixControl::Text)
×
644
        {
645
            bool on = false;
646
            if (algorithmType == RGBAlgorithm::Text &&
×
647
                algorithmText == control->m_resource)
×
648
            {
649
                on = true;
650
            }
651

652
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
653
            button->setDown(on);
×
654
        }
655
    }
656

657
    updateFeedback();
×
658
}
659

660
FunctionParent VCMatrix::functionParent() const
×
661
{
662
    return FunctionParent(FunctionParent::ManualVCWidget, id());
×
663
}
664

665
/*********************************************************************
666
 * Instant changes apply
667
 *********************************************************************/
668

669
void VCMatrix::setInstantChanges(bool instantly)
×
670
{
671
    m_instantApply = instantly;
×
672
}
×
673

674
bool VCMatrix::instantChanges() const
×
675
{
676
    return m_instantApply;
×
677
}
678

679
/*********************************************************************
680
 * Custom controls
681
 *********************************************************************/
682

683
void VCMatrix::addCustomControl(VCMatrixControl const& control)
×
684
{
685
    QWidget *controlWidget = NULL;
×
686

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

776
    Q_ASSERT(controlWidget != NULL);
777

778
    if (control.widgetType() == VCMatrixControl::Knob)
×
779
    {
780
        connect(reinterpret_cast<KnobWidget*>(controlWidget), SIGNAL(valueChanged(int)),
×
781
                this, SLOT(slotCustomControlValueChanged()));
782
    }
783
    else
784
    {
785
        connect(reinterpret_cast<QPushButton*>(controlWidget), SIGNAL(clicked()),
×
786
                this, SLOT(slotCustomControlClicked()));
787
    }
788

789

790
    if (mode() == Doc::Design)
×
791
        controlWidget->setEnabled(false);
×
792

793
    VCMatrixControl *c_control = new VCMatrixControl(control);
×
794
    m_controls[controlWidget] = c_control;
×
795
    m_widgets[c_control] = controlWidget;
×
796

797
    m_controlsLayout->addWidget(controlWidget);
×
798

799
    if (m_controls[controlWidget]->m_inputSource != NULL)
×
800
    {
801
        setInputSource(m_controls[controlWidget]->m_inputSource, m_controls[controlWidget]->m_id);
×
802
    }
803

804
    slotFunctionChanged(); // Start update timer
×
805
}
×
806

807
void VCMatrix::resetCustomControls()
×
808
{
809
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
810
            it != m_controls.end(); ++it)
×
811
    {
812
        QWidget* widget = it.key();
×
813
        m_controlsLayout->removeWidget(widget);
×
814
        delete widget;
×
815

816
        VCMatrixControl* control = it.value();
×
817
        if (!control->m_inputSource.isNull())
×
818
            setInputSource(QSharedPointer<QLCInputSource>(), control->m_id);
×
819
        delete control;
×
820
    }
821
    m_controls.clear();
×
822
    m_widgets.clear();
×
823
}
×
824

825
QList<VCMatrixControl *> VCMatrix::customControls() const
×
826
{
827
    QList<VCMatrixControl*> controls = m_controls.values();
×
828
    std::sort(controls.begin(), controls.end(), VCMatrixControl::compare);
829
    return controls;
×
830
}
831

832
QMap<quint32,QString> VCMatrix::customControlsMap() const
×
833
{
834
    QMap<quint32,QString> map;
835

836
    foreach (VCMatrixControl *control, m_controls.values())
×
837
        map.insert(control->m_id, VCMatrixControl::typeToString(control->m_type));
×
838

839
    return map;
×
840
}
841

842
QWidget *VCMatrix::getWidget(VCMatrixControl* control) const
×
843
{
844
    return m_widgets[control];
×
845
}
846

847
void VCMatrix::slotCustomControlClicked()
×
848
{
849
    QPushButton *btn = qobject_cast<QPushButton*>(sender());
×
850
    VCMatrixControl *control = m_controls[btn];
×
851
    if (control != NULL)
×
852
    {
853
        RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
854
        if (matrix == NULL || mode() == Doc::Design)
×
855
            return;
×
856

857
        if (control->m_type == VCMatrixControl::StartColor)
×
858
        {
859
            matrix->setStartColor(control->m_color);
×
860
            if (instantChanges() == true)
×
861
                matrix->updateColorDelta();
×
862
            btn->setDown(true);
×
863
            emit startColorChanged();
×
864
        }
865
        else if (control->m_type == VCMatrixControl::EndColor)
×
866
        {
867
            matrix->setEndColor(control->m_color);
×
868
            if (instantChanges() == true)
×
869
                matrix->updateColorDelta();
×
870
            btn->setDown(true);
×
871
            emit endColorChanged();
×
872
        }
873
        else if (control->m_type == VCMatrixControl::ResetEndColor)
×
874
        {
875
            matrix->setEndColor(QColor());
×
876
            if (instantChanges() == true)
×
877
                matrix->updateColorDelta();
×
878
            emit endColorChanged();
×
879
        }
880
        else if (control->m_type == VCMatrixControl::Animation)
×
881
        {
882
            RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, control->m_resource);
×
883
            if (!control->m_properties.isEmpty())
×
884
            {
885
                RGBScript *script = static_cast<RGBScript*> (algo);
886
                QHashIterator<QString, QString> it(control->m_properties);
×
887
                while (it.hasNext())
×
888
                {
889
                    it.next();
890
                    script->setProperty(it.key(), it.value());
×
891
                    matrix->setProperty(it.key(), it.value());
×
892
                }
893
            }
894
            matrix->setAlgorithm(algo);
×
895
            if (instantChanges() == true)
×
896
                matrix->updateColorDelta();
×
897
            btn->setDown(true);
×
898
        }
899
        else if (control->m_type == VCMatrixControl::Text)
×
900
        {
901
            RGBAlgorithm* algo = RGBAlgorithm::algorithm(m_doc, "Text");
×
902
            RGBText* text = static_cast<RGBText*> (algo);
903
            text->setText(control->m_resource);
×
904
            matrix->setAlgorithm(algo);
×
905
            if (instantChanges() == true)
×
906
                matrix->updateColorDelta();
×
907
            btn->setDown(true);
×
908
        }
909
    }
910
}
911

912
void VCMatrix::slotCustomControlValueChanged()
×
913
{
914
    KnobWidget *knob = qobject_cast<KnobWidget*>(sender());
×
915
    VCMatrixControl *control = m_controls[knob];
×
916
    if (control != NULL)
×
917
    {
918
        RGBMatrix* matrix = qobject_cast<RGBMatrix*>(m_doc->function(m_matrixID));
×
919
        if (matrix == NULL || mode() == Doc::Design)
×
920
            return;
×
921

922
        if (control->m_type == VCMatrixControl::StartColorKnob)
×
923
        {
924
            QRgb color = matrix->startColor().rgb();
×
925
            QRgb knobValueColor = control->valueToRgb(knob->value());
×
926
            color = (color & ~control->m_color.rgb()) | (knobValueColor & control->m_color.rgb());
×
927

928
            matrix->setStartColor(color);
×
929
            if (instantChanges() == true)
×
930
                matrix->updateColorDelta();
×
931
            emit startColorChanged();
×
932
        }
933
        else if (control->m_type == VCMatrixControl::EndColorKnob)
×
934
        {
935
            QRgb color = matrix->endColor().rgb();
×
936
            QRgb knobValueColor = control->valueToRgb(knob->value());
×
937
            color = (color & ~control->m_color.rgb()) | (knobValueColor & control->m_color.rgb());
×
938

939
            matrix->setEndColor(color);
×
940
            if (instantChanges() == true)
×
941
                matrix->updateColorDelta();
×
942
            emit endColorChanged();
×
943
        }
944
        else
945
        {
946
            // We are not supposed to be here
947
            Q_ASSERT(false);
948
        }
949
        emit matrixControlKnobValueChanged(control->m_id, knob->value());
×
950
    }
951
}
952

953
void VCMatrix::slotMatrixControlKnobValueChanged(int controlID, int value)
×
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
            if (customControls[i]->m_type == VCMatrixControl::StartColorKnob || customControls[i]->m_type == VCMatrixControl::EndColorKnob)
×
961
            {
962
                KnobWidget *knob = qobject_cast<KnobWidget*>(this->getWidget(customControls[i]));
×
963
                knob->setValue(value);
×
964
                break;
965
            }
966
        }
967
    }
968
}
×
969

970
void VCMatrix::slotMatrixControlPushButtonClicked(int controlID)
×
971
{
972
    QList<VCMatrixControl *> customControls = this->customControls();
×
973
    for (int i = 0; i < customControls.length(); i++)
×
974
    {
975
        if (customControls[i]->m_id == controlID)
×
976
        {
977
            QPushButton *btn = qobject_cast<QPushButton*>(this->getWidget(customControls[i]));
×
978
            btn->click();
×
979
            break;
980
        }
981
    }
982
}
×
983

984
void VCMatrix::slotModeChanged(Doc::Mode mode)
×
985
{
986
    if (mode == Doc::Operate)
×
987
        enableWidgetUI(true);
×
988
    else
989
        enableWidgetUI(false);
×
990

991
    VCWidget::slotModeChanged(mode);
×
992
}
×
993

994
/*********************************************************************
995
 * External input
996
 *********************************************************************/
997

998
void VCMatrix::slotKeyPressed(const QKeySequence &keySequence)
×
999
{
1000
    if (acceptsInput() == false)
×
1001
        return;
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_keySequence == keySequence &&
×
1008
                control->widgetType() == VCMatrixControl::Button) // Only for buttons
×
1009
        {
1010
            QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
1011
            button->click();
×
1012
        }
1013
    }
1014
}
1015

1016
void VCMatrix::updateFeedback()
×
1017
{
1018
    sendFeedback(m_slider->value());
×
1019

1020
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
1021
            it != m_controls.end(); ++it)
×
1022
    {
1023
        VCMatrixControl *control = it.value();
×
1024
        if (control->m_inputSource != NULL)
×
1025
        {
1026
            if (control->widgetType() == VCMatrixControl::Knob)
×
1027
            {
1028
                KnobWidget* knob = reinterpret_cast<KnobWidget*>(it.key());
×
1029
                sendFeedback(knob->value(), control->m_inputSource);
×
1030
            }
1031
            else // if (control->widgetType() == VCMatrixControl::Button)
1032
            {
1033
                QPushButton* button = reinterpret_cast<QPushButton*>(it.key());
×
1034
                sendFeedback(button->isDown() ?
×
1035
                                 control->m_inputSource->feedbackValue(QLCInputFeedback::UpperValue) :
×
1036
                                 control->m_inputSource->feedbackValue(QLCInputFeedback::LowerValue),
×
1037
                                 control->m_inputSource);
1038
            }
1039
        }
1040
    }
1041
}
×
1042

1043
void VCMatrix::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
1044
{
1045
    /* Don't let input data through in design mode or if disabled */
1046
    if (acceptsInput() == false)
×
1047
        return;
1048

1049
    quint32 pagedCh = (page() << 16) | channel;
×
1050

1051
    if (checkInputSource(universe, pagedCh, value, sender()))
×
1052
    {
1053
        m_slider->setValue((int) value);
×
1054
        return;
×
1055
    }
1056

1057
    for (QHash<QWidget *, VCMatrixControl *>::iterator it = m_controls.begin();
×
1058
            it != m_controls.end(); ++it)
×
1059
    {
1060
        VCMatrixControl *control = it.value();
×
1061
        if (control->m_inputSource != NULL &&
×
1062
                control->m_inputSource->universe() == universe &&
×
1063
                control->m_inputSource->channel() == pagedCh)
×
1064
        {
1065
            if (control->widgetType() == VCMatrixControl::Knob)
×
1066
            {
1067
                KnobWidget* knob = reinterpret_cast<KnobWidget*>(it.key());
×
1068
                knob->setValue(value);
×
1069
            }
1070
            else
1071
            {
1072
                QPushButton *button = reinterpret_cast<QPushButton*>(it.key());
×
1073
                button->click();
×
1074
            }
1075
        }
1076
    }
1077
}
1078

1079
bool VCMatrix::loadXML(QXmlStreamReader &root)
×
1080
{
1081
    QString str;
×
1082

1083
    if (root.name() != KXMLQLCVCMatrix)
×
1084
    {
1085
        qWarning() << Q_FUNC_INFO << "Matrix node not found";
×
1086
        return false;
×
1087
    }
1088

1089
    /* Widget commons */
1090
    loadXMLCommon(root);
×
1091

1092
    // Sorted list for new controls
1093
    QList<VCMatrixControl> newControls;
×
1094

1095
    /* Children */
1096
    while (root.readNextStartElement())
×
1097
    {
1098
        if (root.name() == KXMLQLCWindowState)
×
1099
        {
1100
            bool visible = false;
×
1101
            int x = 0, y = 0, w = 0, h = 0;
×
1102
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
×
1103
            setGeometry(x, y, w, h);
×
1104
        }
1105
        else if (root.name() == KXMLQLCVCWidgetAppearance)
×
1106
        {
1107
            loadXMLAppearance(root);
×
1108
        }
1109
        else if (root.name() == KXMLQLCVCMatrixFunction)
×
1110
        {
1111
            QXmlStreamAttributes attrs = root.attributes();
×
1112
            str = attrs.value(KXMLQLCVCMatrixFunctionID).toString();
×
1113
            setFunction(str.toUInt());
×
1114
            if (attrs.hasAttribute(KXMLQLCVCMatrixInstantApply))
×
1115
                setInstantChanges(true);
×
1116
            root.skipCurrentElement();
×
1117
        }
1118
        else if (root.name() == KXMLQLCVCWidgetInput)
×
1119
        {
1120
            loadXMLInput(root);
×
1121
        }
1122
        else if (root.name() == KXMLQLCVCMatrixControl)
×
1123
        {
1124
            VCMatrixControl control(0xff);
×
1125
            if (control.loadXML(root))
×
1126
                newControls.insert(std::lower_bound(newControls.begin(), newControls.end(), control), control);
×
1127
        }
1128
        else if (root.name() == KXMLQLCVCMatrixVisibilityMask)
×
1129
        {
1130
            setVisibilityMask(root.readElementText().toUInt());
×
1131
        }
1132
        else
1133
        {
1134
            qWarning() << Q_FUNC_INFO << "Unknown VCMatrix tag:" << root.name().toString();
×
1135
            root.skipCurrentElement();
×
1136
        }
1137
    }
1138

1139
    foreach (VCMatrixControl const& control, newControls)
×
1140
        addCustomControl(control);
×
1141

1142
    return true;
1143
}
1144

1145
bool VCMatrix::saveXML(QXmlStreamWriter *doc)
×
1146
{
1147
    Q_ASSERT(doc != NULL);
1148

1149
    /* VC button entry */
1150
    doc->writeStartElement(KXMLQLCVCMatrix);
×
1151

1152
    saveXMLCommon(doc);
×
1153

1154
    /* Window state */
1155
    saveXMLWindowState(doc);
×
1156

1157
    /* Appearance */
1158
    saveXMLAppearance(doc);
×
1159

1160
    /* Function */
1161
    doc->writeStartElement(KXMLQLCVCMatrixFunction);
×
1162
    doc->writeAttribute(KXMLQLCVCMatrixFunctionID, QString::number(function()));
×
1163

1164
    if (instantChanges() == true)
×
1165
        doc->writeAttribute(KXMLQLCVCMatrixInstantApply, "true");
×
1166
    doc->writeEndElement();
×
1167

1168
    /* Default controls visibility  */
1169
    if (m_visibilityMask != VCMatrix::defaultVisibilityMask())
×
1170
        doc->writeTextElement(KXMLQLCVCMatrixVisibilityMask, QString::number(m_visibilityMask));
×
1171

1172
    /* Slider External input */
1173
    saveXMLInput(doc);
×
1174

1175
    foreach (VCMatrixControl *control, customControls())
×
1176
        control->saveXML(doc);
×
1177

1178
    /* End the <Matrix> tag */
1179
    doc->writeEndElement();
×
1180

1181
    return true;
×
1182
}
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