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

mcallegari / qlcplus / 21047491563

15 Jan 2026 09:47PM UTC coverage: 34.165% (-0.007%) from 34.172%
21047491563

push

github

mcallegari
qmlui: fix WAUV color palette

Reported: https://www.qlcplus.org/forum/viewtopic.php?t=19137

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

2 existing lines in 1 file now uncovered.

17720 of 51866 relevant lines covered (34.16%)

19813.88 hits per line

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

40.0
/engine/src/qlcpalette.cpp
1
/*
2
  Q Light Controller Plus
3
  qlcpalette.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 <QtMath>
23
#include <QDebug>
24

25
#include "monitorproperties.h"
26
#include "qlcpalette.h"
27
#include "qlcchannel.h"
28
#include "scenevalue.h"
29
#include "doc.h"
30

31
#define KXMLQLCPaletteType      QStringLiteral("Type")
32
#define KXMLQLCPaletteName      QStringLiteral("Name")
33
#define KXMLQLCPaletteValue     QStringLiteral("Value")
34
#define KXMLQLCPaletteFanning   QStringLiteral("Fan")
35
#define KXMLQLCPaletteFanLayout QStringLiteral("Layout")
36
#define KXMLQLCPaletteFanAmount QStringLiteral("Amount")
37
#define KXMLQLCPaletteFanValue  QStringLiteral("FanValue")
38

39
QLCPalette::QLCPalette(QLCPalette::PaletteType type, QObject *parent)
18✔
40
    : QObject(parent)
41
    , m_id(QLCPalette::invalidId())
36✔
42
    , m_type(type)
18✔
43
    , m_fanningType(Flat)
18✔
44
    , m_fanningLayout(XAscending)
18✔
45
    , m_fanningAmount(100)
18✔
46
{
47
}
18✔
48

49
QLCPalette *QLCPalette::createCopy()
×
50
{
51
    QLCPalette *copy = new QLCPalette(type());
×
52
    copy->setValues(this->values());
×
53
    copy->setName(this->name());
×
54
    copy->setFanningType(this->fanningType());
×
55
    copy->setFanningLayout(this->fanningLayout());
×
56
    copy->setFanningAmount(this->fanningAmount());
×
57
    copy->setFanningValue(this->fanningValue());
×
58

59
    return copy;
×
60
}
61

62
QLCPalette::~QLCPalette()
20✔
63
{
64

65
}
20✔
66

67
/************************************************************************
68
 * Properties
69
 ************************************************************************/
70

71
quint32 QLCPalette::id() const
5✔
72
{
73
    return m_id;
5✔
74
}
75

76
void QLCPalette::setID(quint32 id)
5✔
77
{
78
    m_id = id;
5✔
79
}
5✔
80

81
quint32 QLCPalette::invalidId()
25✔
82
{
83
    return UINT_MAX;
25✔
84
}
85

86
QLCPalette::PaletteType QLCPalette::type() const
10✔
87
{
88
    return m_type;
10✔
89
}
90

91
QString QLCPalette::typeToString(QLCPalette::PaletteType type)
10✔
92
{
93
    switch (type)
10✔
94
    {
95
        case Dimmer:    return "Dimmer";
1✔
96
        case Color:     return "Color";
1✔
97
        case Pan:       return "Pan";
1✔
98
        case Tilt:      return "Tilt";
1✔
99
        case PanTilt:   return "PanTilt";
2✔
100
        case Shutter:   return "Shutter";
1✔
101
        case Gobo:      return "Gobo";
1✔
102
        case Zoom:      return "Zoom";
1✔
103
        case Undefined: return "";
1✔
104
    }
105

106
    return "";
×
107
}
108

109
QLCPalette::PaletteType QLCPalette::stringToType(const QString &str)
10✔
110
{
111
    if (str == "Dimmer")
10✔
112
        return Dimmer;
1✔
113
    else if (str == "Color")
9✔
114
        return Color;
2✔
115
    else if (str == "Pan")
7✔
116
        return Pan;
1✔
117
    else if (str == "Tilt")
6✔
118
        return Tilt;
1✔
119
    else if (str == "PanTilt")
5✔
120
        return PanTilt;
1✔
121
    else if (str == "Shutter")
4✔
122
        return Shutter;
1✔
123
    else if (str == "Gobo")
3✔
124
        return Gobo;
1✔
125
    else if (str == "Zoom")
2✔
126
        return Zoom;
1✔
127

128
    return Undefined;
1✔
129
}
130

