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

mcallegari / qlcplus / 13633248611

03 Mar 2025 02:31PM UTC coverage: 31.871% (+0.4%) from 31.5%
13633248611

push

github

web-flow
actions: add chrpath to profile

14689 of 46089 relevant lines covered (31.87%)

26426.11 hits per line

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

62.0
/engine/src/qlcchannel.cpp
1
/*
2
  Q Light Controller Plus
3
  qlcchannel.cpp
4

5
  Copyright (C) Heikki Junnila
6
                Massimo Callegari
7

8
  Licensed under the Apache License, Version 2.0 (the "License");
9
  you may not use this file except in compliance with the License.
10
  You may obtain a copy of the License at
11

12
      http://www.apache.org/licenses/LICENSE-2.0.txt
13

14
  Unless required by applicable law or agreed to in writing, software
15
  distributed under the License is distributed on an "AS IS" BASIS,
16
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
  See the License for the specific language governing permissions and
18
  limitations under the License.
19
*/
20

21
#include <QXmlStreamReader>
22
#include <QStringList>
23
#include <QMetaEnum>
24
#include <QPainter>
25
#include <iostream>
26
#include <QString>
27
#include <QDebug>
28
#include <QFile>
29

30
#include "qlcchannel.h"
31
#include "qlccapability.h"
32

33
#define KXMLQLCChannelGroupIntensity   QString("Intensity")
34
#define KXMLQLCChannelGroupColour      QString("Colour")
35
#define KXMLQLCChannelGroupGobo        QString("Gobo")
36
#define KXMLQLCChannelGroupPrism       QString("Prism")
37
#define KXMLQLCChannelGroupShutter     QString("Shutter")
38
#define KXMLQLCChannelGroupBeam        QString("Beam")
39
#define KXMLQLCChannelGroupSpeed       QString("Speed")
40
#define KXMLQLCChannelGroupEffect      QString("Effect")
41
#define KXMLQLCChannelGroupPan         QString("Pan")
42
#define KXMLQLCChannelGroupTilt        QString("Tilt")
43
#define KXMLQLCChannelGroupMaintenance QString("Maintenance")
44
#define KXMLQLCChannelGroupNothing     QString("Nothing")
45

46
#define KXMLQLCChannelColourGeneric    QString("Generic")
47
#define KXMLQLCChannelColourRed        QString("Red")
48
#define KXMLQLCChannelColourGreen      QString("Green")
49
#define KXMLQLCChannelColourBlue       QString("Blue")
50
#define KXMLQLCChannelColourCyan       QString("Cyan")
51
#define KXMLQLCChannelColourMagenta    QString("Magenta")
52
#define KXMLQLCChannelColourYellow     QString("Yellow")
53
#define KXMLQLCChannelColourAmber      QString("Amber")
54
#define KXMLQLCChannelColourWhite      QString("White")
55
#define KXMLQLCChannelColourUV         QString("UV")
56
#define KXMLQLCChannelColourLime       QString("Lime")
57
#define KXMLQLCChannelColourIndigo     QString("Indigo")
58

59
QLCChannel::QLCChannel(QObject *parent)
1,779✔
60
    : QObject(parent)
61
    , m_preset(Custom)
1,779✔
62
    , m_group(Intensity)
1,779✔
63
    , m_defaultValue(0)
1,779✔
64
    , m_controlByte(MSB)
1,779✔
65
    , m_colour(NoColour)
1,779✔
66
{
67
}
1,779✔
68

69
QLCChannel *QLCChannel::createCopy()
2✔
70
{
71
    QLCChannel *copy = new QLCChannel();
2✔
72
    copy->setPreset(this->preset());
2✔
73
    if (this->preset() != Custom)
2✔
74
    {
75
        copy->setName(this->name());
×
76
        copy->addPresetCapability();
×
77
    }
78
    else
79
    {
80
        copy->setGroup(this->group());
2✔
81
        copy->setControlByte(this->controlByte());
2✔
82
        copy->setColour(this->colour());
2✔
83
        copy->setName(this->name());
2✔
84

85
        QListIterator<QLCCapability*> it(this->capabilities());
2✔
86
        while (it.hasNext() == true)
10✔
87
            copy->addCapability(it.next()->createCopy());
8✔
88
    }
89
    copy->setDefaultValue(this->defaultValue());
2✔
90

91
    return copy;
2✔
92
}
93

94
QLCChannel::~QLCChannel()
1,630✔
95
{
96
    while (m_capabilities.isEmpty() == false)
4,735✔
97
        delete m_capabilities.takeFirst();
3,103✔
98
}
1,630✔
99

100
QLCChannel& QLCChannel::operator=(const QLCChannel& channel)
×
101
{
102
    if (this != &channel)
×
103
    {
104
        QListIterator<QLCCapability*> it(channel.m_capabilities);
×
105

106
        m_name = channel.m_name;
×
107
        m_preset = channel.m_preset;
×
108
        m_group = channel.m_group;
×
109
        m_defaultValue = channel.m_defaultValue;
×
110
        m_controlByte = channel.m_controlByte;
×
111
        m_colour = channel.m_colour;
×
112

113
        /* Clear old capabilities */
114
        while (m_capabilities.isEmpty() == false)
×
115
            delete m_capabilities.takeFirst();
×
116

117
        /* Copy new capabilities from the other channel */
118
        while (it.hasNext() == true)
×
119
            m_capabilities.append(it.next()->createCopy());
×
120
    }
121

122
    return *this;
×
123
}
124

125
quint32 QLCChannel::invalid()
6,919,405✔
126
{
127
    return UINT_MAX;
6,919,405✔
128
}
129

130
/*********************************************************************
131
 * Presets
132
 *********************************************************************/
133

134
QString QLCChannel::presetToString(QLCChannel::Preset preset)
×
135
{
136
    int index = staticMetaObject.indexOfEnumerator("Preset");
×
137
    return staticMetaObject.enumerator(index).valueToKey(preset);
×
138
}
139

