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

mcallegari / qlcplus / 7213665246

14 Dec 2023 07:31PM UTC coverage: 32.05% (+0.05%) from 32.001%
7213665246

push

github

mcallegari
engine: fix defCache test unit

15160 of 47301 relevant lines covered (32.05%)

23612.43 hits per line

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

87.86
/engine/src/qlcfixturedef.cpp
1
/*
2
  Q Light Controller Plus
3
  qlcfixturedef.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 <QXmlStreamWriter>
23
#include <iostream>
24
#include <QString>
25
#include <QDebug>
26
#include <QFile>
27

28
#include "qlcfixturemode.h"
29
#include "qlcfixturedef.h"
30
#include "qlcchannel.h"
31
#include "qlcfile.h"
32
#include "fixture.h"
33

34
QLCFixtureDef::QLCFixtureDef()
37,071✔
35
    : m_isLoaded(false)
36
    , m_isUser(false)
37
    , m_fileAbsolutePath(QString())
38
    , m_type(Dimmer)
37,071✔
39
{
40
}
37,071✔
41

42
QLCFixtureDef::QLCFixtureDef(const QLCFixtureDef* fixtureDef)
1✔
43
    : m_isLoaded(false)
44
    , m_isUser(false)
45
    , m_fileAbsolutePath(QString())
46
    , m_type(Dimmer)
1✔
47
{
48
    if (fixtureDef != NULL)
1✔
49
        *this = *fixtureDef;
1✔
50
}
1✔
51

52
QLCFixtureDef::~QLCFixtureDef()
36,844✔
53
{
54
    while (m_channels.isEmpty() == false)
37,615✔
55
        delete m_channels.takeFirst();
771✔
56

57
    while (m_modes.isEmpty() == false)
36,990✔
58
        delete m_modes.takeFirst();
146✔
59
}
36,844✔
60

61
QLCFixtureDef& QLCFixtureDef::operator=(const QLCFixtureDef& fixture)
1✔
62
{
63
    if (this != &fixture)
1✔
64
    {
65
        QListIterator <QLCChannel*> chit(fixture.m_channels);
2✔
66
        QListIterator <QLCFixtureMode*> modeit(fixture.m_modes);
2✔
67

68
        m_manufacturer = fixture.m_manufacturer;
1✔
69
        m_model = fixture.m_model;
1✔
70
        m_type = fixture.m_type;
1✔
71
        m_author = fixture.m_author;
1✔
72

73
        /* Clear all channels */
74
        while (m_channels.isEmpty() == false)
1✔
75
            delete m_channels.takeFirst();
×
76

77
        /* Copy channels from the other fixture */
78
        while (chit.hasNext() == true)
2✔
79
            m_channels.append(chit.next()->createCopy());
1✔
80

81
        /* Clear all modes */
82
        while (m_modes.isEmpty() == false)
1✔
83
            delete m_modes.takeFirst();
×
84

85
        /* Copy modes from the other fixture */
86
        while (modeit.hasNext() == true)
2✔
87
            m_modes.append(new QLCFixtureMode(this, modeit.next()));
1✔
88
    }
89

90
    return *this;
1✔
91
}
92

93
QString QLCFixtureDef::definitionSourceFile() const
3✔
94
{
95
    return m_fileAbsolutePath;
3✔
96
}
97

98
void QLCFixtureDef::setDefinitionSourceFile(const QString &absPath)
36,802✔
99
{
100
    m_fileAbsolutePath = absPath;
36,802✔
101
    m_isLoaded = false;
36,802✔
102
}
36,802✔
103

104
/****************************************************************************
105
 * General properties
106
 ****************************************************************************/
107

108
QString QLCFixtureDef::name() const
7✔
109
{
110
    return m_manufacturer + QString(" ") + m_model;
14✔
111
}
112

113
void QLCFixtureDef::setManufacturer(const QString& mfg)
37,096✔
114
{
115
    m_manufacturer = mfg;
37,096✔
116
}
37,096✔
117

118
QString QLCFixtureDef::manufacturer() const
29,289,200✔
119
{
120
    return m_manufacturer;
29,289,200✔
121
}
122

