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

mcallegari / qlcplus / 27867971263

20 Jun 2026 10:09AM UTC coverage: 35.268% (-0.1%) from 35.377%
27867971263

push

github

mcallegari
Back to 5.3.0 debug

18433 of 52265 relevant lines covered (35.27%)

41250.48 hits per line

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

40.33
/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_isTemporary(true)
18✔
43
    , m_type(type)
18✔
44
    , m_fanningType(Flat)
18✔
45
    , m_fanningLayout(XAscending)
18✔
46
    , m_fanningAmount(100)
18✔
47
{
48
}
18✔
49

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

60
    return copy;
×
61
}
62

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

66
}
20✔
67

68
/************************************************************************
69
 * Properties
70
 ************************************************************************/
71

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

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

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

87
bool QLCPalette::isTemporary() const
×
88
{
89
    return m_isTemporary;
×
90
}
91

92
void QLCPalette::setTemporary(bool temporary)
2✔
93
{
94
    if (m_isTemporary == temporary)
2✔
95
        return;
×
96

97
    m_isTemporary = temporary;
2✔
98
    emit temporaryChanged();
2✔
99
}
100

101
QLCPalette::PaletteType QLCPalette::type() const
10✔
102
{
103
    return m_type;
10✔
104
}
105

106
QString QLCPalette::typeToString(QLCPalette::PaletteType type)
10✔
107
{
108
    switch (type)
10✔
109
    {
110
        case Dimmer:    return "Dimmer";
1✔
111
        case Color:     return "Color";
1✔
112
        case Pan:       return "Pan";
1✔
113
        case Tilt:      return "Tilt";
1✔
114
        case PanTilt:   return "PanTilt";
2✔
115
        case Shutter:   return "Shutter";
1✔
116
        case Gobo:      return "Gobo";
1✔
117
        case Zoom:      return "Zoom";
1✔
118
        case Undefined: return "";
1✔
119
    }
120

121
    return "";
×
122
}
123

124
QLCPalette::PaletteType QLCPalette::stringToType(const QString &str)
10✔
125
{
126
    if (str == "Dimmer")
10✔
127
        return Dimmer;
1✔
128
    else if (str == "Color")
9✔
129
        return Color;
2✔
130
    else if (str == "Pan")
7✔
131
        return Pan;
1✔
132
    else if (str == "Tilt")
6✔
133
        return Tilt;
1✔
134
    else if (str == "PanTilt")
5✔
135
        return PanTilt;
1✔
136
    else if (str == "Shutter")
4✔
137
        return Shutter;
1✔
138
    else if (str == "Gobo")
3✔
139
        return Gobo;
1✔
140
    else if (str == "Zoom")
2✔
141
        return Zoom;
1✔
142

143
    return Undefined;
1✔
144
}
145

146
QString QLCPalette::iconResource(bool svg) const
8✔
147
{
148
    QString prefix = svg ? "qrc" : "";
8✔
149
    QString ext = svg ? "svg" : "png";
8✔
150

151
    switch(type())
8✔
152
    {
153
        case Dimmer: return QString("%1:/intensity.%2").arg(prefix).arg(ext);
1✔
154
        case Color: return QString("%1:/color.%2").arg(prefix).arg(ext);
1✔
155
        case Pan: return QString("%1:/pan.%2").arg(prefix).arg(ext);
1✔
156
        case Tilt: return QString("%1:/tilt.%2").arg(prefix).arg(ext);
1✔
157
        case PanTilt: return QString("%1:/position.%2").arg(prefix).arg(ext);
1✔
158
        case Shutter: return QString("%1:/shutter.%2").arg(prefix).arg(ext);
1✔
159
        case Gobo: return QString("%1:/gobo.%2").arg(prefix).arg(ext);
1✔
160
        case Zoom: return QString("%1:/beam.%2").arg(prefix).arg(ext);
1✔
161
        default: return "";
×
162
    }
163
}
8✔
164

165
QString QLCPalette::name() const
4✔
166
{
167
    return m_name;
4✔
168
}
169