140
QLCChannel::Preset QLCChannel::stringToPreset(const QString &preset)
490✔
141
{
142
    int index = staticMetaObject.indexOfEnumerator("Preset");
490✔
143
    return Preset(staticMetaObject.enumerator(index).keyToValue(preset.toStdString().c_str()));
490✔
144
}
145

146
QLCChannel::Preset QLCChannel::preset() const
8✔
147
{
148
    return m_preset;
8✔
149
}
150

151
/* please see
152
https://github.com/mcallegari/qlcplus/wiki/Fixture-definition-presets
153
when changing this function */
154
void QLCChannel::setPreset(QLCChannel::Preset preset)
492✔
155
{
156
    if (preset == m_preset)
492✔
157
        return;
2✔
158

159
    m_preset = preset;
490✔
160
    emit presetChanged();
490✔
161

162
    if (preset == Custom)
490✔
163
        return;
164

165
    Group grp = Intensity;
166
    PrimaryColour col = NoColour;
167
    ControlByte cb = MSB;
168
    QString prname;
169

170
    switch (preset)
490✔
171
    {
172
        case IntensityMasterDimmer:
30✔
173
            prname = "Master dimmer";
30✔
174
        break;
175
        case IntensityMasterDimmerFine:
10✔
176
            prname = "Master dimmer fine";
10✔
177
            cb = LSB;
178
        break;
179
        case IntensityDimmer:
37✔
180
            prname = "Dimmer";
37✔
181
        break;
182
        case IntensityDimmerFine:
×
183
            prname = "Dimmer fine";
×
184
            cb = LSB;
185
        break;
186
        case IntensityRed:
72✔
187
            prname = KXMLQLCChannelColourRed;
72✔
188
            col = Red;
189
        break;
72✔
190
        case IntensityRedFine:
10✔
191
            prname = KXMLQLCChannelColourRed + " fine";
10✔
192
            col = Red;
193
            cb = LSB;
194
        break;
10✔
195
        case IntensityGreen:
72✔
196
            prname = KXMLQLCChannelColourGreen;
72✔
197
            col = Green;
198
        break;
72✔
199
        case IntensityGreenFine:
10✔
200
            prname = KXMLQLCChannelColourGreen + " fine";
10✔
201
            col = Green;
202
            cb = LSB;
203
        break;
10✔
204
        case IntensityBlue:
72✔
205
            prname = KXMLQLCChannelColourBlue;
72✔
206
            col = Blue;
207
        break;
72✔
208
        case IntensityBlueFine:
10✔
209
            prname = KXMLQLCChannelColourBlue + " fine";
10✔
210
            col = Blue;
211
            cb = LSB;
212
        break;
10✔
213
        case IntensityCyan:
4✔
214
            prname = KXMLQLCChannelColourCyan;
4✔
215
            col = Cyan;
216
        break;
4✔
217
        case IntensityCyanFine:
×
218
            prname = KXMLQLCChannelColourCyan + " fine";
×
219
            col = Cyan;
220
            cb = LSB;
221
        break;
×
222
        case IntensityMagenta:
4✔
223
            prname = KXMLQLCChannelColourMagenta;
4✔
224
            col = Magenta;
225
        break;
4✔
226
        case IntensityMagentaFine:
×
227
            prname = KXMLQLCChannelColourMagenta + " fine";
×
228
            col = Magenta;
229
            cb = LSB;
230
        break;
×
231
        case IntensityYellow:
4✔
232
            prname = KXMLQLCChannelColourYellow;
4✔
233
            col = Yellow;
234
        break;
4✔
235
        case IntensityYellowFine:
×
236
            prname = KXMLQLCChannelColourYellow + " fine";
×
237
            col = Yellow;
238
            cb = LSB;
239
        break;
×
240
        case IntensityAmber:
×
241
            prname = KXMLQLCChannelColourAmber;
×
242
            col = Amber;
243
        break;
×
244
        case IntensityAmberFine:
×
245
            prname = KXMLQLCChannelColourAmber + " fine";
×
246
            col = Amber;
247
            cb = LSB;
248
        break;
×
249
        case IntensityWhite:
19✔
250
            prname = KXMLQLCChannelColourWhite;
19✔
251
            col = White;
252
        break;
19✔
253
        case IntensityWhiteFine:
×
254
            prname = KXMLQLCChannelColourWhite + " fine";
×
255
            col = White;
256
            cb = LSB;
257
        break;
×
258
        case IntensityUV:
×
259
            prname = KXMLQLCChannelColourUV;
×
260
            col = UV;
261
        break;
×
262
        case IntensityUVFine:
×
263
            prname = KXMLQLCChannelColourUV + " fine";
×
264
            col = UV;
265
            cb = LSB;
266
        break;
×
267
        case IntensityIndigo:
×
268
            prname = KXMLQLCChannelColourIndigo;
×
269
            col = Indigo;
270
        break;
×
271
        case IntensityIndigoFine:
×
272
            prname = KXMLQLCChannelColourIndigo + " fine";
×
273
            col = Indigo;
274
            cb = LSB;
275
        break;
×
276
        case IntensityLime:
×
277
            prname = KXMLQLCChannelColourLime;
×
278
            col = Lime;
279
        break;
×
280
        case IntensityLimeFine:
×
281
            prname = KXMLQLCChannelColourLime + " fine";
×
282
            col = Lime;
283
            cb = LSB;
284
        break;
×
285
        case IntensityHue:
×
286
            prname = "Hue";
×
287
            //col = Hue;
288
        break;
289
        case IntensityHueFine:
×
290
            prname = "Hue fine";
×
291
            //col = Hue;
292
            cb = LSB;
293
        break;
294
        case IntensitySaturation:
×
295
            prname = "Saturation";
×
296
            //col = Saturation;
297
        break;
298
        case IntensitySaturationFine:
×
299
            prname = "Saturation fine";
×
300
            //col = Saturation;
301
            cb = LSB;
302
        break;
303
        case IntensityLightness:
×
304
            prname = "Lightness";
×
305
            //col = Lightness;
306
        break;
307
        case IntensityLightnessFine:
×
308
            prname = "Lightness fine";
×
309
            //col = Lightness;
310
            cb = LSB;
311
        break;
312
        case IntensityValue:
×
313
            prname = "Value";
×
314
            //col = Value;
315
        break;
316
        case IntensityValueFine:
×
317
            prname = "Value fine";
×
318
            //col = Value;
319
            cb = LSB;
320
        break;
321
        case PositionPan:
38✔
322
            grp = Pan;
323
            prname = KXMLQLCChannelGroupPan;
38✔
324
        break;
38✔
325
        case PositionPanFine:
15✔
326
            grp = Pan;
327
            prname = KXMLQLCChannelGroupPan + " fine";
15✔
328
            cb = LSB;
329
        break;
15✔
330
        case PositionTilt:
40✔
331
            grp = Tilt;
332
            prname = KXMLQLCChannelGroupTilt;
40✔
333
        break;
40✔
334
        case PositionTiltFine:
20✔
335
            grp = Tilt;
336
            prname = KXMLQLCChannelGroupTilt + " fine";
20✔
337
            cb = LSB;
338
        break;
20✔
339
        case PositionXAxis:
×
340
            grp = Pan;
341
            prname = "X Axis";
×
342
        break;
343
        case PositionYAxis:
×
344
            grp = Tilt;
345
            prname = "Y Axis";
×
346
        break;
347
        case SpeedPanSlowFast:
1✔
348
        case SpeedPanFastSlow:
349
            grp = Speed;
350
            prname = "Pan speed";
1✔
351
        break;
352
        case SpeedTiltSlowFast:
6✔
353
        case SpeedTiltFastSlow:
354
            grp = Speed;
355
            prname = "Tilt speed";
6✔
356
        break;
357
        case SpeedPanTiltSlowFast:
5✔
358
        case SpeedPanTiltFastSlow:
359
            grp = Speed;
360
            prname = "Pan/Tilt speed";
5✔
361
        break;
362
        case ColorMacro:
×
363
            grp = Colour;
364
            prname = "Color macro";
×
365
        break;
366
        case ColorWheel:
×
367
            grp = Colour;
368
            prname = "Color wheel";
×
369
        break;
370
        case ColorWheelFine:
×
371
            grp = Colour;
372
            prname = "Color wheel fine";
×
373
            cb = LSB;
374
        break;
375
        case ColorRGBMixer:
×
376
            grp = Colour;
377
            prname = "RGB mixer";
×
378
        break;
379
        case ColorCTOMixer:
×
380
            grp = Colour;
381
            prname = "CTO mixer";
×
382
        break;
383
        case ColorCTCMixer:
×
384
            grp = Colour;
385
            prname = "CTC mixer";
×
386
        break;
387
        case ColorCTBMixer:
×
388
            grp = Colour;
389
            prname = "CTB mixer";
×
390
        break;
391
        case GoboWheel:
×
392
            grp = Gobo;
393
            prname = "Gobo wheel";
×
394
        break;
395
        case GoboWheelFine:
×
396
            grp = Gobo;
397
            prname = "Gobo wheel fine";
×
398
            cb = LSB;
399
        break;
400
        case GoboIndex:
×
401
            grp = Gobo;
402
            prname = "Gobo index";
×
403
        break;
404
        case GoboIndexFine:
×
405
            grp = Gobo;
406
            prname = "Gobo index fine";
×
407
            cb = LSB;
408
        break;
409
        case ShutterStrobeSlowFast:
3✔
410
        case ShutterStrobeFastSlow:
411
            grp = Shutter;
412
            prname = "Strobe";
3✔
413
        break;
414
        case ShutterIrisMinToMax:
×
415
        case ShutterIrisMaxToMin:
416
            grp = Shutter;
417
            prname = "Iris";
×
418
        break;
419
        case ShutterIrisFine:
×
420
            grp = Shutter;
421
            prname = "Iris fine";
×
422
            cb = LSB;
423
        break;
424
        case BeamFocusNearFar:
4✔
425
        case BeamFocusFarNear:
426
            grp = Beam;
427
            prname = "Focus";
4✔
428
        break;
429
        case BeamFocusFine:
×
430
            grp = Beam;
431
            prname = "Focus fine";
×
432
            cb = LSB;
433
        break;
434
        case BeamZoomSmallBig:
3✔
435
        case BeamZoomBigSmall:
436
            grp = Beam;
437
            prname = "Zoom";
3✔
438
        break;
439
        case BeamZoomFine:
×
440
            grp = Beam;
441
            prname = "Zoom fine";
×
442
            cb = LSB;
443
        break;
444
        case PrismRotationFastSlow:
×
445
        case PrismRotationSlowFast:
446
            grp = Prism;
447
            prname = "Prism rotation";
×
448
        break;
449
        case NoFunction:
1✔
450
            grp = Nothing;
451
            prname = "No function";
1✔
452
        break;
453
        default:
454
        break;
455
    }
456

457
    if (name().isEmpty())
490✔
458
        setName(prname);
×
459
    setGroup(grp);
490✔
460
    setColour(col);
490✔
461
    setControlByte(cb);
490✔
462
}
490✔
463