131
QString QLCPalette::iconResource(bool svg) const
8✔
132
{
133
    QString prefix = svg ? "qrc" : "";
8✔
134
    QString ext = svg ? "svg" : "png";
8✔
135

136
    switch(type())
8✔
137
    {
138
        case Dimmer: return QString("%1:/intensity.%2").arg(prefix).arg(ext);
1✔
139
        case Color: return QString("%1:/color.%2").arg(prefix).arg(ext);
1✔
140
        case Pan: return QString("%1:/pan.%2").arg(prefix).arg(ext);
1✔
141
        case Tilt: return QString("%1:/tilt.%2").arg(prefix).arg(ext);
1✔
142
        case PanTilt: return QString("%1:/position.%2").arg(prefix).arg(ext);
1✔
143
        case Shutter: return QString("%1:/shutter.%2").arg(prefix).arg(ext);
1✔
144
        case Gobo: return QString("%1:/gobo.%2").arg(prefix).arg(ext);
1✔
145
        case Zoom: return QString("%1:/beam.%2").arg(prefix).arg(ext);
1✔
146
        default: return "";
×
147
    }
148
}
8✔
149

150
QString QLCPalette::name() const
4✔
151
{
152
    return m_name;
4✔
153
}
154

155
void QLCPalette::setName(const QString &name)
3✔
156
{
157
    if (name == m_name)
3✔
158
        return;
×
159

160
    m_name = QString(name);
3✔
161
    emit nameChanged();
3✔
162
}
163

164
QVariant QLCPalette::value() const
4✔
165
{
166
    if (m_values.isEmpty())
4✔
167
        return QVariant();
×
168

169
    return m_values.first();
4✔
170
}
171

172
int QLCPalette::intValue1() const
×
173
{
174
    if (m_values.isEmpty())
×
175
        return -1;
×
176

177
    return m_values.at(0).toInt();
×
178
}
179

180
int QLCPalette::intValue2() const
×
181
{
182
    if (m_values.count() < 2)
×
183
        return -1;
×
184

185
    return m_values.at(1).toInt();
×
186
}
187

188
float QLCPalette::floatValue1() const
×
189
{
190
    if (m_values.isEmpty())
×
191
        return -1;
×
192

193
    return m_values.at(0).toFloat();
×
194
}
195

196
QString QLCPalette::strValue1() const
×
197
{
198
    if (m_values.isEmpty())
×
199
        return QString();
×
200

201
    return m_values.at(0).toString();
×
202
}
203

204
QColor QLCPalette::rgbValue() const
×
205
{
206
    if (m_values.isEmpty())
×
207
        return QColor();
×
208

209
    QColor rgb, wauv;
×
210
    stringToColor(m_values.at(0).toString(), rgb, wauv);
×
211

212
    return rgb;
×
213
}
214

215
QColor QLCPalette::wauvValue() const
×
216
{
217
    if (m_values.isEmpty())
×
218
        return QColor();
×
219

220
    QColor rgb, wauv;
×
221
    stringToColor(m_values.at(0).toString(), rgb, wauv);
×
222

223
    return wauv;
×
224
}
225

226
void QLCPalette::setValue(QVariant val)
3✔
227
{
228
    m_values.clear();
3✔
229
    m_values.append(val);
3✔
230
}
3✔
231

232
void QLCPalette::setValue(QVariant val1, QVariant val2)
2✔
233
{
234
    m_values.clear();
2✔
235
    m_values.append(val1);
2✔
236
    m_values.append(val2);
2✔
237
}
2✔
238

239
QVariantList QLCPalette::values() const
6✔
240
{
241
    return m_values;
6✔
242
}
243

244
void QLCPalette::setValues(QVariantList values)
×
245
{
246
    m_values = values;
×
247
}
×
248

249
void QLCPalette::resetValues()
×
250
{
251
    m_values.clear();
×
252
}
×
253

