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

mcallegari / qlcplus / 20794594664

07 Jan 2026 07:52PM UTC coverage: 34.17% (-0.1%) from 34.276%
20794594664

push

github

mcallegari
Back to 5.1.1 debug

17716 of 51846 relevant lines covered (34.17%)

19821.52 hits per line

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

40.84
/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
                QColor startColor = value().value<QColor>();
×
405
                QColor col = startColor;
×
406

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

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

441
                if (fType != Flat)
×
442
                {
443
                    int offset = int(qreal(intFanValue) * factor);
×
444
                    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
445
                        offset *= centeredSign;
×
446
                    degrees = int(qreal(degrees) + qreal(offset));
×
447
                }
448

449
                list << fixture->positionToValues(QLCChannel::Pan, degrees);
×
450
            }
451
            break;
×
452
            case Tilt:
×
453
            {
454
                int degrees = m_values.count() == 2 ? m_values.at(1).toInt() : 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::Tilt, degrees);
×
465
            }
466
            break;
×
467
            case PanTilt:
×
468
            {
469
                if (m_values.count() == 2)
×
470
                {
471
                    int panDegrees = m_values.at(0).toInt();
×
472
                    int tiltDegrees = m_values.at(1).toInt();
×
473

474
                    if (fType != Flat)
×
475
                    {
476
                        int offset = int(qreal(intFanValue) * factor);
×
477
                        if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
478
                            offset *= centeredSign;
×
479
                        panDegrees = int((qreal(panDegrees) + qreal(offset)));
×
480
                        tiltDegrees = int((qreal(tiltDegrees) + qreal(offset)));
×
481
                    }
482

483
                    list << fixture->positionToValues(QLCChannel::Pan, panDegrees);
×
484
                    list << fixture->positionToValues(QLCChannel::Tilt, tiltDegrees);
×
485
                }
486
            }
487
            break;
×
488
            case Shutter:
×
489
            {
490
                quint32 shCh = fixture->channelNumber(QLCChannel::Shutter, QLCChannel::MSB);
×
491
                if (shCh != QLCChannel::invalid())
×
492
                    list << SceneValue(id, shCh, uchar(value().toUInt()));
×
493
            }
494
            break;
×
495
            case Gobo:
×
496
            {
497
                quint32 goboCh = fixture->channelNumber(QLCChannel::Gobo, QLCChannel::MSB);
×
498
                if (goboCh != QLCChannel::invalid())
×
499
                    list << SceneValue(id, goboCh, uchar(value().toUInt()));
×
500
            }
501
            break;
×
502
            case Zoom:
×
503
            {
504
                for (int i = 0; i < int(fixture->channels()); i++)
×
505
                {
506
                    const QLCChannel *ch = fixture->channel(quint32(i));
×
507
                    if (ch == nullptr)
×
508
                        continue;
×
509

510
                    if (ch->group() == QLCChannel::Beam &&
×
511
                        (ch->preset() == QLCChannel::BeamZoomSmallBig || ch->preset() == QLCChannel::BeamZoomBigSmall))
×
512
                    {
513
                        list << fixture->zoomToValues(value().toFloat(), false);
×
514
                        break;
×
515
                    }
516
                }
517
            }
518
            break;
×
519
            case Undefined:
×
520
            break;
×
521
        }
522

523
        progress += (1.0 / qreal(fxCount - 1));
×
524
    }
×
525

526
    return list;
×
527
}
×
528

529
QList<SceneValue> QLCPalette::valuesFromFixtureGroups(Doc *doc, QList<quint32> groups)
×
530
{
531
    QList<quint32> fixturesList;
×
532

533
    foreach (quint32 id, groups)
×
534
    {
535
        FixtureGroup *group = doc->fixtureGroup(id);
×
536
        if (group == NULL)
×
537
            continue;
×
538

539
        fixturesList.append(group->fixtureList());
×
540
    }
×
541

542
    return valuesFromFixtures(doc, fixturesList);
×
543
}
×
544