464
/* please see
465
https://github.com/mcallegari/qlcplus/wiki/Fixture-definition-presets
466
when changing this function */
467
QLCCapability *QLCChannel::addPresetCapability()
490✔
468
{
469
    QLCCapability *cap = new QLCCapability();
980✔
470
    switch (m_preset)
490✔
471
    {
472
        case IntensityMasterDimmer:
67✔
473
        case IntensityDimmer:
474
            cap->setName(name() + " (0 - 100%)");
67✔
475
        break;
67✔
476
        case IntensityRed:
247✔
477
        case IntensityGreen:
478
        case IntensityBlue:
479
        case IntensityCyan:
480
        case IntensityMagenta:
481
        case IntensityYellow:
482
        case IntensityAmber:
483
        case IntensityWhite:
484
        case IntensityUV:
485
        case IntensityIndigo:
486
        case IntensityLime:
487
        case IntensityHue:
488
        case IntensitySaturation:
489
        case IntensityLightness:
490
        case IntensityValue:
491
            cap->setName(name() + " intensity (0 - 100%)");
247✔
492
        break;
247✔
493
        case IntensityMasterDimmerFine:
154✔
494
        case IntensityDimmerFine:
495
        case IntensityRedFine:
496
        case IntensityGreenFine:
497
        case IntensityBlueFine:
498
        case IntensityCyanFine:
499
        case IntensityMagentaFine:
500
        case IntensityYellowFine:
501
        case IntensityAmberFine:
502
        case IntensityWhiteFine:
503
        case IntensityUVFine:
504
        case IntensityIndigoFine:
505
        case IntensityLimeFine:
506
        case IntensityHueFine:
507
        case IntensitySaturationFine:
508
        case IntensityLightnessFine:
509
        case IntensityValueFine:
510
        case PositionPan:
511
        case PositionPanFine:
512
        case PositionTilt:
513
        case PositionTiltFine:
514
        case PositionXAxis:
515
        case PositionYAxis:
516
        case ColorWheelFine:
517
        case ColorRGBMixer:
518
        case ColorCTOMixer:
519
        case ColorCTCMixer:
520
        case ColorCTBMixer:
521
        case GoboWheelFine:
522
        case GoboIndexFine:
523
        case ShutterIrisFine:
524
        case BeamFocusFine:
525
        case BeamZoomFine:
526
        case NoFunction:
527
            cap->setName(name());
154✔
528
        break;
154✔
529
        case SpeedPanSlowFast:
1✔
530
            cap->setName("Pan (Slow to fast)");
1✔
531
        break;
1✔
532
        case SpeedPanFastSlow:
×
533
            cap->setName("Pan (Fast to slow)");
×
534
        break;
×
535
        case SpeedTiltSlowFast:
×
536
            cap->setName("Tilt (Slow to fast)");
×
537
        break;
×
538
        case SpeedTiltFastSlow:
6✔
539
            cap->setName("Tilt (Fast to slow)");
6✔
540
        break;
6✔
541
        case SpeedPanTiltSlowFast:
1✔
542
            cap->setName("Pan and tilt (Slow to fast)");
1✔
543
        break;
1✔
544
        case SpeedPanTiltFastSlow:
4✔
545
            cap->setName("Pan and tilt (Fast to slow)");
4✔
546
        break;
4✔
547
        case ColorMacro:
×
548
        case ColorWheel:
549
        case GoboWheel:
550
        case GoboIndex:
551
            cap->setName(name() + " presets");
×
552
        break;
×
553
        case ShutterStrobeSlowFast:
1✔
554
            cap->setName("Strobe (Slow to fast)");
1✔
555
        break;
1✔
556
        case ShutterStrobeFastSlow:
2✔
557
            cap->setName("Strobe (Fast to slow)");
2✔
558
        break;
2✔
559
        case ShutterIrisMinToMax:
×
560
            cap->setName("Iris (Minimum to maximum)");
×
561
        break;
×
562
        case ShutterIrisMaxToMin:
×
563
            cap->setName("Iris (Maximum to minimum)");
×
564
        break;
×
565
        case BeamFocusNearFar:
1✔
566
            cap->setName("Beam (Near to far)");
1✔
567
        break;
1✔
568
        case BeamFocusFarNear:
3✔
569
            cap->setName("Beam (Far to near)");
3✔
570
        break;
3✔
571
        case BeamZoomSmallBig:
2✔
572
            cap->setName("Zoom (Small to big)");
2✔
573
        break;
2✔
574
        case BeamZoomBigSmall:
1✔
575
            cap->setName("Zoom (Big to small)");
1✔
576
        break;
1✔
577
        case PrismRotationSlowFast:
×
578
            cap->setName("Prism rotation (Slow to fast)");
×
579
        break;
×
580
        case PrismRotationFastSlow:
×
581
            cap->setName("Prism rotation (Fast to slow)");
×
582
        break;
×
583
        default:
584
        break;
585
    }
586

587
    addCapability(cap);
490✔
588

589
    return cap;
490✔
590
}
591