254
QList<SceneValue> QLCPalette::valuesFromFixtures(Doc *doc, QList<quint32> fixtures)
×
255
{
256
    QList<SceneValue> list;
×
257

258
    int fxCount = fixtures.count();
×
259
    // normalized progress in [ 0.0, 1.0 ] range
260
    qreal progress = 0.0;
×
261
    int intFanValue = fanningValue().toInt();
×
262
    FanningType fType = fanningType();
×
263
    FanningLayout fLayout = fanningLayout();
×
264
    MonitorProperties *mProps = doc->monitorProperties();
×
265
    qreal centerCoord = 0.0;
×
266
    qreal maxCenterDistance = 0.0;
×
267

268
    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
269
    {
270
        bool hasCoord = false;
×
271
        qreal minCoord = 0.0;
×
272
        qreal maxCoord = 0.0;
×
273

274
        foreach (quint32 id, fixtures)
×
275
        {
276
            QVector3D pos = mProps->fixturePosition(id, 0, 0);
×
277
            qreal coord = 0.0;
×
278

279
            switch (fLayout)
×
280
            {
281
                case XCentered: coord = pos.x(); break;
×
282
                case YCentered: coord = pos.y(); break;
×
283
                case ZCentered: coord = pos.z(); break;
×
284
                default: break;
×
285
            }
286

287
            if (hasCoord == false)
×
288
            {
289
                minCoord = coord;
×
290
                maxCoord = coord;
×
291
                hasCoord = true;
×
292
            }
293
            else
294
            {
295
                minCoord = qMin(minCoord, coord);
×
296
                maxCoord = qMax(maxCoord, coord);
×
297
            }
298
        }
×
299

300
        centerCoord = (minCoord + maxCoord) / 2.0;
×
301
        maxCenterDistance = qMax(qAbs(minCoord - centerCoord), qAbs(maxCoord - centerCoord));
×
302
    }
303

304
    // sort the fixtures list based on selected layout
305
    std::sort(fixtures.begin(), fixtures.end(),
×
306
        [fLayout, mProps, centerCoord](quint32 a, quint32 b) {
×
307
            QVector3D posA = mProps->fixturePosition(a, 0, 0);
×
308
            QVector3D posB = mProps->fixturePosition(b, 0, 0);
×
309

310
            switch(fLayout)
×
311
            {
312
                case XAscending: return posA.x() < posB.x();
×
313
                case XDescending: return posB.x() < posA.x();
×
314
                case XCentered:
×
315
                {
316
                    qreal distA = qAbs(posA.x() - centerCoord);
×
317
                    qreal distB = qAbs(posB.x() - centerCoord);
×
318
                    return (distA == distB) ? (posA.x() < posB.x()) : (distA < distB);
×
319
                }
320
                case YAscending: return posA.y() < posB.y();
×
321
                case YDescending: return posB.y() < posA.y();
×
322
                case YCentered:
×
323
                {
324
                    qreal distA = qAbs(posA.y() - centerCoord);
×
325
                    qreal distB = qAbs(posB.y() - centerCoord);
×
326
                    return (distA == distB) ? (posA.y() < posB.y()) : (distA < distB);
×
327
                }
328
                case ZAscending: return posA.z() < posB.z();
×
329
                case ZDescending: return posB.z() < posA.z();
×
330
                case ZCentered:
×
331
                {
332
                    qreal distA = qAbs(posA.z() - centerCoord);
×
333
                    qreal distB = qAbs(posB.z() - centerCoord);
×
334
                    return (distA == distB) ? (posA.z() < posB.z()) : (distA < distB);
×
335
                }
336
                default: return false;
×
337
            }
338
        });
339

340
    foreach (quint32 id, fixtures)
×
341
    {
342
        Fixture *fixture = doc->fixture(id);
×
343
        if (fixture == NULL)
×
344
            continue;
×
345

346
        qreal factor = valueFactor(progress);
×
347
        int centeredSign = 1;
×
348

349
        if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
350
        {
351
            QVector3D pos = mProps->fixturePosition(id, 0, 0);
×
352
            qreal coord = 0.0;
×
353

354
            switch (fLayout)
×
355
            {
356
                case XCentered: coord = pos.x(); break;
×
357
                case YCentered: coord = pos.y(); break;
×
358
                case ZCentered: coord = pos.z(); break;
×
359
                default: break;
×
360
            }
361

362
            if (coord > centerCoord)
×
363
                centeredSign = 1;
×
364
            else if (coord < centerCoord)
×
365
                centeredSign = -1;
×
366
            else
367
                centeredSign = 0;
×
368

369
            if (maxCenterDistance > 0.0)
×
370
            {
371
                qreal distance = qAbs(coord - centerCoord);
×
372
                factor = valueFactor(distance / maxCenterDistance);
×
373
            }
374
            else
375
            {
376
                factor = valueFactor(0.0);
×
377
            }
378
        }
379

380
        switch(type())
×
381
        {
382
            case Dimmer:
×
383
            {
384
                int dValue = value().toInt();
×
385
                quint32 masterIntensityChannel = fixture->type() == QLCFixtureDef::Dimmer ?
×
386
                            0 : fixture->masterIntensityChannel();
×
387

388
                if (fType != Flat)
×
389
                    dValue = int((qreal(intFanValue - dValue) * factor) + dValue);
×
390

391
                if (masterIntensityChannel != QLCChannel::invalid())
×
392
                    list << SceneValue(id, masterIntensityChannel, uchar(dValue));
×
393

394
                for (int i = 0; i < fixture->heads(); i++)
×
395
                {
396
                    quint32 headDimmerChannel = fixture->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, i);
×
397
                    if (headDimmerChannel != QLCChannel::invalid())
×
398
                        list << SceneValue(id, headDimmerChannel, uchar(dValue));
×
399
                }
400
            }
401
            break;
×
402
            case Color:
×
403
            {
404

NEW
405
                QColor startColor = rgbValue();
×
UNCOV
406
                QColor col = startColor;
×
NEW
407
                QColor wauv = wauvValue();
×
408

409
                if (fType != Flat)
×
410
                {
411
                    QColor endColor = fanningValue().value<QColor>();
×
412
                    qreal rDelta = endColor.red() - startColor.red();
×
413
                    qreal gDelta = endColor.green() - startColor.green();
×
414
                    qreal bDelta = endColor.blue() - startColor.blue();
×
415
                    col.setRed(startColor.red() + qRound(rDelta * factor));
×
416
                    col.setGreen(startColor.green() + qRound(gDelta * factor));
×
417
                    col.setBlue(startColor.blue() + qRound(bDelta * factor));
×
418
                }
419

420
                for (int i = 0; i < fixture->heads(); i++)
×
421
                {
422
                    QVector<quint32> rgbCh = fixture->rgbChannels(i);
×
423
                    if (rgbCh.size() == 3)
×
424
                    {
425
                        list << SceneValue(id, rgbCh.at(0), uchar(col.red()));
×
426
                        list << SceneValue(id, rgbCh.at(1), uchar(col.green()));
×
427
                        list << SceneValue(id, rgbCh.at(2), uchar(col.blue()));
×
428
                    }
429
                    QVector<quint32> cmyCh = fixture->cmyChannels(i);
×
430
                    if (cmyCh.size() == 3)
×
431
                    {
432
                        list << SceneValue(id, cmyCh.at(0), uchar(col.cyan()));
×
433
                        list << SceneValue(id, cmyCh.at(1), uchar(col.magenta()));
×
434
                        list << SceneValue(id, cmyCh.at(2), uchar(col.yellow()));
×
435
                    }
436

NEW
437
                    if (wauv.isValid())
×
438
                    {
NEW
439
                        quint32 channel = fixture->channelNumber(QLCChannel::White, QLCChannel::MSB, i);
×
NEW
440
                        if (channel != QLCChannel::invalid())
×
NEW
441
                            list << SceneValue(id, channel, uchar(wauv.red()));
×
NEW
442
                        channel = fixture->channelNumber(QLCChannel::Amber, QLCChannel::MSB, i);
×
NEW
443
                        if (channel != QLCChannel::invalid())
×
NEW
444
                            list << SceneValue(id, channel, uchar(wauv.green()));
×
NEW
445
                        channel = fixture->channelNumber(QLCChannel::UV, QLCChannel::MSB, i);
×
NEW
446
                        if (channel != QLCChannel::invalid())
×
NEW
447
                            list << SceneValue(id, channel, uchar(wauv.blue()));
×
448
                    }
UNCOV
449
                }
×
450
            }
451
            break;
×
452
            case Pan:
×
453
            {
454
                int degrees = value().toInt();
×
455

456
                if (fType != Flat)
×
457
                {
458
                    int offset = int(qreal(intFanValue) * factor);
×
459
                    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
460
                        offset *= centeredSign;
×
461
                    degrees = int(qreal(degrees) + qreal(offset));
×
462
                }
463

464
                list << fixture->positionToValues(QLCChannel::Pan, degrees);
×
465
            }
466
            break;
×
467
            case Tilt:
×
468
            {
469
                int degrees = m_values.count() == 2 ? m_values.at(1).toInt() : value().toInt();
×
470

471
                if (fType != Flat)
×
472
                {
473
                    int offset = int(qreal(intFanValue) * factor);
×
474
                    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
475
                        offset *= centeredSign;
×
476
                    degrees = int(qreal(degrees) + qreal(offset));
×
477
                }
478

479
                list << fixture->positionToValues(QLCChannel::Tilt, degrees);
×
480
            }
481
            break;
×
482
            case PanTilt:
×
483
            {
484
                if (m_values.count() == 2)
×
485
                {
486
                    int panDegrees = m_values.at(0).toInt();
×
487
                    int tiltDegrees = m_values.at(1).toInt();
×
488

489
                    if (fType != Flat)
×
490
                    {
491
                        int offset = int(qreal(intFanValue) * factor);
×
492
                        if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
493
                            offset *= centeredSign;
×
494
                        panDegrees = int((qreal(panDegrees) + qreal(offset)));
×
495
                        tiltDegrees = int((qreal(tiltDegrees) + qreal(offset)));
×
496
                    }
497

498
                    list << fixture->positionToValues(QLCChannel::Pan, panDegrees);
×
499
                    list << fixture->positionToValues(QLCChannel::Tilt, tiltDegrees);
×
500
                }
501
            }
502
            break;
×
503
            case Shutter:
×
504
            {
505
                quint32 shCh = fixture->channelNumber(QLCChannel::Shutter, QLCChannel::MSB);
×
506
                if (shCh != QLCChannel::invalid())
×
507
                    list << SceneValue(id, shCh, uchar(value().toUInt()));
×
508
            }
509
            break;
×
510
            case Gobo:
×
511
            {
512
                quint32 goboCh = fixture->channelNumber(QLCChannel::Gobo, QLCChannel::MSB);
×
513
                if (goboCh != QLCChannel::invalid())
×
514
                    list << SceneValue(id, goboCh, uchar(value().toUInt()));
×
515
            }
516
            break;
×
517
            case Zoom:
×
518
            {
519
                for (int i = 0; i < int(fixture->channels()); i++)
×
520
                {
521
                    const QLCChannel *ch = fixture->channel(quint32(i));
×
522
                    if (ch == nullptr)
×
523
                        continue;
×
524

525
                    if (ch->group() == QLCChannel::Beam &&
×
526
                        (ch->preset() == QLCChannel::BeamZoomSmallBig || ch->preset() == QLCChannel::BeamZoomBigSmall))
×
527
                    {
528
                        list << fixture->zoomToValues(value().toFloat(), false);
×
529
                        break;
×
530
                    }
531
                }
532
            }
533
            break;
×
534
            case Undefined:
×
535
            break;
×
536
        }
537

538
        progress += (1.0 / qreal(fxCount - 1));
×
539
    }