123
void QLCFixtureDef::setModel(const QString& model)
37,096✔
124
{
125
    m_model = model;
37,096✔
126
}
37,096✔
127

128
QString QLCFixtureDef::model() const
1,224,880✔
129
{
130
    return m_model;
1,224,880✔
131
}
132

133
void QLCFixtureDef::setType(const FixtureType type)
286✔
134
{
135
    m_type = type;
286✔
136
}
286✔
137

138
QLCFixtureDef::FixtureType QLCFixtureDef::type()
49✔
139
{
140
    return m_type;
49✔
141
}
142

143
QLCFixtureDef::FixtureType QLCFixtureDef::stringToType(const QString& type)
52✔
144
{
145
    if (type == "Color Changer") return ColorChanger;
52✔
146
    else if (type == "Dimmer") return Dimmer;
47✔
147
    else if (type == "Effect") return Effect;
47✔
148
    else if (type == "Fan") return Fan;
46✔
149
    else if (type == "Flower") return Flower;
46✔
150
    else if (type == "Hazer") return Hazer;
45✔
151
    else if (type == "Laser") return Laser;
44✔
152
    else if (type == "Moving Head") return MovingHead;
43✔
153
    else if (type == "Scanner") return Scanner;
30✔
154
    else if (type == "Smoke") return Smoke;
12✔
155
    else if (type == "Strobe") return Strobe;
11✔
156
    else if (type == "LED Bar (Beams)") return LEDBarBeams;
10✔
157
    else if (type == "LED Bar (Pixels)") return LEDBarPixels;
4✔
158

159
    return Other;
1✔
160
}
161

162
QString QLCFixtureDef::typeToString(QLCFixtureDef::FixtureType type)
28✔
163
{
164
    switch(type)
28✔
165
    {
166
        case ColorChanger: return "Color Changer";
2✔
167
        case Dimmer: return "Dimmer";
2✔
168
        case Effect: return "Effect";
2✔
169
        case Fan: return "Fan";
×
170
        case Flower: return "Flower";
2✔
171
        case Hazer: return "Hazer";
2✔
172
        case Laser: return "Laser";
2✔
173
        case MovingHead: return "Moving Head";
4✔
174
        case Scanner: return "Scanner";
3✔
175
        case Smoke: return "Smoke";
2✔
176
        case Strobe: return "Strobe";
2✔
177
        case LEDBarBeams: return "LED Bar (Beams)";
2✔
178
        case LEDBarPixels: return "LED Bar (Pixels)";
2✔
179
        default: return "Other";
1✔
180
    }
181
}
182

183
void QLCFixtureDef::setAuthor(const QString& author)
283✔
184
{
185
    m_author = author;
283✔
186
}
283✔
187

188
QString QLCFixtureDef::author()
3✔
189
{
190
    return m_author;
3✔
191
}
192

193
void QLCFixtureDef::checkLoaded(QString mapPath)
195✔
194
{
195
    // Already loaded ? Nothing to do
196
    if (m_isLoaded == true)
195✔
197
        return;
146✔
198

199
    if (manufacturer() == KXMLFixtureGeneric &&
108✔
200
       (model() == KXMLFixtureGeneric || model() == KXMLFixtureRGBPanel))
55✔
201
    {
202
        m_isLoaded = true;
×
203
        return;
×
204
    }
205
    if (m_fileAbsolutePath.isEmpty())
53✔
206
    {
207
        qWarning() << Q_FUNC_INFO << "Empty file path provided! This is a trouble.";
4✔
208
        return;
4✔
209
    }
210

211
    // check if path is relative (from map) or absolute (user def)
212
    QDir defPath(m_fileAbsolutePath);
98✔
213
    if (defPath.isRelative())
49✔
214
        m_fileAbsolutePath = QString("%1%2%3").arg(mapPath).arg(QDir::separator()).arg(m_fileAbsolutePath);
49✔
215

216
    qDebug() << "Loading fixture definition now... " << m_fileAbsolutePath;
49✔
217
    bool error = loadXML(m_fileAbsolutePath);
49✔
218
    if (error == false)
49✔
219
        m_isLoaded = true;
49✔
220
}
221

222
void QLCFixtureDef::setLoaded(bool loaded)
2✔
223
{
224
    m_isLoaded = loaded;
2✔
225
}
2✔
226