592
/*****************************************************************************
593
 * Groups
594
 *****************************************************************************/
595

596
QStringList QLCChannel::groupList()
1✔
597
{
598
    QStringList list;
599

600
    // Keep this list in alphabetical order because it's used only in UI
601
    list.append(KXMLQLCChannelGroupBeam);
1✔
602
    list.append(KXMLQLCChannelGroupColour);
1✔
603
    list.append(KXMLQLCChannelGroupEffect);
1✔
604
    list.append(KXMLQLCChannelGroupGobo);
1✔
605
    list.append(KXMLQLCChannelGroupIntensity);
1✔
606
    list.append(KXMLQLCChannelGroupMaintenance);
1✔
607
    list.append(KXMLQLCChannelGroupNothing);
1✔
608
    list.append(KXMLQLCChannelGroupPan);
1✔
609
    list.append(KXMLQLCChannelGroupPrism);
1✔
610
    list.append(KXMLQLCChannelGroupShutter);
1✔
611
    list.append(KXMLQLCChannelGroupSpeed);
1✔
612
    list.append(KXMLQLCChannelGroupTilt);
1✔
613

614
    return list;
1✔
615
}
616

617
QString QLCChannel::groupToString(Group grp)
22✔
618
{
619
    switch (grp)
22✔
620
    {
621
    case Intensity:
2✔
622
        return KXMLQLCChannelGroupIntensity;
2✔
623
    case Colour:
5✔
624
        return KXMLQLCChannelGroupColour;
5✔
625
    case Gobo:
3✔
626
        return KXMLQLCChannelGroupGobo;
3✔
627
    case Prism:
1✔
628
        return KXMLQLCChannelGroupPrism;
1✔
629
    case Shutter:
4✔
630
        return KXMLQLCChannelGroupShutter;
4✔
631
    case Beam:
1✔
632
        return KXMLQLCChannelGroupBeam;
1✔
633
    case Speed:
1✔
634
        return KXMLQLCChannelGroupSpeed;
1✔
635
    case Effect:
1✔
636
        return KXMLQLCChannelGroupEffect;
1✔
637
    case Pan:
1✔
638
        return KXMLQLCChannelGroupPan;
1✔
639
    case Tilt:
1✔
640
        return KXMLQLCChannelGroupTilt;
1✔
641
    case Maintenance:
1✔
642
        return KXMLQLCChannelGroupMaintenance;
1✔
643
    default:
1✔
644
        return KXMLQLCChannelGroupNothing;
1✔
645
    }
646
}
647