170
void QLCPalette::setName(const QString &name)
3✔
171
{
172
    if (name == m_name)
3✔
173
        return;
×
174

175
    m_name = QString(name);
3✔
176
    emit nameChanged();
3✔
177
}
178

179
QVariant QLCPalette::value() const
4✔
180
{
181
    if (m_values.isEmpty())
4✔
182
        return QVariant();
×
183

184
    return m_values.first();
4✔
185
}
186

187
int QLCPalette::intValue1() const
×
188
{
189
    if (m_values.isEmpty())
×
190
        return -1;
×
191

192
    return m_values.at(0).toInt();
×
193
}
194

195
int QLCPalette::intValue2() const
×
196
{
197
    if (m_values.count() < 2)
×
198
        return -1;
×
199

200
    return m_values.at(1).toInt();
×
201
}
202

203
float QLCPalette::floatValue1() const
×
204
{
205
    if (m_values.isEmpty())
×
206
        return -1;
×
207

208
    return m_values.at(0).toFloat();
×
209
}
210

211
QString QLCPalette::strValue1() const
×
212
{
213
    if (m_values.isEmpty())
×
214
        return QString();
×
215

216
    return m_values.at(0).toString();
×
217
}
218

219
QColor QLCPalette::rgbValue() const
×
220
{
221
    if (m_values.isEmpty())
×
222
        return QColor();
×
223

224
    QColor rgb, wauv;
×
225
    stringToColor(m_values.at(0).toString(), rgb, wauv);
×
226

227
    return rgb;
×
228
}
229

230
QColor QLCPalette::wauvValue() const
×
231
{
232
    if (m_values.isEmpty())
×
233
        return QColor();
×
234

235
    QColor rgb, wauv;
×
236
    stringToColor(m_values.at(0).toString(), rgb, wauv);
×
237

238
    return wauv;
×
239
}
240

241
void QLCPalette::setValue(QVariant val)
3✔
242
{
243
    m_values.clear();
3✔
244
    m_values.append(val);
3✔
245
}
3✔
246

247
void QLCPalette::setValue(QVariant val1, QVariant val2)
2✔
248
{
249
    m_values.clear();
2✔
250
    m_values.append(val1);
2✔
251
    m_values.append(val2);
2✔
252
}
2✔
253

254
QVariantList QLCPalette::values() const
6✔
255
{
256
    return m_values;
6✔
257
}
258

259
void QLCPalette::setValues(QVariantList values)
×
260
{
261
    m_values = values;
×
262
}
×
263

264
void QLCPalette::resetValues()
×
265
{
266
    m_values.clear();
×
267
}
×
268