227
bool QLCFixtureDef::isUser() const
2,944✔
228
{
229
    return m_isUser;
2,944✔
230
}
231

232
void QLCFixtureDef::setIsUser(bool flag)
2✔
233
{
234
    m_isUser = flag;
2✔
235
}
2✔
236

237
/****************************************************************************
238
 * Channels
239
 ****************************************************************************/
240

241
bool QLCFixtureDef::addChannel(QLCChannel* channel)
1,673✔
242
{
243
    if (channel != NULL && m_channels.contains(channel) == false)
1,673✔
244
    {
245
        m_channels.append(channel);
1,671✔
246
        return true;
1,671✔
247
    }
248
    else
249
    {
250
        return false;
2✔
251
    }
252
}
253

254
bool QLCFixtureDef::removeChannel(QLCChannel* channel)
7✔
255
{
256
    /* First remove the channel from all modes */
257
    QListIterator <QLCFixtureMode*> modeit(m_modes);
14✔
258
    while (modeit.hasNext() == true)
7✔
259
        modeit.next()->removeChannel(channel);
×
260

261
    /* Then remove the actual channel from this fixture definition */
262
    QMutableListIterator <QLCChannel*> chit(m_channels);
7✔
263
    while (chit.hasNext() == true)
9✔
264
    {
265
        if (chit.next() == channel)
4✔
266
        {
267
            chit.remove();
2✔
268
            delete channel;
2✔
269
            return true;
2✔
270
        }
271
    }
272

273
    return false;
5✔
274
}
275

276
QLCChannel* QLCFixtureDef::channel(const QString& name)
1,422✔
277
{
278
    QListIterator <QLCChannel*> it(m_channels);
2,844✔
279

280
    while (it.hasNext() == true)
20,940✔
281
    {
282
        QLCChannel* ch = it.next();
20,937✔
283
        if (ch->name() == name)
20,937✔
284
            return ch;
1,419✔
285
    }
286

287
    return NULL;
3✔
288
}
289

290
QList <QLCChannel*> QLCFixtureDef::channels() const
2,668✔
291
{
292
    return m_channels;
2,668✔
293
}
294

295
/****************************************************************************
296
 * Modes
297
 ****************************************************************************/
298

299
bool QLCFixtureDef::addMode(QLCFixtureMode* mode)
377✔
300
{
301
    if (mode != NULL && m_modes.contains(mode) == false)
377✔
302
    {
303
        m_modes.append(mode);
375✔
304
        return true;
375✔
305
    }
306
    else
307
    {
308
        return false;
2✔
309
    }
310
}
311

312
bool QLCFixtureDef::removeMode(QLCFixtureMode* mode)
7✔
313
{
314
    QMutableListIterator <QLCFixtureMode*> it(m_modes);
7✔
315
    while (it.hasNext() == true)
9✔
316
    {
317
        if (it.next() == mode)
4✔
318
        {
319
            it.remove();
2✔
320
            delete mode;
2✔
321
            return true;
2✔
322
        }
323
    }
324

325
    return false;
5✔
326
}
327

328
QLCFixtureMode *QLCFixtureDef::mode(const QString& name)
50✔
329
{
330
    QListIterator <QLCFixtureMode*> it(m_modes);
100✔
331

332
    while (it.hasNext() == true)
79✔
333
    {
334
        QLCFixtureMode *mode = it.next();
78✔
335
        if (mode->name() == name)
78✔
336
            return mode;
49✔
337
    }
338

339
    return NULL;
1✔
340
}
341

342
QList <QLCFixtureMode*> QLCFixtureDef::modes()
188✔
343
{
344
    return m_modes;
188✔
345
}
346

347
/****************************************************************************
348
 * Physical
349
 ****************************************************************************/
350

351
void QLCFixtureDef::setPhysical(const QLCPhysical& physical)
52✔
352
{
353
    m_physical = physical;
52✔
354
}
52✔
355

356
QLCPhysical QLCFixtureDef::physical() const
55✔
357
{
358
    return m_physical;
55✔
359
}
360

361
/****************************************************************************
362
 * XML operations
363
 ****************************************************************************/
364