×
540

541
    return list;
×
542
}
×
543

544
QList<SceneValue> QLCPalette::valuesFromFixtureGroups(Doc *doc, QList<quint32> groups)
×
545
{
546
    QList<quint32> fixturesList;
×
547

548
    foreach (quint32 id, groups)
×
549
    {
550
        FixtureGroup *group = doc->fixtureGroup(id);
×
551
        if (group == NULL)
×
552
            continue;
×
553

554
        fixturesList.append(group->fixtureList());
×
555
    }
×
556

557
    return valuesFromFixtures(doc, fixturesList);
×
558
}
×
559

560
qreal QLCPalette::valueFactor(qreal progress)
×
561
{
562
    qreal factor = 1.0;
×
563
    qreal normalizedAmount = qreal(m_fanningAmount) / 100.0;
×
564

565
    switch (m_fanningType)
×
566
    {
567
        case Flat:
×
568
            // nothing to do. Factor is always 1.0
569
        break;
×
570
        case Linear:
×
571
        {
572
            if (normalizedAmount < 1.0)
×
573
            {
574
                if (progress > normalizedAmount)
×
575
                    factor = 1.0;
×
576
                else
577
                    factor = progress * normalizedAmount;
×
578
            }
579
            else if (normalizedAmount > 1.0)
×
580
            {
581
                factor = progress / normalizedAmount;
×
582
            }
583
            else
584
            {
585
                factor = progress;
×
586
            }
587
        }
588
        break;
×
589
        case Sine:
×
590
        {
591
            qreal degrees = (progress * 360.0) + 270.0;
×
592
            factor = (qSin(normalizedAmount * qDegreesToRadians(degrees)) + 1.0) / 2.0;
×
593
        }
594
        break;
×
595
        case Square:
×
596
        {
597
            factor = qSin(normalizedAmount * qDegreesToRadians(progress * 360.0)) < 0 ? 1 : 0;
×
598
        }
599
        break;
×
600
        case Saw:
×
601
        break;
×
602
    }
603

604
    return factor;
×
605
}
606