269
QList<SceneValue> QLCPalette::valuesFromFixtures(Doc *doc, QList<quint32> fixtures) const
×
270
{
271
    QList<SceneValue> list;
×
272

273
    int fxCount = fixtures.count();
×
274
    // normalized progress in [ 0.0, 1.0 ] range
275
    qreal progress = 0.0;
×
276
    int intFanValue = fanningValue().toInt();
×
277
    FanningType fType = fanningType();
×
278
    FanningLayout fLayout = fanningLayout();
×
279
    MonitorProperties *mProps = doc->monitorProperties();
×
280
    qreal centerCoord = 0.0;
×
281
    qreal maxCenterDistance = 0.0;
×
282

283
    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
284
    {
285
        bool hasCoord = false;
×
286
        qreal minCoord = 0.0;
×
287
        qreal maxCoord = 0.0;
×
288

289
        foreach (quint32 id, fixtures)
×
290
        {
291
            QVector3D pos = mProps->fixturePosition(id, 0, 0);
×
292
            qreal coord = 0.0;
×
293

294
            switch (fLayout)
×
295
            {
296
                case XCentered: coord = pos.x(); break;
×
297
                case YCentered: coord = pos.y(); break;
×
298
                case ZCentered: coord = pos.z(); break;
×
299
                default: break;
×
300
            }
301

302
            if (hasCoord == false)
×
303
            {
304
                minCoord = coord;
×
305
                maxCoord = coord;
×
306
                hasCoord = true;
×
307
            }
308
            else
309
            {
310
                minCoord = qMin(minCoord, coord);
×
311
                maxCoord = qMax(maxCoord, coord);
×
312
            }
313
        }
×
314

315
        centerCoord = (minCoord + maxCoord) / 2.0;
×
316
        maxCenterDistance = qMax(qAbs(minCoord - centerCoord), qAbs(maxCoord - centerCoord));
×
317
    }
318

319
    // sort the fixtures list based on selected layout
320
    std::sort(fixtures.begin(), fixtures.end(),
×
321
        [fLayout, mProps, centerCoord](quint32 a, quint32 b) {
×
322
            QVector3D posA = mProps->fixturePosition(a, 0, 0);
×
323
            QVector3D posB = mProps->fixturePosition(b, 0, 0);
×
324

325
            switch(fLayout)
×
326
            {
327
                case XAscending: return posA.x() < posB.x();
×
328
                case XDescending: return posB.x() < posA.x();
×
329
                case XCentered:
×
330
                {
331
                    qreal distA = qAbs(posA.x() - centerCoord);
×
332
                    qreal distB = qAbs(posB.x() - centerCoord);
×
333
                    return (distA == distB) ? (posA.x() < posB.x()) : (distA < distB);
×
334
                }
335
                case YAscending: return posA.y() < posB.y();
×
336
                case YDescending: return posB.y() < posA.y();
×
337
                case YCentered:
×
338
                {
339
                    qreal distA = qAbs(posA.y() - centerCoord);
×
340
                    qreal distB = qAbs(posB.y() - centerCoord);
×
341
                    return (distA == distB) ? (posA.y() < posB.y()) : (distA < distB);
×
342
                }
343
                case ZAscending: return posA.z() < posB.z();
×
344
                case ZDescending: return posB.z() < posA.z();
×
345
                case ZCentered:
×
346
                {
347
                    qreal distA = qAbs(posA.z() - centerCoord);
×
348
                    qreal distB = qAbs(posB.z() - centerCoord);
×
349
                    return (distA == distB) ? (posA.z() < posB.z()) : (distA < distB);
×
350
                }
351
                default: return false;
×
352
            }
353
        });
354

355
    foreach (quint32 id, fixtures)
×
356
    {
357
        Fixture *fixture = doc->fixture(id);
×
358
        if (fixture == NULL)
×
359
            continue;
×
360

361
        qreal factor = valueFactor(progress);
×
362
        int centeredSign = 1;
×
363

364
        if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
365
        {
366
            QVector3D pos = mProps->fixturePosition(id, 0, 0);
×
367
            qreal coord = 0.0;
×
368

369
            switch (fLayout)
×
370
            {
371
                case XCentered: coord = pos.x(); break;
×
372
                case YCentered: coord = pos.y(); break;
×
373
                case ZCentered: coord = pos.z(); break;
×
374
                default: break;
×
375
            }
376

377
            if (coord > centerCoord)
×
378
                centeredSign = 1;
×
379
            else if (coord < centerCoord)
×
380
                centeredSign = -1;
×
381
            else
382
                centeredSign = 0;
×
383

384
            if (maxCenterDistance > 0.0)
×
385
            {
386
                qreal distance = qAbs(coord - centerCoord);
×
387
                factor = valueFactor(distance / maxCenterDistance);
×
388
            }
389
            else
390
            {
391
                factor = valueFactor(0.0);
×
392
            }
393
        }
394

395
        switch(type())
×
396
        {
397
            case Dimmer:
×
398
            {
399
                int dValue = value().toInt();
×
400
                quint32 masterIntensityChannel = fixture->type() == QLCFixtureDef::Dimmer ?
×
401
                            0 : fixture->masterIntensityChannel();
×
402

403
                if (fType != Flat)
×
404
                    dValue = int((qreal(intFanValue - dValue) * factor) + dValue);
×
405

406
                if (masterIntensityChannel != QLCChannel::invalid())
×
407
                    list << SceneValue(id, masterIntensityChannel, uchar(dValue));
×
408

409
                for (int i = 0; i < fixture->heads(); i++)
×
410
                {
411
                    quint32 headDimmerChannel = fixture->channelNumber(QLCChannel::Intensity, QLCChannel::MSB, i);
×
412
                    if (headDimmerChannel != QLCChannel::invalid())
×
413
                        list << SceneValue(id, headDimmerChannel, uchar(dValue));
×
414
                }
415
            }
416
            break;
×
417
            case Color:
×
418
            {
419

420
                QColor startColor = rgbValue();
×
421
                QColor col = startColor;
×
422
                QColor wauv = wauvValue();
×
423

424
                if (fType != Flat)
×
425
                {
426
                    QColor endColor = fanningValue().value<QColor>();
×
427
                    qreal rDelta = endColor.red() - startColor.red();
×
428
                    qreal gDelta = endColor.green() - startColor.green();
×
429
                    qreal bDelta = endColor.blue() - startColor.blue();
×
430
                    col.setRed(startColor.red() + qRound(rDelta * factor));
×
431
                    col.setGreen(startColor.green() + qRound(gDelta * factor));
×
432
                    col.setBlue(startColor.blue() + qRound(bDelta * factor));
×
433
                }
434

435
                for (int i = 0; i < fixture->heads(); i++)
×
436
                {
437
                    QVector<quint32> rgbCh = fixture->rgbChannels(i);
×
438
                    if (rgbCh.size() == 3)
×
439
                    {
440
                        list << SceneValue(id, rgbCh.at(0), uchar(col.red()));
×
441
                        list << SceneValue(id, rgbCh.at(1), uchar(col.green()));
×
442
                        list << SceneValue(id, rgbCh.at(2), uchar(col.blue()));
×
443
                    }
444
                    QVector<quint32> cmyCh = fixture->cmyChannels(i);
×
445
                    if (cmyCh.size() == 3)
×
446
                    {
447
                        list << SceneValue(id, cmyCh.at(0), uchar(col.cyan()));
×
448
                        list << SceneValue(id, cmyCh.at(1), uchar(col.magenta()));
×
449
                        list << SceneValue(id, cmyCh.at(2), uchar(col.yellow()));
×
450
                    }
451

452
                    if (wauv.isValid())
×
453
                    {
454
                        quint32 channel = fixture->channelNumber(QLCChannel::White, QLCChannel::MSB, i);
×
455
                        if (channel != QLCChannel::invalid())
×
456
                            list << SceneValue(id, channel, uchar(wauv.red()));
×
457
                        channel = fixture->channelNumber(QLCChannel::Amber, QLCChannel::MSB, i);
×
458
                        if (channel != QLCChannel::invalid())
×
459
                            list << SceneValue(id, channel, uchar(wauv.green()));
×
460
                        channel = fixture->channelNumber(QLCChannel::UV, QLCChannel::MSB, i);
×
461
                        if (channel != QLCChannel::invalid())
×
462
                            list << SceneValue(id, channel, uchar(wauv.blue()));
×
463
                    }
464
                }
×
465
            }
466
            break;
×
467
            case Pan:
×
468
            {
469
                int degrees = 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::Pan, degrees);
×
480
            }
481
            break;
×
482
            case Tilt:
×
483
            {
484
                int degrees = m_values.count() == 2 ? m_values.at(1).toInt() : value().toInt();
×
485

486
                if (fType != Flat)
×
487
                {
488
                    int offset = int(qreal(intFanValue) * factor);
×
489
                    if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
490
                        offset *= centeredSign;
×
491
                    degrees = int(qreal(degrees) + qreal(offset));
×
492
                }
493

494
                list << fixture->positionToValues(QLCChannel::Tilt, degrees);
×
495
            }
496
            break;
×
497
            case PanTilt:
×
498
            {
499
                if (m_values.count() == 2)
×
500
                {
501
                    int panDegrees = m_values.at(0).toInt();
×
502
                    int tiltDegrees = m_values.at(1).toInt();
×
503

504
                    if (fType != Flat)
×
505
                    {
506
                        int offset = int(qreal(intFanValue) * factor);
×
507
                        if (fLayout == XCentered || fLayout == YCentered || fLayout == ZCentered)
×
508
                            offset *= centeredSign;
×
509
                        panDegrees = int((qreal(panDegrees) + qreal(offset)));
×
510
                        tiltDegrees = int((qreal(tiltDegrees) + qreal(offset)));
×
511
                    }
512

513
                    list << fixture->positionToValues(QLCChannel::Pan, panDegrees);
×
514
                    list << fixture->positionToValues(QLCChannel::Tilt, tiltDegrees);
×
515
                }
516
            }
517
            break;
×
518
            case Shutter:
×
519
            {
520
                quint32 shCh = fixture->channelNumber(QLCChannel::Shutter, QLCChannel::MSB);
×
521
                if (shCh != QLCChannel::invalid())
×
522
                    list << SceneValue(id, shCh, uchar(value().toUInt()));
×
523
            }
524
            break;
×
525
            case Gobo:
×
526
            {
527
                quint32 goboCh = fixture->channelNumber(QLCChannel::Gobo, QLCChannel::MSB);
×
528
                if (goboCh != QLCChannel::invalid())
×
529
                    list << SceneValue(id, goboCh, uchar(value().toUInt()));
×
530
            }
531
            break;
×
532
            case Zoom:
×
533
            {
534
                for (int i = 0; i < int(fixture->channels()); i++)
×
535
                {
536
                    const QLCChannel *ch = fixture->channel(quint32(i));
×
537
                    if (ch == nullptr)
×
538
                        continue;
×
539

540
                    if (ch->group() == QLCChannel::Beam &&
×
541
                        (ch->preset() == QLCChannel::BeamZoomSmallBig || ch->preset() == QLCChannel::BeamZoomBigSmall))
×
542
                    {
543
                        list << fixture->zoomToValues(value().toFloat(), false);
×
544
                        break;
×
545
                    }
546
                }
547
            }
548
            break;
×
549
            case Undefined:
×
550
            break;
×
551
        }
552

553
        progress += (1.0 / qreal(fxCount - 1));
×
554
    }