648
QLCChannel::Group QLCChannel::stringToGroup(const QString& str)
261✔
649
{
650
    if (str == KXMLQLCChannelGroupIntensity)
261✔
651
        return Intensity;
652
    else if (str == KXMLQLCChannelGroupColour)
241✔
653
        return Colour;
654
    else if (str == KXMLQLCChannelGroupGobo)
180✔
655
        return Gobo;
656
    else if (str == KXMLQLCChannelGroupPrism)
151✔
657
        return Prism;
658
    else if (str == KXMLQLCChannelGroupShutter)
145✔
659
        return Shutter;
660
    else if (str == KXMLQLCChannelGroupBeam)
111✔
661
        return Beam;
662
    else if (str == KXMLQLCChannelGroupSpeed)
106✔
663
        return Speed;
664
    else if (str == KXMLQLCChannelGroupEffect)
56✔
665
        return Effect;
666
    else if (str == KXMLQLCChannelGroupPan)
17✔
667
        return Pan;
668
    else if (str == KXMLQLCChannelGroupTilt)
15✔
669
        return Tilt;
670
    else if (str == KXMLQLCChannelGroupMaintenance)
12✔
671
        return Maintenance;
672
    else if (str == KXMLQLCChannelGroupNothing)
×
673
        return Nothing;
674
    else
675
        return NoGroup;
×
676
}
677

678
QString QLCChannel::groupString() const
×
679
{
680
    return groupToString(m_group);
×
681
}
682

683
void QLCChannel::setGroup(Group grp)
1,763✔
684
{
685
    if (grp == m_group)
1,763✔
686
        return;
687

688
    m_group = grp;
390✔
689
    emit groupChanged();
390✔
690
}
691

692
QLCChannel::Group QLCChannel::group() const
862,114✔
693
{
694
    return m_group;
862,114✔
695
}
696

697
QPixmap QLCChannel::drawIntensity(QColor color, QString str) const
×
698
{
699
    QPixmap pm(32, 32);
×
700
    QPainter painter(&pm);
×
701
    painter.setRenderHint(QPainter::Antialiasing);
×
702

703
    /*QFont tfont = QApplication::font();
704
    tfont.setBold(true);
705
    tfont.setPixelSize(14);
706
    painter.setFont(tfont);*/
707

708
    pm.fill(color);
×
709
    if (str == "B")
×
710
        painter.setPen(Qt::white);
×
711
    painter.drawText(0, 0, 32, 32, Qt::AlignHCenter|Qt::AlignVCenter, str);
712

713
    return pm;
×
714
}
×
715

716
QIcon QLCChannel::getIntensityIcon() const
×
717
{
718
    QPixmap pm(32, 32);
×
719

720
    if (m_colour == QLCChannel::Red)
×
721
        pm = drawIntensity(Qt::red, "R");
×
722
    else if (m_colour == QLCChannel::Green)
×
723
        pm = drawIntensity(Qt::green, "G");
×
724
    else if (m_colour == QLCChannel::Blue)
×
725
        pm = drawIntensity(Qt::blue, "B");
×
726
    else if (m_colour == QLCChannel::Cyan)
×
727
        pm = drawIntensity(Qt::cyan, "C");
×
728
    else if (m_colour == QLCChannel::Magenta)
×
729
        pm = drawIntensity(Qt::magenta, "M");
×
730
    else if (m_colour == QLCChannel::Yellow)
×
731
        pm = drawIntensity(Qt::yellow, "Y");
×
732
    else if (m_colour == QLCChannel::Amber)
×
733
        pm = drawIntensity(QColor(0xFFFF7E00), "A");
×
734
    else if (m_colour == QLCChannel::White)
×
735
        pm = drawIntensity(Qt::white, "W");
×
736
    else if (m_colour == QLCChannel::UV)
×
737
        pm = drawIntensity(QColor(0xFF9400D3), "UV");
×
738
    else if (m_colour == QLCChannel::Lime)
×
739
        pm = drawIntensity(QColor(0xFFADFF2F), "L");
×
740
    else if (m_colour == QLCChannel::Indigo)
×
741
        pm = drawIntensity(QColor(0xFF4B0082), "I");
×
742
    else
743
    {
744
        // None of the primary colours matched and since this is an
745
        // intensity channel, it must be controlling a plain dimmer OSLT.
746
        return QIcon(":/intensity.png");
×
747
    }
748

749
    return QIcon(pm);
×
750
}
×
751