607
/************************************************************************
608
 * Fanning
609
 ************************************************************************/
610

611
QLCPalette::FanningType QLCPalette::fanningType() const
2✔
612
{
613
    return m_fanningType;
2✔
614
}
615

616
void QLCPalette::setFanningType(QLCPalette::FanningType type)
1✔
617
{
618
    if (type == m_fanningType)
1✔
619
        return;
×
620

621
    m_fanningType = type;
1✔
622

623
    emit fanningTypeChanged();
1✔
624
}
625

626
QString QLCPalette::fanningTypeToString(QLCPalette::FanningType type)
5✔
627
{
628
    switch (type)
5✔
629
    {
630
        case Flat:      return "Flat";
1✔
631
        case Linear:    return "Linear";
1✔
632
        case Sine:      return "Sine";
1✔
633
        case Square:    return "Square";
1✔
634
        case Saw:       return "Saw";
1✔
635
    }
636

637
    return "";
×
638
}
639

640
QLCPalette::FanningType QLCPalette::stringToFanningType(const QString &str)
7✔
641
{
642
    if (str == "Flat")
7✔
643
        return Flat;
1✔
644
    else if (str == "Linear")
6✔
645
        return Linear;
2✔
646
    else if (str == "Sine")
4✔
647
        return Sine;
1✔
648
    else if (str == "Square")
3✔
649
        return Square;
1✔
650
    else if (str == "Saw")
2✔
651
        return Saw;
1✔
652

653
    return Flat;
1✔
654
}
655