×
555

556
    return list;
×
557
}
×
558

559
QList<SceneValue> QLCPalette::valuesFromFixtureGroups(Doc *doc, QList<quint32> groups) const
×
560
{
561
    QList<quint32> fixturesList;
×
562

563
    foreach (quint32 id, groups)
×
564
    {
565
        FixtureGroup *group = doc->fixtureGroup(id);
×
566
        if (group == NULL)
×
567
            continue;
×
568

569
        fixturesList.append(group->fixtureList());
×
570
    }
×
571

572
    return valuesFromFixtures(doc, fixturesList);
×
573
}
×
574

575
qreal QLCPalette::valueFactor(qreal progress) const
×
576
{
577
    qreal factor = 1.0;
×
578
    qreal normalizedAmount = qreal(m_fanningAmount) / 100.0;
×
579

580
    switch (m_fanningType)
×
581
    {
582
        case Flat:
×
583
            // nothing to do. Factor is always 1.0
584
        break;
×
585
        case Linear:
×
586
        {
587
            if (normalizedAmount < 1.0)
×
588
            {
589
                if (progress > normalizedAmount)
×
590
                    factor = 1.0;
×
591
                else
592
                    factor = progress * normalizedAmount;
×
593
            }
594
            else if (normalizedAmount > 1.0)
×
595
            {
596
                factor = progress / normalizedAmount;
×
597
            }
598
            else
599
            {
600
                factor = progress;
×
601
            }
602
        }
603
        break;
×
604
        case Sine:
×
605
        {
606
            qreal degrees = (progress * 360.0) + 270.0;
×
607
            factor = (qSin(normalizedAmount * qDegreesToRadians(degrees)) + 1.0) / 2.0;
×
608
        }
609
        break;
×
610
        case Square:
×
611
        {
612
            factor = qSin(normalizedAmount * qDegreesToRadians(progress * 360.0)) < 0 ? 1 : 0;
×
613
        }
614
        break;
×
615
        case Saw:
×
616
        break;
×
617
    }
618

619
    return factor;
×
620
}
621