752
QString QLCChannel::getIntensityColorCode(bool svg) const
28✔
753
{
754
    QString prefix = svg ? "qrc" : "";
56✔
755
    QString ext = svg ? "svg" : "png";
56✔
756

757
    if (m_colour == QLCChannel::Red)
28✔
758
        return svg ? QString("qrc:/red.svg") : QString("#FF0000");
×
759
    else if (m_colour == QLCChannel::Green)
28✔
760
        return svg ? QString("qrc:/green.svg") : QString("#00FF00");
×
761
    else if (m_colour == QLCChannel::Blue)
28✔
762
        return svg ? QString("qrc:/blue.svg") : QString("#0000FF");
×
763
    else if (m_colour == QLCChannel::Cyan)
28✔
764
        return svg ? QString("qrc:/cyan.svg") : QString("#00FFFF");
×
765
    else if (m_colour == QLCChannel::Magenta)
28✔
766
        return svg ? QString("qrc:/magenta.svg") : QString("#FF00FF");
×
767
    else if (m_colour == QLCChannel::Yellow)
28✔
768
        return svg ? QString("qrc:/yellow.svg") : QString("#FFFF00");
×
769
    else if (m_colour == QLCChannel::Amber)
28✔
770
        return svg ? QString("qrc:/amber.svg") : QString("#FF7E00");
×
771
    else if (m_colour == QLCChannel::White)
28✔
772
        return svg ? QString("qrc:/white.svg") : QString("#FFFFFF");
×
773
    else if (m_colour == QLCChannel::UV)
28✔
774
        return svg ? QString("qrc:/uv.svg") : QString("#9400D3");
×
775
    else if (m_colour == QLCChannel::Lime)
28✔
776
        return svg ? QString("qrc:/lime.svg") : QString("#ADFF2F");
×
777
    else if (m_colour == QLCChannel::Indigo)
28✔
778
        return svg ? QString("qrc:/indigo.svg") : QString("#4B0082");
×
779
    else
780
    {
781
        // None of the primary colours matched and since this is an
782
        // intensity channel, it must be controlling a plain dimmer OSLT.
783
        return QString("%1:/intensity.%2").arg(prefix).arg(ext);
28✔
784
    }
785

786
    return QString("%1:/intensity.%2").arg(prefix).arg(ext);
787
}
28✔
788

789
QIcon QLCChannel::getIcon() const
×
790
{
791
    if (group() == Intensity)
×
792
        return getIntensityIcon();
×
793
    else
794
        return QIcon(getIconNameFromGroup(group()));
×
795
}
796

797
QString QLCChannel::getIconNameFromGroup(QLCChannel::Group grp, bool svg) const
28✔
798
{
799
    QString prefix = svg ? "qrc" : "";
56✔
800
    QString ext = svg ? "svg" : "png";
56✔
801

802
    switch(grp)
28✔
803
    {
804
        case Pan: return QString("%1:/pan.%2").arg(prefix).arg(ext); break;
×
805
        case Tilt: return QString("%1:/tilt.%2").arg(prefix).arg(ext); break;
×
806
        case Colour: return QString("%1:/colorwheel.%2").arg(prefix).arg(ext); break;
×
807
        case Effect: return QString("%1:/star.%2").arg(prefix).arg(ext); break;
×
808
        case Gobo: return QString("%1:/gobo.%2").arg(prefix).arg(ext); break;
×
809
        case Shutter: return QString("%1:/shutter.%2").arg(prefix).arg(ext); break;
×
810
        case Speed: return QString("%1:/speed.%2").arg(prefix).arg(ext); break;
×
811
        case Prism: return QString("%1:/prism.%2").arg(prefix).arg(ext); break;
×
812
        case Maintenance: return QString("%1:/configure.%2").arg(prefix).arg(ext); break;
×
813
        case Intensity: return getIntensityColorCode(svg); break;
28✔
814
        case Beam: return QString("%1:/beam.%2").arg(prefix).arg(ext); break;
×
815
        case Nothing: return QString("%1:/uncheck.%2").arg(prefix).arg(ext); break;
×
816
        default:
817
        break;
818
    }
819

820
    return QString("%1:/intensity.%2").arg(prefix).arg(ext);
×
821
}
28✔
822

823
/*****************************************************************************
824
 * Properties
825
 *****************************************************************************/
826

827
QString QLCChannel::name() const
22,489✔
828
{
829
    return m_name;
22,489✔
830
}
831

832
void QLCChannel::setName(const QString &name)
1,758✔
833
{
834
    if (name == m_name)
1,758✔
835
        return;
836

837
    m_name = name;
1,758✔
838
    emit nameChanged();
1,758✔
839
}
840

841
uchar QLCChannel::defaultValue() const
5,860✔
842
{
843
    return m_defaultValue;
5,860✔
844
}
845

846
void QLCChannel::setDefaultValue(uchar value)
3✔
847
{
848
    if (value == m_defaultValue)
3✔
849
        return;
850

851
    m_defaultValue = value;
1✔
852
    emit defaultValueChanged();
1✔
853
}
854

855
QLCChannel::ControlByte QLCChannel::controlByte() const
8,627✔
856
{
857
    return m_controlByte;
8,627✔
858
}
859

860
void QLCChannel::setControlByte(ControlByte byte)
801✔
861
{
862
    if (byte == m_controlByte)
801✔
863
        return;
864

865
    m_controlByte = byte;
114✔
866
    emit controlByteChanged();
114✔
867
}
868

869
/*****************************************************************************
870
 * Colours
871
 *****************************************************************************/
872