656
QLCPalette::FanningLayout QLCPalette::fanningLayout() const
2✔
657
{
658
    return m_fanningLayout;
2✔
659
}
660

661
void QLCPalette::setFanningLayout(QLCPalette::FanningLayout layout)
1✔
662
{
663
    if (layout == m_fanningLayout)
1✔
664
        return;
1✔
665

666
    m_fanningLayout = layout;
×
667

668
    emit fanningLayoutChanged();
×
669
}
670

671
QString QLCPalette::fanningLayoutToString(QLCPalette::FanningLayout layout)
9✔
672
{
673
    switch (layout)
9✔
674
    {
675
        case XAscending:    return "XAscending";
1✔
676
        case XDescending:   return "XDescending";
1✔
677
        case XCentered:     return "XCentered";
1✔
678
        case YAscending:    return "YAscending";
1✔
679
        case YDescending:   return "YDescending";
1✔
680
        case YCentered:     return "YCentered";
1✔
681
        case ZAscending:    return "ZAscending";
1✔
682
        case ZDescending:   return "ZDescending";
1✔
683
        case ZCentered:     return "ZCentered";
1✔
684
    }
685

686
    return "";
×
687
}
688

689
QLCPalette::FanningLayout QLCPalette::stringToFanningLayout(const QString &str)
11✔
690
{
691
    if (str == "XAscending")
11✔
692
        return XAscending;
1✔
693
    else if (str == "XDescending")
10✔
694
        return XDescending;
1✔
695
    else if (str == "XCentered")
9✔
696
        return XCentered;
1✔
697
    else     if (str == "YAscending")
8✔
698
        return YAscending;
1✔
699
    else if (str == "YDescending")
7✔
700
        return YDescending;
1✔
701
    else if (str == "YCentered")
6✔
702
        return YCentered;
1✔
703
    else if (str == "ZAscending")
5✔
704
        return ZAscending;
1✔
705
    else if (str == "ZDescending")
4✔
706
        return ZDescending;
1✔
707
    else if (str == "ZCentered")
3✔
708
        return ZCentered;
1✔
709

710
    return XAscending;
2✔
711
}
712