365
QFile::FileError QLCFixtureDef::saveXML(const QString& fileName)
2✔
366
{
367
    QFile::FileError error;
368

369
    if (fileName.isEmpty() == true)
2✔
370
        return QFile::OpenError;
×
371

372
    QString tempFileName(fileName);
4✔
373
    tempFileName += ".temp";
2✔
374
    QFile file(tempFileName);
4✔
375
    if (file.open(QIODevice::WriteOnly) == false)
2✔
376
        return file.error();
1✔
377

378
    QXmlStreamWriter doc(&file);
2✔
379
    doc.setAutoFormatting(true);
1✔
380
    doc.setAutoFormattingIndent(1);
1✔
381
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
382
    doc.setCodec("UTF-8");
1✔
383
#endif
384
    QLCFile::writeXMLHeader(&doc, KXMLQLCFixtureDefDocument, author());
1✔
385

386
    doc.writeTextElement(KXMLQLCFixtureDefManufacturer, m_manufacturer);
1✔
387
    doc.writeTextElement(KXMLQLCFixtureDefModel, m_model);
1✔
388
    doc.writeTextElement(KXMLQLCFixtureDefType, typeToString(m_type));
1✔
389

390
    /* Channels */
391
    QListIterator <QLCChannel*> chit(m_channels);
2✔
392
    while (chit.hasNext() == true)
2✔
393
        chit.next()->saveXML(&doc);
1✔
394

395
    /* Modes */
396
    QListIterator <QLCFixtureMode*> modeit(m_modes);
2✔
397
    while (modeit.hasNext() == true)
2✔
398
        modeit.next()->saveXML(&doc);
1✔
399

400
    m_physical.saveXML(&doc);
1✔
401

402
    /* End the document and close all the open elements */
403
    error = QFile::NoError;
1✔
404
    doc.writeEndDocument();
1✔
405
    file.close();
1✔
406

407
    // Save to actual requested file name
408
    QFile currFile(fileName);
2✔
409
    if (currFile.exists() && !currFile.remove())
1✔
410
    {
411
        qWarning() << "Could not erase" << fileName;
×
412
        return currFile.error();
×
413
    }
414
    if (!file.rename(fileName))
1✔
415
    {
416
        qWarning() << "Could not rename" << tempFileName << "to" << fileName;
×
417
        return file.error();
×
418
    }
419

420
    return error;
1✔
421
}
422

423
QFile::FileError QLCFixtureDef::loadXML(const QString& fileName)
63✔
424
{
425
    QFile::FileError error = QFile::NoError;
63✔
426

427
    if (fileName.isEmpty() == true)
63✔
428
        return QFile::OpenError;
1✔
429

430
    QXmlStreamReader *doc = QLCFile::getXMLReader(fileName);
62✔
431
    if (doc == NULL || doc->device() == NULL || doc->hasError())
62✔
432
    {
433
        qWarning() << Q_FUNC_INFO << "Unable to read from" << fileName;
10✔
434
        return QFile::ReadError;
10✔
435
    }
436

437
    while (!doc->atEnd())
104✔
438
    {
439
        if (doc->readNext() == QXmlStreamReader::DTD)
104✔
440
            break;
52✔
441
    }
442
    if (doc->hasError())
52✔
443
    {
444
        QLCFile::releaseXMLReader(doc);
×
445
        return QFile::ResourceError;
×
446
    }
447

448
    if (doc->dtdName() == KXMLQLCFixtureDefDocument)
52✔
449
    {
450
        // qDebug() << Q_FUNC_INFO << "Loading " << fileName;
451
        if (loadXML(*doc) == true)
52✔
452
            error = QFile::NoError;
52✔
453
        else
454
        {
455
            qWarning() << fileName << QString("%1\nLine %2, column %3")
×
456
                        .arg(doc->errorString())
×
457
                        .arg(doc->lineNumber())
×
458
                        .arg(doc->columnNumber());
×
459
            error = QFile::ReadError;
×
460
        }
461
    }
462
    else
463
    {
464
        error = QFile::ReadError;
×
465
        qWarning() << Q_FUNC_INFO << fileName
×
466
                   << "is not a fixture definition file";
×
467
    }
468

469
    QLCFile::releaseXMLReader(doc);
52✔
470

471
    return error;
52✔
472
}
473