622
/************************************************************************
623
 * Fanning
624
 ************************************************************************/
625

626
QLCPalette::FanningType QLCPalette::fanningType() const
2✔
627
{
628
    return m_fanningType;
2✔
629
}
630

631
void QLCPalette::setFanningType(QLCPalette::FanningType type)
1✔
632
{
633
    if (type == m_fanningType)
1✔
634
        return;
×
635

636
    m_fanningType = type;
1✔
637

638
    emit fanningTypeChanged();
1✔
639
}
640

641
QString QLCPalette::fanningTypeToString(QLCPalette::FanningType type)
5✔
642
{
643
    switch (type)
5✔
644
    {
645
        case Flat:      return "Flat";
1✔
646
        case Linear:    return "Linear";
1✔
647
        case Sine:      return "Sine";
1✔
648
        case Square:    return "Square";
1✔
649
        case Saw:       return "Saw";
1✔
650
    }
651

652
    return "";
×
653
}
654

655
QLCPalette::FanningType QLCPalette::stringToFanningType(const QString &str)
7✔
656
{
657
    if (str == "Flat")
7✔
658
        return Flat;
1✔
659
    else if (str == "Linear")
6✔
660
        return Linear;
2✔
661
    else if (str == "Sine")
4✔
662
        return Sine;
1✔
663
    else if (str == "Square")
3✔
664
        return Square;
1✔
665
    else if (str == "Saw")
2✔
666
        return Saw;
1✔
667

668
    return Flat;
1✔
669
}
670