713
int QLCPalette::fanningAmount() const
3✔
714
{
715
    return m_fanningAmount;
3✔
716
}
717

718
void QLCPalette::setFanningAmount(int amount)
2✔
719
{
720
    if (amount == m_fanningAmount)
2✔
721
        return;
×
722

723
    m_fanningAmount = amount;
2✔
724

725
    emit fanningAmountChanged();
2✔
726
}
727

728
QVariant QLCPalette::fanningValue() const
2✔
729
{
730
    return m_fanningValue;
2✔
731
}
732

733
void QLCPalette::setFanningValue(QVariant value)
1✔
734
{
735
    if (value == m_fanningValue)
1✔
736
        return;
×
737

738
    m_fanningValue = value;
1✔
739

740
    emit fanningValueChanged();
1✔
741
}
742

743
/************************************************************************
744
 * Color helpers
745
 ************************************************************************/
746

747
QString QLCPalette::colorToString(QColor rgb, QColor wauv)
2✔
748
{
749
    QString final = rgb.name();
2✔
750
    final.append(wauv.name().right(6));
2✔
751
    return final;
2✔
752
}
×
753

754
bool QLCPalette::stringToColor(QString str, QColor &rgb, QColor &wauv)
3✔
755
{
756
    // string must be like #rrggbb or #rrggbbwwaauv
757
    if (str.length() != 7 && str.length() != 13)
3✔
758
        return false;
1✔
759

760
    rgb = QColor(str.left(7));
2✔
761

762
    if (str.length() == 13)
2✔
763
        wauv = QColor("#" + str.right(6));
2✔
764
    else
765
        wauv = QColor();
×
766

767
    return true;
2✔
768
}
769

770
/************************************************************************
771
 * Load & Save
772
 ************************************************************************/
773

774
bool QLCPalette::loader(QXmlStreamReader &xmlDoc, Doc *doc)
×
775
{
776
    QLCPalette *palette = new QLCPalette(Dimmer, doc);
×
777
    Q_ASSERT(palette != NULL);
×
778

779
    if (palette->loadXML(xmlDoc) == true)
×
780
    {
781
        doc->addPalette(palette, palette->id());
×
782
    }
783
    else
784
    {
785
        qWarning() << Q_FUNC_INFO << "QLCPalette" << palette->name() << "cannot be loaded.";
×
786
        delete palette;
×
787
        return false;
×
788
    }
789

790
    return true;
×
791
}
792