545
qreal QLCPalette::valueFactor(qreal progress)
×
546
{
547
    qreal factor = 1.0;
×
548
    qreal normalizedAmount = qreal(m_fanningAmount) / 100.0;
×
549

550
    switch (m_fanningType)
×
551
    {
552
        case Flat:
×
553
            // nothing to do. Factor is always 1.0
554
        break;
×
555
        case Linear:
×
556
        {
557
            if (normalizedAmount < 1.0)
×
558
            {
559
                if (progress > normalizedAmount)
×
560
                    factor = 1.0;
×
561
                else
562
                    factor = progress * normalizedAmount;
×
563
            }
564
            else if (normalizedAmount > 1.0)
×
565
            {
566
                factor = progress / normalizedAmount;
×
567
            }
568
            else
569
            {
570
                factor = progress;
×
571
            }
572
        }
573
        break;
×
574
        case Sine:
×
575
        {
576
            qreal degrees = (progress * 360.0) + 270.0;
×
577
            factor = (qSin(normalizedAmount * qDegreesToRadians(degrees)) + 1.0) / 2.0;
×
578
        }
579
        break;
×
580
        case Square:
×
581
        {
582
            factor = qSin(normalizedAmount * qDegreesToRadians(progress * 360.0)) < 0 ? 1 : 0;
×
583
        }
584
        break;
×
585
        case Saw:
×
586
        break;
×
587
    }
588

589
    return factor;
×
590
}
591

592
/************************************************************************
593
 * Fanning
594
 ************************************************************************/
595

596
QLCPalette::FanningType QLCPalette::fanningType() const
2✔
597
{
598
    return m_fanningType;
2✔
599
}
600

601
void QLCPalette::setFanningType(QLCPalette::FanningType type)
1✔
602
{
603
    if (type == m_fanningType)
1✔
604
        return;
×
605

606
    m_fanningType = type;
1✔
607

608
    emit fanningTypeChanged();
1✔
609
}
610

611
QString QLCPalette::fanningTypeToString(QLCPalette::FanningType type)
5✔
612
{
613
    switch (type)
5✔
614
    {
615
        case Flat:      return "Flat";
1✔
616
        case Linear:    return "Linear";
1✔
617
        case Sine:      return "Sine";
1✔
618
        case Square:    return "Square";
1✔
619
        case Saw:       return "Saw";
1✔
620
    }
621

622
    return "";
×
623
}
624

625
QLCPalette::FanningType QLCPalette::stringToFanningType(const QString &str)
7✔
626
{
627
    if (str == "Flat")
7✔
628
        return Flat;
1✔
629
    else if (str == "Linear")
6✔
630
        return Linear;
2✔
631
    else if (str == "Sine")
4✔
632
        return Sine;
1✔
633
    else if (str == "Square")
3✔
634
        return Square;
1✔
635
    else if (str == "Saw")
2✔
636
        return Saw;
1✔
637

638
    return Flat;
1✔
639
}
640

641
QLCPalette::FanningLayout QLCPalette::fanningLayout() const
2✔
642
{
643
    return m_fanningLayout;
2✔
644
}
645

646
void QLCPalette::setFanningLayout(QLCPalette::FanningLayout layout)
1✔
647
{
648
    if (layout == m_fanningLayout)
1✔
649
        return;
1✔
650

651
    m_fanningLayout = layout;
×
652

653
    emit fanningLayoutChanged();
×
654
}
655

656
QString QLCPalette::fanningLayoutToString(QLCPalette::FanningLayout layout)
9✔
657
{
658
    switch (layout)
9✔
659
    {
660
        case XAscending:    return "XAscending";
1✔
661
        case XDescending:   return "XDescending";
1✔
662
        case XCentered:     return "XCentered";
1✔
663
        case YAscending:    return "YAscending";
1✔
664
        case YDescending:   return "YDescending";
1✔
665
        case YCentered:     return "YCentered";
1✔
666
        case ZAscending:    return "ZAscending";
1✔
667
        case ZDescending:   return "ZDescending";
1✔
668
        case ZCentered:     return "ZCentered";
1✔
669
    }
670

671
    return "";
×
672
}
673

674
QLCPalette::FanningLayout QLCPalette::stringToFanningLayout(const QString &str)
11✔
675
{
676
    if (str == "XAscending")
11✔
677
        return XAscending;
1✔
678
    else if (str == "XDescending")
10✔
679
        return XDescending;
1✔
680
    else if (str == "XCentered")
9✔
681
        return XCentered;
1✔
682
    else     if (str == "YAscending")
8✔
683
        return YAscending;
1✔
684
    else if (str == "YDescending")
7✔
685
        return YDescending;
1✔
686
    else if (str == "YCentered")
6✔
687
        return YCentered;
1✔
688
    else if (str == "ZAscending")
5✔
689
        return ZAscending;
1✔
690
    else if (str == "ZDescending")
4✔
691
        return ZDescending;
1✔
692
    else if (str == "ZCentered")
3✔
693
        return ZCentered;
1✔
694

695
    return XAscending;
2✔
696
}
697