671
QLCPalette::FanningLayout QLCPalette::fanningLayout() const
2✔
672
{
673
    return m_fanningLayout;
2✔
674
}
675

676
void QLCPalette::setFanningLayout(QLCPalette::FanningLayout layout)
1✔
677
{
678
    if (layout == m_fanningLayout)
1✔
679
        return;
1✔
680

681
    m_fanningLayout = layout;
×
682

683
    emit fanningLayoutChanged();
×
684
}
685

686
QString QLCPalette::fanningLayoutToString(QLCPalette::FanningLayout layout)
9✔
687
{
688
    switch (layout)
9✔
689
    {
690
        case XAscending:    return "XAscending";
1✔
691
        case XDescending:   return "XDescending";
1✔
692
        case XCentered:     return "XCentered";
1✔
693
        case YAscending:    return "YAscending";
1✔
694
        case YDescending:   return "YDescending";
1✔
695
        case YCentered:     return "YCentered";
1✔
696
        case ZAscending:    return "ZAscending";
1✔
697
        case ZDescending:   return "ZDescending";
1✔
698
        case ZCentered:     return "ZCentered";
1✔
699
    }
700

701
    return "";
×
702
}
703

704
QLCPalette::FanningLayout QLCPalette::stringToFanningLayout(const QString &str)
11✔
705
{
706
    if (str == "XAscending")
11✔
707
        return XAscending;
1✔
708
    else if (str == "XDescending")
10✔
709
        return XDescending;
1✔
710
    else if (str == "XCentered")
9✔
711
        return XCentered;
1✔
712
    else     if (str == "YAscending")
8✔
713
        return YAscending;
1✔
714
    else if (str == "YDescending")
7✔
715
        return YDescending;
1✔
716
    else if (str == "YCentered")
6✔
717
        return YCentered;
1✔
718
    else if (str == "ZAscending")
5✔
719
        return ZAscending;
1✔
720
    else if (str == "ZDescending")
4✔
721
        return ZDescending;
1✔
722
    else if (str == "ZCentered")
3✔
723
        return ZCentered;
1✔
724

725
    return XAscending;
2✔
726
}
727

728
int QLCPalette::fanningAmount() const
3✔
729
{
730
    return m_fanningAmount;
3✔
731
}
732