793
bool QLCPalette::loadXML(QXmlStreamReader &doc)
2✔
794
{
795
    if (doc.name() != KXMLQLCPalette)
2✔
796
    {
797
        qWarning() << Q_FUNC_INFO << "Palette node not found";
1✔
798
        return false;
1✔
799
    }
800

801
    QXmlStreamAttributes attrs = doc.attributes();
1✔
802

803
    bool ok = false;
1✔
804
    quint32 id = attrs.value(KXMLQLCPaletteID).toString().toUInt(&ok);
1✔
805
    if (ok == false)
1✔
806
    {
807
        qWarning() << "Invalid Palette ID:" << attrs.value(KXMLQLCPaletteID).toString();
×
808
        return false;
×
809
    }
810

811
    setID(id);
1✔
812

813
    if (attrs.hasAttribute(KXMLQLCPaletteType) == false)
1✔
814
    {
815
        qWarning() << "Palette type not found!";
×
816
        return false;
×
817
    }
818

819
    m_type = stringToType(attrs.value(KXMLQLCPaletteType).toString());
1✔
820

821
    if (attrs.hasAttribute(KXMLQLCPaletteName))
1✔
822
        setName(attrs.value(KXMLQLCPaletteName).toString());
1✔
823

824
    if (attrs.hasAttribute(KXMLQLCPaletteValue))
1✔
825
    {
826
        QString strVal = attrs.value(KXMLQLCPaletteValue).toString();
1✔
827
        switch (m_type)
1✔
828
        {
829
            case Dimmer:
×
830
            case Pan:
831
            case Tilt:
832
                setValue(strVal.toInt());
×
833
            break;
×
834
            case Color:
1✔
835
                setValue(strVal);
1✔
836
            break;
1✔
837
            case PanTilt:
×
838
            {
839
                QStringList posList = strVal.split(",");
×
840
                if (posList.count() == 2)
×
841
                    setValue(posList.at(0).toInt(), posList.at(1).toInt());
×
842
            }
×
843
            break;
×
844
            case Zoom:
×
845
                setValue(strVal.toFloat());
×
846
            break;
×
847
            case Shutter:   break;
×
848
            case Gobo:      break;
×
849
            case Undefined: break;
×
850
        }
851
    }
1✔
852

853
    if (attrs.hasAttribute(KXMLQLCPaletteFanning))
1✔
854
    {
855
        setFanningType(stringToFanningType(attrs.value(KXMLQLCPaletteFanning).toString()));
1✔
856

857
        if (attrs.hasAttribute(KXMLQLCPaletteFanLayout))
1✔
858
            setFanningLayout(stringToFanningLayout(attrs.value(KXMLQLCPaletteFanLayout).toString()));
1✔
859

860
        if (attrs.hasAttribute(KXMLQLCPaletteFanAmount))
1✔
861
            setFanningAmount(attrs.value(KXMLQLCPaletteFanAmount).toInt());
1✔
862

863
        if (attrs.hasAttribute(KXMLQLCPaletteFanValue))
1✔
864
        {
865
            QString strVal = attrs.value(KXMLQLCPaletteFanValue).toString();
1✔
866
            switch (m_type)
1✔
867
            {
868
                case Dimmer:
×
869
                case Pan:
870
                case Tilt:
871
                case PanTilt:
872
                case Zoom:
873
                    setFanningValue(strVal.toInt());
×
874
                break;
×
875
                case Color:
1✔
876
                    setFanningValue(strVal);
1✔
877
                break;
1✔
878
                case Shutter:   break;
×
879
                case Gobo:      break;
×
880
                case Undefined: break;
×
881
            }
882
        }
1✔
883
    }
884

885
    return true;
1✔
886
}
1✔
887

888
bool QLCPalette::saveXML(QXmlStreamWriter *doc)
1✔
889
{
890
    Q_ASSERT(doc != NULL);
1✔
891

892
    if (m_values.isEmpty())
1✔
893
    {
894
        qWarning() << "Unable to save a Palette without value!";
×
895
        return false;
×
896
    }
897

898
    /* write a Palette entry */
899
    doc->writeStartElement(KXMLQLCPalette);
2✔
900
    doc->writeAttribute(KXMLQLCPaletteID, QString::number(this->id()));
2✔
901
    doc->writeAttribute(KXMLQLCPaletteType, typeToString(m_type));
2✔
902
    doc->writeAttribute(KXMLQLCPaletteName, this->name());
2✔
903

904
    /* write value */
905
    switch (m_type)
1✔
906
    {
907
        case Dimmer:
×
908
        case Pan:
909
        case Tilt:
910
        case Zoom:
911
        case Color:
912
            doc->writeAttribute(KXMLQLCPaletteValue, value().toString());
×
913
        break;
×
914
        case PanTilt:
1✔
915
            doc->writeAttribute(KXMLQLCPaletteValue,
2✔
916
                                QString("%1,%2").arg(m_values.at(0).toInt()).arg(m_values.at(1).toInt()));
2✔
917
        break;
1✔
918
        case Shutter:   break;
×
919
        case Gobo:      break;
×
920
        case Undefined: break;
×
921
    }
922

923
    /* write fanning */
924
    if (m_fanningType != Flat)
1✔
925
    {
926
        doc->writeAttribute(KXMLQLCPaletteFanning, fanningTypeToString(m_fanningType));
×
927
        doc->writeAttribute(KXMLQLCPaletteFanLayout, fanningLayoutToString(m_fanningLayout));
×
928
        doc->writeAttribute(KXMLQLCPaletteFanAmount, QString::number(m_fanningAmount));
×
929
        doc->writeAttribute(KXMLQLCPaletteFanValue, fanningValue().toString());
×
930
    }
931

932
    doc->writeEndElement();
1✔
933

934
    return true;
1✔
935
}
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