474
bool QLCFixtureDef::loadXML(QXmlStreamReader& doc)
52✔
475
{
476
    bool retval = false;
52✔
477

478
    if (doc.readNextStartElement() == false)
52✔
479
        return false;
×
480

481
    if (doc.name() == KXMLQLCFixtureDef)
52✔
482
    {
483
        while (doc.readNextStartElement())
1,164✔
484
        {
485
            if (doc.name() == KXMLQLCCreator)
1,112✔
486
            {
487
                loadCreator(doc);
52✔
488
            }
489
            else if (doc.name() == KXMLQLCFixtureDefManufacturer)
1,060✔
490
            {
491
                setManufacturer(doc.readElementText());
52✔
492
            }
493
            else if (doc.name() == KXMLQLCFixtureDefModel)
1,008✔
494
            {
495
                setModel(doc.readElementText());
52✔
496
            }
497
            else if (doc.name() == KXMLQLCFixtureDefType)
956✔
498
            {
499
                setType(stringToType(doc.readElementText()));
52✔
500
            }
501
            else if (doc.name() == KXMLQLCChannel)
904✔
502
            {
503
                QLCChannel* ch = new QLCChannel();
720✔
504
                if (ch->loadXML(doc) == true)
720✔
505
                {
506
                    /* Loading succeeded */
507
                    if (addChannel(ch) == false)
720✔
508
                    {
509
                        /* Channel already exists */
510
                        delete ch;
×
511
                    }
512
                }
513
                else
514
                {
515
                    /* Loading failed */
516
                    delete ch;
×
517
                }
518
            }
519
            else if (doc.name() == KXMLQLCFixtureMode)
184✔
520
            {
521
                QLCFixtureMode* mode = new QLCFixtureMode(this);
132✔
522
                if (mode->loadXML(doc) == true)
132✔
523
                {
524
                    /* Loading succeeded */
525
                    if (addMode(mode) == false)
132✔
526
                    {
527
                        /* Mode already exists */
528
                        delete mode;
×
529
                    }
530
                }
531
                else
532
                {
533
                    /* Loading failed */
534
                    delete mode;
×
535
                }
536
            }
537
            else if (doc.name() == KXMLQLCPhysical)
52✔
538
            {
539
                /* Global physical */
540
                QLCPhysical physical;
104✔
541
                physical.loadXML(doc);
52✔
542
                setPhysical(physical);
52✔
543
            }
544
            else
545
            {
546
                qWarning() << Q_FUNC_INFO << "Unknown Fixture tag: " << doc.name();
×
547
                doc.skipCurrentElement();
×
548
            }
549
        }
550

551
        retval = true;
52✔
552
    }
553
    else
554
    {
555
        qWarning() << Q_FUNC_INFO << "Fixture node not found";
×
556
        retval = false;
×
557
    }
558

559
    if (retval == true)
52✔
560
        m_isLoaded = true;
52✔
561
    return retval;
52✔
562
}
563

564
bool QLCFixtureDef::loadCreator(QXmlStreamReader &doc)
52✔
565
{
566
    if (doc.name() != KXMLQLCCreator)
52✔
567
    {
568
        qWarning() << Q_FUNC_INFO << "file creator information not found!";
×
569
        return false;
×
570
    }
571

572
    while (doc.readNextStartElement())
208✔
573
    {
574
        if (doc.name() == KXMLQLCCreatorName)
156✔
575
        {
576
            /* Ignore name */
577
            doc.skipCurrentElement();
52✔
578
        }
579
        else if (doc.name() == KXMLQLCCreatorVersion)
104✔
580
        {
581
            /* Ignore version */
582
            doc.skipCurrentElement();
52✔
583
        }
584
        else if (doc.name() == KXMLQLCCreatorAuthor)
52✔
585
        {
586
            setAuthor(doc.readElementText());
52✔
587
        }
588
        else
589
        {
590
            qWarning() << Q_FUNC_INFO << "unknown creator tag:" << doc.name();
×
591
            doc.skipCurrentElement();
×
592
        }
593
    }
594

595
    return true;
52✔
596
}
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