733
void QLCPalette::setFanningAmount(int amount)
2✔
734
{
735
    if (amount == m_fanningAmount)
2✔
736
        return;
×
737

738
    m_fanningAmount = amount;
2✔
739

740
    emit fanningAmountChanged();
2✔
741
}
742

743
QVariant QLCPalette::fanningValue() const
2✔
744
{
745
    return m_fanningValue;
2✔
746
}
747

748
void QLCPalette::setFanningValue(QVariant value)
1✔
749
{
750
    if (value == m_fanningValue)
1✔
751
        return;
×
752

753
    m_fanningValue = value;
1✔
754

755
    emit fanningValueChanged();
1✔
756
}
757

758
/************************************************************************
759
 * Color helpers
760
 ************************************************************************/
761

762
QString QLCPalette::colorToString(QColor rgb, QColor wauv)
2✔
763
{
764
    QString final = rgb.name();
2✔
765
    final.append(wauv.name().right(6));
2✔
766
    return final;
2✔
767
}
×
768

769
bool QLCPalette::stringToColor(const QString& str, QColor &rgb, QColor &wauv)
3✔
770
{
771
    // string must be like #rrggbb or #rrggbbwwaauv
772
    if (str.length() != 7 && str.length() != 13)
3✔
773
        return false;
1✔
774

775
    rgb = QColor(str.left(7));
2✔
776

777
    if (str.length() == 13)
2✔
778
        wauv = QColor("#" + str.right(6));
2✔
779
    else
780
        wauv = QColor();
×
781

782
    return true;
2✔
783
}
784

785
/************************************************************************
786
 * Load & Save
787
 ************************************************************************/
788

789
bool QLCPalette::loader(QXmlStreamReader &xmlDoc, Doc *doc)
×
790
{
791
    QLCPalette *palette = new QLCPalette(Dimmer, doc);
×
792
    Q_ASSERT(palette != NULL);
×
793

794
    if (palette->loadXML(xmlDoc) == true)
×
795
    {
796
        doc->addPalette(palette, palette->id());
×
797
    }
798
    else
799
    {
800
        qWarning() << Q_FUNC_INFO << "QLCPalette" << palette->name() << "cannot be loaded.";
×
801
        delete palette;
×
802
        return false;
×
803
    }
804

805
    return true;
×
806
}
807