698
int QLCPalette::fanningAmount() const
3✔
699
{
700
    return m_fanningAmount;
3✔
701
}
702

703
void QLCPalette::setFanningAmount(int amount)
2✔
704
{
705
    if (amount == m_fanningAmount)
2✔
706
        return;
×
707

708
    m_fanningAmount = amount;
2✔
709

710
    emit fanningAmountChanged();
2✔
711
}
712

713
QVariant QLCPalette::fanningValue() const
2✔
714
{
715
    return m_fanningValue;
2✔
716
}
717

718
void QLCPalette::setFanningValue(QVariant value)
1✔
719
{
720
    if (value == m_fanningValue)
1✔
721
        return;
×
722

723
    m_fanningValue = value;
1✔
724

725
    emit fanningValueChanged();
1✔
726
}
727

728
/************************************************************************
729
 * Color helpers
730
 ************************************************************************/
731

732
QString QLCPalette::colorToString(QColor rgb, QColor wauv)
2✔
733
{
734
    QString final = rgb.name();
2✔
735
    final.append(wauv.name().right(6));
2✔
736
    return final;
2✔
737
}
×
738

739
bool QLCPalette::stringToColor(QString str, QColor &rgb, QColor &wauv)
3✔
740
{
741
    // string must be like #rrggbb or #rrggbbwwaauv
742
    if (str.length() != 7 && str.length() != 13)
3✔
743
        return false;
1✔
744

745
    rgb = QColor(str.left(7));
2✔
746

747
    if (str.length() == 13)
2✔
748
        wauv = QColor("#" + str.right(6));
2✔
749
    else
750
        wauv = QColor();
×
751

752
    return true;
2✔
753
}
754

755
/************************************************************************
756
 * Load & Save
757
 ************************************************************************/
758

759
bool QLCPalette::loader(QXmlStreamReader &xmlDoc, Doc *doc)
×
760
{
761
    QLCPalette *palette = new QLCPalette(Dimmer, doc);
×
762
    Q_ASSERT(palette != NULL);
×
763

764
    if (palette->loadXML(xmlDoc) == true)
×
765
    {
766
        doc->addPalette(palette, palette->id());
×
767
    }
768
    else
769
    {
770
        qWarning() << Q_FUNC_INFO << "QLCPalette" << palette->name() << "cannot be loaded.";
×
771
        delete palette;
×
772
        return false;
×
773
    }
774

775
    return true;
×
776
}
777