873
QStringList QLCChannel::colourList()
1✔
874
{
875
    QStringList list;
876
    //list << KXMLQLCChannelColourGeneric;
877
    list << KXMLQLCChannelColourRed;
2✔
878
    list << KXMLQLCChannelColourGreen;
2✔
879
    list << KXMLQLCChannelColourBlue;
2✔
880
    list << KXMLQLCChannelColourCyan;
2✔
881
    list << KXMLQLCChannelColourMagenta;
2✔
882
    list << KXMLQLCChannelColourYellow;
2✔
883
    list << KXMLQLCChannelColourAmber;
2✔
884
    list << KXMLQLCChannelColourWhite;
2✔
885
    list << KXMLQLCChannelColourUV;
2✔
886
    list << KXMLQLCChannelColourLime;
2✔
887
    list << KXMLQLCChannelColourIndigo;
2✔
888
    return list;
1✔
889
}
890

891
QString QLCChannel::colourToString(PrimaryColour colour)
12✔
892
{
893
    switch (colour)
12✔
894
    {
895
    case Red:
1✔
896
        return KXMLQLCChannelColourRed;
1✔
897
    case Green:
1✔
898
        return KXMLQLCChannelColourGreen;
1✔
899
    case Blue:
1✔
900
        return KXMLQLCChannelColourBlue;
1✔
901
    case Cyan:
2✔
902
        return KXMLQLCChannelColourCyan;
2✔
903
    case Magenta:
1✔
904
        return KXMLQLCChannelColourMagenta;
1✔
905
    case Yellow:
1✔
906
        return KXMLQLCChannelColourYellow;
1✔
907
    case Amber:
1✔
908
        return KXMLQLCChannelColourAmber;
1✔
909
    case White:
1✔
910
        return KXMLQLCChannelColourWhite;
1✔
911
    case UV:
1✔
912
        return KXMLQLCChannelColourUV;
1✔
913
    case Lime:
1✔
914
        return KXMLQLCChannelColourLime;
1✔
915
    case Indigo:
1✔
916
        return KXMLQLCChannelColourIndigo;
1✔
917
    case NoColour:
×
918
    default:
919
        return KXMLQLCChannelColourGeneric;
×
920
    }
921
}
922

923
QLCChannel::PrimaryColour QLCChannel::stringToColour(const QString& str)
1✔
924
{
925
    if (str == KXMLQLCChannelColourRed)
1✔
926
        return Red;
927
    else if (str == KXMLQLCChannelColourGreen)
1✔
928
        return Green;
929
    else if (str == KXMLQLCChannelColourBlue)
1✔
930
        return Blue;
931
    else if (str == KXMLQLCChannelColourCyan)
1✔
932
        return Cyan;
933
    else if (str == KXMLQLCChannelColourMagenta)
×
934
        return Magenta;
935
    else if (str == KXMLQLCChannelColourYellow)
×
936
        return Yellow;
937
    else if (str == KXMLQLCChannelColourAmber)
×
938
        return Amber;
939
    else if (str == KXMLQLCChannelColourWhite)
×
940
        return White;
941
    else if (str == KXMLQLCChannelColourUV)
×
942
        return UV;
943
    else if (str == KXMLQLCChannelColourLime)
×
944
        return Lime;
945
    else if (str == KXMLQLCChannelColourIndigo)
×
946
        return Indigo;
947
    else
948
        return NoColour;
×
949
}
950

951
void QLCChannel::setColour(QLCChannel::PrimaryColour colour)
797✔
952
{
953
    if (colour == m_colour)
797✔
954
        return;
955

956
    m_colour = colour;
579✔
957

958
    emit colourChanged();
579✔
959
}
960

961
QLCChannel::PrimaryColour QLCChannel::colour() const
4,198✔
962
{
963
    return m_colour;
4,198✔
964
}
965

966
/*****************************************************************************
967
 * Capabilities
968
 *****************************************************************************/
969

970
const QList <QLCCapability*> QLCChannel::capabilities() const
3,405✔
971
{
972
    return m_capabilities;
3,405✔
973
}
974

975
QLCCapability* QLCChannel::searchCapability(uchar value) const
1,046✔
976
{
977
    QListIterator <QLCCapability*> it(m_capabilities);
1,046✔
978
    while (it.hasNext() == true)
1,885✔
979
    {
980
        QLCCapability* capability = it.next();
1,884✔
981
        if (capability->min() <= value && capability->max() >= value)
1,884✔
982
            return capability;
1,045✔
983
    }
984

985
    return NULL;
986
}
987

988
QLCCapability* QLCChannel::searchCapability(const QString& name,
4✔
989
        bool exactMatch) const
990
{
991
    QListIterator <QLCCapability*> it(m_capabilities);
4✔
992
    while (it.hasNext() == true)
10✔
993
    {
994
        QLCCapability* capability = it.next();
9✔
995
        if (exactMatch == true && capability->name() == name)
9✔
996
            return capability;
3✔
997
        else if (exactMatch == false &&
6✔
998
                 capability->name().contains(name) == true)
6✔
999
            return capability;
×
1000
    }
1001

1002
    return NULL;
1003
}
1004

1005
bool QLCChannel::addCapability(QLCCapability* cap)
3,806✔
1006
{
1007
    Q_ASSERT(cap != NULL);
1008

1009
    /* Check for overlapping values */
1010
    foreach (QLCCapability* another, m_capabilities)
25,349✔
1011
    {
1012
        if (another->overlaps(cap) == true)
21,549✔
1013
            return false;
1014
    }
1015

1016
    m_capabilities.append(cap);
3,800✔
1017
    return true;
3,800✔
1018
}
1019

1020
bool QLCChannel::setCapabilityRange(QLCCapability* cap, uchar min, uchar max)
×
1021
{
1022
    Q_ASSERT(cap != NULL);
1023

1024
    uchar prevMin = cap->min();
×
1025
    cap->setMin(min);
×
1026
    uchar prevMax = cap->max();
×
1027
    cap->setMax(max);
×
1028

1029
    /* Check for overlapping values */
1030
    foreach (QLCCapability* another, m_capabilities)
×
1031
    {
1032
        if (another == cap)
×
1033
            continue;
×
1034

1035
        if (another->overlaps(cap) == true)
×
1036
        {
1037
            cap->setMin(prevMin);
×
1038
            cap->setMax(prevMax);
×
1039
            return false;
1040
        }
1041
    }
1042

1043
    return true;
×
1044
}
1045