808
bool QLCPalette::loadXML(QXmlStreamReader &doc)
2✔
809
{
810
    if (doc.name() != KXMLQLCPalette)
2✔
811
    {
812
        qWarning() << Q_FUNC_INFO << "Palette node not found";
1✔
813
        return false;
1✔
814
    }
815

816
    QXmlStreamAttributes attrs = doc.attributes();
1✔
817

818
    bool ok = false;
1✔
819
    quint32 id = attrs.value(KXMLQLCPaletteID).toString().toUInt(&ok);
1✔
820
    if (ok == false)
1✔
821
    {
822
        qWarning() << "Invalid Palette ID:" << attrs.value(KXMLQLCPaletteID).toString();
×
823
        return false;
×
824
    }
825

826
    setID(id);
1✔
827

828
    if (attrs.hasAttribute(KXMLQLCPaletteType) == false)
1✔
829
    {
830
        qWarning() << "Palette type not found!";
×
831
        return false;
×
832
    }
833

834
    m_type = stringToType(attrs.value(KXMLQLCPaletteType).toString());
1✔
835

836
    if (attrs.hasAttribute(KXMLQLCPaletteName))
1✔
837
        setName(attrs.value(KXMLQLCPaletteName).toString());
1✔
838

839
    if (attrs.hasAttribute(KXMLQLCPaletteValue))
1✔
840
    {
841
        QString strVal = attrs.value(KXMLQLCPaletteValue).toString();
1✔
842
        switch (m_type)
1✔
843
        {
844
            case Pan:
×
845
            case Tilt:
846
                setValue(strVal.toInt());
×
847
            break;
×
848
            case Color:
1✔
849
                setValue(strVal);
1✔
850
            break;
1✔
851
            case PanTilt:
×
852
            {
853
                QStringList posList = strVal.split(",");
×
854
                if (posList.count() == 2)
×
855
                    setValue(posList.at(0).toInt(), posList.at(1).toInt());
×
856
            }
×
857
            break;
×
858
            case Dimmer:
×
859
            case Zoom:
860
                setValue(strVal.toFloat());
×
861
            break;
×
862
            case Shutter:   break;
×
863
            case Gobo:      break;
×
864
            case Undefined: break;
×
865
        }
866
    }
1✔
867

868
    if (attrs.hasAttribute(KXMLQLCPaletteFanning))
1✔
869
    {
870
        setFanningType(stringToFanningType(attrs.value(KXMLQLCPaletteFanning).toString()));
1✔
871

872
        if (attrs.hasAttribute(KXMLQLCPaletteFanLayout))
1✔
873
            setFanningLayout(stringToFanningLayout(attrs.value(KXMLQLCPaletteFanLayout).toString()));
1✔
874

875
        if (attrs.hasAttribute(KXMLQLCPaletteFanAmount))
1✔
876
            setFanningAmount(attrs.value(KXMLQLCPaletteFanAmount).toInt());
1✔
877

878
        if (attrs.hasAttribute(KXMLQLCPaletteFanValue))
1✔
879
        {
880
            QString strVal = attrs.value(KXMLQLCPaletteFanValue).toString();
1✔
881
            switch (m_type)
1✔
882
            {
883
                case Dimmer:
×
884
                case Pan:
885
                case Tilt:
886
                case PanTilt:
887
                case Zoom:
888
                    setFanningValue(strVal.toInt());
×
889
                break;
×
890
                case Color:
1✔
891
                    setFanningValue(strVal);
1✔
892
                break;
1✔
893
                case Shutter:   break;
×
894
                case Gobo:      break;
×
895
                case Undefined: break;
×
896
            }
897
        }
1✔
898
    }
899

900
    return true;
1✔
901
}
1✔
902

903
bool QLCPalette::saveXML(QXmlStreamWriter *doc) const
1✔
904
{
905
    Q_ASSERT(doc != NULL);
1✔
906

907
    if (m_values.isEmpty())
1✔
908
    {
909
        qWarning() << "Unable to save a Palette without value!";
×
910
        return false;
×
911
    }
912

913
    /* write a Palette entry */
914
    doc->writeStartElement(KXMLQLCPalette);
2✔
915
    doc->writeAttribute(KXMLQLCPaletteID, QString::number(this->id()));
2✔
916
    doc->writeAttribute(KXMLQLCPaletteType, typeToString(m_type));
2✔
917
    doc->writeAttribute(KXMLQLCPaletteName, this->name());
2✔
918

919
    /* write value */
920
    switch (m_type)
1✔
921
    {
922
        case Dimmer:
×
923
        case Pan:
924
        case Tilt:
925
        case Zoom:
926
        case Color:
927
            doc->writeAttribute(KXMLQLCPaletteValue, value().toString());
×
928
        break;
×
929
        case PanTilt:
1✔
930
            doc->writeAttribute(KXMLQLCPaletteValue,
2✔
931
                                QString("%1,%2").arg(m_values.at(0).toInt()).arg(m_values.at(1).toInt()));
2✔
932
        break;
1✔
933
        case Shutter:   break;
×
934
        case Gobo:      break;
×
935
        case Undefined: break;
×
936
    }
937

938
    /* write fanning */
939
    if (m_fanningType != Flat)
1✔
940
    {
941
        doc->writeAttribute(KXMLQLCPaletteFanning, fanningTypeToString(m_fanningType));
×
942
        doc->writeAttribute(KXMLQLCPaletteFanLayout, fanningLayoutToString(m_fanningLayout));
×
943
        doc->writeAttribute(KXMLQLCPaletteFanAmount, QString::number(m_fanningAmount));
×
944
        doc->writeAttribute(KXMLQLCPaletteFanValue, fanningValue().toString());
×
945
    }
946

947
    doc->writeEndElement();
1✔
948

949
    return true;
1✔
950
}
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