778
bool QLCPalette::loadXML(QXmlStreamReader &doc)
2✔
779
{
780
    if (doc.name() != KXMLQLCPalette)
2✔
781
    {
782
        qWarning() << Q_FUNC_INFO << "Palette node not found";
1✔
783
        return false;
1✔
784
    }
785

786
    QXmlStreamAttributes attrs = doc.attributes();
1✔
787

788
    bool ok = false;
1✔
789
    quint32 id = attrs.value(KXMLQLCPaletteID).toString().toUInt(&ok);
1✔
790
    if (ok == false)
1✔
791
    {
792
        qWarning() << "Invalid Palette ID:" << attrs.value(KXMLQLCPaletteID).toString();
×
793
        return false;
×
794
    }
795

796
    setID(id);
1✔
797

798
    if (attrs.hasAttribute(KXMLQLCPaletteType) == false)
1✔
799
    {
800
        qWarning() << "Palette type not found!";
×
801
        return false;
×
802
    }
803

804
    m_type = stringToType(attrs.value(KXMLQLCPaletteType).toString());
1✔
805

806
    if (attrs.hasAttribute(KXMLQLCPaletteName))
1✔
807
        setName(attrs.value(KXMLQLCPaletteName).toString());
1✔
808

809
    if (attrs.hasAttribute(KXMLQLCPaletteValue))
1✔
810
    {
811
        QString strVal = attrs.value(KXMLQLCPaletteValue).toString();
1✔
812
        switch (m_type)
1✔
813
        {
814
            case Dimmer:
×
815
            case Pan:
816
            case Tilt:
817
                setValue(strVal.toInt());
×
818
            break;
×
819
            case Color:
1✔
820
                setValue(strVal);
1✔
821
            break;
1✔
822
            case PanTilt:
×
823
            {
824
                QStringList posList = strVal.split(",");
×
825
                if (posList.count() == 2)
×
826
                    setValue(posList.at(0).toInt(), posList.at(1).toInt());
×
827
            }
×
828
            break;
×
829
            case Zoom:
×
830
                setValue(strVal.toFloat());
×
831
            break;
×
832
            case Shutter:   break;
×
833
            case Gobo:      break;
×
834
            case Undefined: break;
×
835
        }
836
    }
1✔
837

838
    if (attrs.hasAttribute(KXMLQLCPaletteFanning))
1✔
839
    {
840
        setFanningType(stringToFanningType(attrs.value(KXMLQLCPaletteFanning).toString()));
1✔
841

842
        if (attrs.hasAttribute(KXMLQLCPaletteFanLayout))
1✔
843
            setFanningLayout(stringToFanningLayout(attrs.value(KXMLQLCPaletteFanLayout).toString()));
1✔
844

845
        if (attrs.hasAttribute(KXMLQLCPaletteFanAmount))
1✔
846
            setFanningAmount(attrs.value(KXMLQLCPaletteFanAmount).toInt());
1✔
847

848
        if (attrs.hasAttribute(KXMLQLCPaletteFanValue))
1✔
849
        {
850
            QString strVal = attrs.value(KXMLQLCPaletteFanValue).toString();
1✔
851
            switch (m_type)
1✔
852
            {
853
                case Dimmer:
×
854
                case Pan:
855
                case Tilt:
856
                case PanTilt:
857
                case Zoom:
858
                    setFanningValue(strVal.toInt());
×
859
                break;
×
860
                case Color:
1✔
861
                    setFanningValue(strVal);
1✔
862
                break;
1✔
863
                case Shutter:   break;
×
864
                case Gobo:      break;
×
865
                case Undefined: break;
×
866
            }
867
        }
1✔
868
    }
869

870
    return true;
1✔
871
}
1✔
872

873
bool QLCPalette::saveXML(QXmlStreamWriter *doc)
1✔
874
{
875
    Q_ASSERT(doc != NULL);
1✔
876

877
    if (m_values.isEmpty())
1✔
878
    {
879
        qWarning() << "Unable to save a Palette without value!";
×
880
        return false;
×
881
    }
882

883
    /* write a Palette entry */
884
    doc->writeStartElement(KXMLQLCPalette);
2✔
885
    doc->writeAttribute(KXMLQLCPaletteID, QString::number(this->id()));
2✔
886
    doc->writeAttribute(KXMLQLCPaletteType, typeToString(m_type));
2✔
887
    doc->writeAttribute(KXMLQLCPaletteName, this->name());
2✔
888

889
    /* write value */
890
    switch (m_type)
1✔
891
    {
892
        case Dimmer:
×
893
        case Pan:
894
        case Tilt:
895
        case Zoom:
896
        case Color:
897
            doc->writeAttribute(KXMLQLCPaletteValue, value().toString());
×
898
        break;
×
899
        case PanTilt:
1✔
900
            doc->writeAttribute(KXMLQLCPaletteValue,
2✔
901
                                QString("%1,%2").arg(m_values.at(0).toInt()).arg(m_values.at(1).toInt()));
2✔
902
        break;
1✔
903
        case Shutter:   break;
×
904
        case Gobo:      break;
×
905
        case Undefined: break;
×
906
    }
907

908
    /* write fanning */
909
    if (m_fanningType != Flat)
1✔
910
    {
911
        doc->writeAttribute(KXMLQLCPaletteFanning, fanningTypeToString(m_fanningType));
×
912
        doc->writeAttribute(KXMLQLCPaletteFanLayout, fanningLayoutToString(m_fanningLayout));
×
913
        doc->writeAttribute(KXMLQLCPaletteFanAmount, QString::number(m_fanningAmount));
×
914
        doc->writeAttribute(KXMLQLCPaletteFanValue, fanningValue().toString());
×
915
    }
916

917
    doc->writeEndElement();
1✔
918

919
    return true;
1✔
920
}
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