1046
bool QLCChannel::removeCapability(QLCCapability* cap)
3✔
1047
{
1048
    Q_ASSERT(cap != NULL);
1049

1050
    QMutableListIterator <QLCCapability*> it(m_capabilities);
3✔
1051
    while (it.hasNext() == true)
5✔
1052
    {
1053
        if (it.next() == cap)
4✔
1054
        {
1055
            it.remove();
2✔
1056
            delete cap;
2✔
1057
            return true;
2✔
1058
        }
1059
    }
1060

1061
    return false;
1062
}
1063

1064
static bool capsort(const QLCCapability* cap1, const QLCCapability* cap2)
26✔
1065
{
1066
    return (*cap1) < (*cap2);
26✔
1067
}
1068

1069
void QLCChannel::sortCapabilities()
1✔
1070
{
1071
    std::sort(m_capabilities.begin(), m_capabilities.end(), capsort);
2✔
1072
}
1✔
1073

1074
/*****************************************************************************
1075
 * File operations
1076
 *****************************************************************************/
1077

1078
bool QLCChannel::saveXML(QXmlStreamWriter *doc) const
2✔
1079
{
1080
    Q_ASSERT(doc != NULL);
1081

1082
    /* Channel entry */
1083
    doc->writeStartElement(KXMLQLCChannel);
2✔
1084
    doc->writeAttribute(KXMLQLCChannelName, m_name);
2✔
1085

1086
    if (m_defaultValue)
2✔
1087
        doc->writeAttribute(KXMLQLCChannelDefault, QString::number(m_defaultValue));
×
1088

1089
    if (m_preset != Custom)
2✔
1090
    {
1091
        doc->writeAttribute(KXMLQLCChannelPreset, presetToString(m_preset));
×
1092
        doc->writeEndElement();
×
1093
        return true;
×
1094
    }
1095

1096
    /* Group */
1097
    doc->writeStartElement(KXMLQLCChannelGroup);
2✔
1098
    /* Group control byte */
1099
    doc->writeAttribute(KXMLQLCChannelGroupByte, QString::number(controlByte()));
2✔
1100
    /* Group name */
1101
    doc->writeCharacters(groupToString(m_group));
2✔
1102
    doc->writeEndElement();
2✔
1103

1104
    /* Colour */
1105
    if (m_colour != NoColour)
2✔
1106
        doc->writeTextElement(KXMLQLCChannelColour, QLCChannel::colourToString(colour()));
×
1107

1108
    /* Capabilities */
1109
    QListIterator <QLCCapability*> it(m_capabilities);
2✔
1110
    while (it.hasNext() == true)
6✔
1111
        it.next()->saveXML(doc);
4✔
1112

1113
    doc->writeEndElement();
2✔
1114
    return true;
1115
}
1116

1117
bool QLCChannel::loadXML(QXmlStreamReader &doc)
752✔
1118
{
1119
    if (doc.name() != KXMLQLCChannel)
1,504✔
1120
    {
1121
        qWarning() << "Channel node not found.";
1✔
1122
        return false;
1✔
1123
    }
1124

1125
    QXmlStreamAttributes attrs = doc.attributes();
751✔
1126

1127
    /* Get channel name */
1128
    QString str = attrs.value(KXMLQLCChannelName).toString();
751✔
1129
    if (str.isEmpty() == true)
751✔
1130
        return false;
1131
    setName(str);
751✔
1132

1133
    if (attrs.hasAttribute(KXMLQLCChannelDefault))
751✔
1134
    {
1135
        str = attrs.value(KXMLQLCChannelDefault).toString();
×
1136
        setDefaultValue(uchar(str.toInt()));
×
1137
    }
1138

1139
    if (attrs.hasAttribute(KXMLQLCChannelPreset))
751✔
1140
    {
1141
        str = attrs.value(KXMLQLCChannelPreset).toString();
490✔
1142
        setPreset(stringToPreset(str));
490✔
1143
        addPresetCapability();
490✔
1144
    }
1145

1146
    /* Subtags */
1147
    while (doc.readNextStartElement())
3,584✔
1148
    {
1149
        if (doc.name() == KXMLQLCCapability)
5,666✔
1150
        {
1151
            /* Create a new capability and attempt to load it */
1152
            QLCCapability* cap = new QLCCapability();
5,140✔
1153
            if (cap->loadXML(doc) == true)
2,570✔
1154
            {
1155
                /* Loading succeeded */
1156
                if (addCapability(cap) == false)
2,569✔
1157
                {
1158
                    /* Value overlaps with existing value */
1159
                    delete cap;
1✔
1160
                }
1161
            }
1162
            else
1163
            {
1164
                /* Loading failed */
1165
                delete cap;
1✔
1166
                doc.skipCurrentElement();
1✔
1167
            }
1168
        }
1169
        else if (doc.name() == KXMLQLCChannelGroup)
526✔
1170
        {
1171
            str = doc.attributes().value(KXMLQLCChannelGroupByte).toString();
261✔
1172
            setControlByte(ControlByte(str.toInt()));
261✔
1173
            setGroup(stringToGroup(doc.readElementText()));
261✔
1174
        }
1175
        else if (doc.name() == KXMLQLCChannelColour)
4✔
1176
        {
1177
            setColour(stringToColour(doc.readElementText()));
1✔
1178
        }
1179
        else
1180
        {
1181
            qWarning() << Q_FUNC_INFO << "Unknown Channel tag: " << doc.name();
1✔
1182
            doc.skipCurrentElement();
1✔
1183
        }
1184
    }
1185

1186
    return true;
1187
}
751✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc