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

mcallegari / qlcplus / 6751080228

03 Nov 2023 11:13PM UTC coverage: 28.067% (-0.002%) from 28.069%
6751080228

push

github

mcallegari
qmlui: more Tardis actions

15384 of 54812 relevant lines covered (28.07%)

20286.28 hits per line

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

74.44
/engine/src/qlcfixturedefcache.cpp
1
/*
2
  Q Light Controller
3
  qlcfixturedefcache.cpp
4

5
  Copyright (c) Heikki Junnila
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 <QCoreApplication>
21
#include <QXmlStreamReader>
22
#include <QDebug>
23
#include <QList>
24
#include <QSet>
25

26
#if defined(WIN32) || defined(Q_OS_WIN)
27
#   include <windows.h>
28
#else
29
#   include <unistd.h>
30
#endif
31

32
#include "qlcfixturedefcache.h"
33
#include "avolitesd4parser.h"
34
#include "qlcfixturedef.h"
35
#include "qlcconfig.h"
36
#include "qlcfile.h"
37

38
#define FIXTURES_MAP_NAME QString("FixturesMap.xml")
39
#define KXMLQLCFixtureMap QString("FixturesMap")
40

41
QLCFixtureDefCache::QLCFixtureDefCache()
176✔
42
{
43
}
176✔
44

45
QLCFixtureDefCache::~QLCFixtureDefCache()
176✔
46
{
47
    clear();
176✔
48
}
176✔
49

50
QLCFixtureDef* QLCFixtureDefCache::fixtureDef(
212✔
51
    const QString& manufacturer, const QString& model) const
52
{
53
    QListIterator <QLCFixtureDef*> it(m_defs);
424✔
54
    while (it.hasNext() == true)
147,827✔
55
    {
56
        QLCFixtureDef* def = it.next();
147,809✔
57
        if (def->manufacturer() == manufacturer && def->model() == model)
147,809✔
58
        {
59
            def->checkLoaded(m_mapAbsolutePath);
194✔
60
            return def;
194✔
61
        }
62
    }
63

64
    return NULL;
18✔
65
}
66

67
QStringList QLCFixtureDefCache::manufacturers() const
38✔
68
{
69
    QSet <QString> makers;
76✔
70

71
    // Gather a list of manufacturers
72
    QListIterator <QLCFixtureDef*> it(m_defs);
76✔
73
    while (it.hasNext() == true)
29,521✔
74
        makers << it.next()->manufacturer();
29,483✔
75

76
    // Bounce the QSet into a QStringList
77
    QStringList list;
38✔
78
    foreach (QString manuf, makers)
5,540✔
79
        list << manuf;
2,751✔
80

81
    return list;
76✔
82
}
83

84
QStringList QLCFixtureDefCache::models(const QString& manufacturer) const
36,706✔
85
{
86
    QSet <QString> models;
73,412✔
87
    QListIterator <QLCFixtureDef*> it(m_defs);
73,412✔
88
    while (it.hasNext() == true)
28,023,900✔
89
    {
90
        QLCFixtureDef* def = it.next();
27,987,200✔
91
        if (def->manufacturer() == manufacturer)
27,987,200✔
92
            models << def->model();
1,132,400✔
93
    }
94

95
    // Bounce the QSet into a QStringList
96
    QStringList list;
36,706✔
97
    foreach (QString model, models)
2,301,520✔
98
        list << model;
1,132,400✔
99

100
    return list;
73,412✔
101
}
102

103
QMap<QString, QMap<QString, bool> > QLCFixtureDefCache::fixtureCache() const
×
104
{
105
    QMap<QString, QMap<QString, bool> > map;
×
106

107
    QListIterator <QLCFixtureDef*> it(m_defs);
×
108
    while (it.hasNext() == true)
×
109
    {
110
        QLCFixtureDef *def = it.next();
×
111
        map[def->manufacturer()][def->model()] = def->isUser();
×
112
    }
113

114
    return map;
×
115
}
116

117
bool QLCFixtureDefCache::addFixtureDef(QLCFixtureDef* fixtureDef)
35,339✔
118
{
119
    if (fixtureDef == NULL)
35,339✔
120
        return false;
1✔
121

122
    if (models(fixtureDef->manufacturer()).contains(fixtureDef->model()) == false)
35,338✔
123
    {
124
        m_defs << fixtureDef;
35,336✔
125
        return true;
35,336✔
126
    }
127
    else
128
    {
129
        qWarning() << Q_FUNC_INFO << "Cache already contains"
2✔
130
                   << fixtureDef->name();
2✔
131
        return false;
2✔
132
    }
133
}
134

135
bool QLCFixtureDefCache::storeFixtureDef(QString filename, QString data)
×
136
{
137
    QDir userFolder = userDefinitionDirectory();
×
138

139
    QFile file(userFolder.absoluteFilePath(filename));
×
140
    if (file.open(QIODevice::WriteOnly | QIODevice::Text) == false)
×
141
        return false;
×
142

143
    file.write(data.toUtf8());
×
144
    file.close();
×
145

146
    // reload user definitions
147
    load(userDefinitionDirectory());
×
148

149
    return true;
×
150
}
151

152
bool QLCFixtureDefCache::load(const QDir& dir)
6✔
153
{
154
    qDebug() << Q_FUNC_INFO << dir.path();
6✔
155

156
    if (dir.exists() == false || dir.isReadable() == false)
6✔
157
        return false;
5✔
158

159
    /* Attempt to read all specified files from the given directory */
160
    QStringListIterator it(dir.entryList());
2✔
161
    while (it.hasNext() == true)
1✔
162
    {
163
        QString path(dir.absoluteFilePath(it.next()));
×
164

165
        if (path.toLower().endsWith(KExtFixture) == true)
×
166
            loadQXF(path, true);
×
167
        else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
×
168
            loadD4(path);
×
169
        else
170
            qWarning() << Q_FUNC_INFO << "Unrecognized fixture extension:" << path;
×
171
    }
172

173
    return true;
1✔
174
}
175

176
int QLCFixtureDefCache::loadMapManufacturer(QXmlStreamReader *doc, QString manufacturer)
3,264✔
177
{
178
    int count = 0;
3,264✔
179
    QString spacedManufacturer = manufacturer;
3,264✔
180
    spacedManufacturer.replace("_", " ");
3,264✔
181

182
    while (doc->readNextStartElement())
38,592✔
183
    {
184
        if (doc->name() == QString("F"))
35,328✔
185
        {
186
            QString defFile = "";
70,656✔
187
            QString model = "";
70,656✔
188

189
            if (doc->attributes().hasAttribute("n"))
35,328✔
190
            {
191
                defFile = QString("%1%2%3%4")
70,656✔
192
                            .arg(manufacturer).arg(QDir::separator())
70,656✔
193
                            .arg(doc->attributes().value("n").toString()).arg(KExtFixture);
35,328✔
194
                //qDebug() << "Manufacturer" << spacedManufacturer << "file" << defFile;
195
            }
196

197
            if (doc->attributes().hasAttribute("m"))
35,328✔
198
                model = doc->attributes().value("m").toString();
35,328✔
199

200
            if (defFile.isEmpty() == false &&
35,328✔
201
                spacedManufacturer.isEmpty() == false &&
70,656✔
202
                model.isEmpty() == false)
35,328✔
203
            {
204
                QLCFixtureDef *fxi = new QLCFixtureDef();
35,328✔
205
                Q_ASSERT(fxi != NULL);
35,328✔
206

207
                fxi->setDefinitionSourceFile(defFile);
35,328✔
208
                fxi->setManufacturer(spacedManufacturer);
35,328✔
209
                fxi->setModel(model);
35,328✔
210

211
                /* Delete the def if it's a duplicate. */
212
                if (addFixtureDef(fxi) == false)
35,328✔
213
                    delete fxi;
×
214
                fxi = NULL;
35,328✔
215
                count++;
35,328✔
216
            }
217
        }
218
        else
219
        {
220
            qWarning() << Q_FUNC_INFO << "Unknown manufacturer tag: " << doc->name();
×
221
        }
222
        doc->skipCurrentElement();
35,328✔
223
    }
224

225
    return count;
6,528✔
226
}
227

228
bool QLCFixtureDefCache::loadMap(const QDir &dir)
24✔
229
{
230
    qDebug() << Q_FUNC_INFO << dir.path();
24✔
231

232
    if (dir.exists() == false || dir.isReadable() == false)
24✔
233
        return false;
×
234

235
    QString mapPath(dir.absoluteFilePath(FIXTURES_MAP_NAME));
48✔
236

237
    if (mapPath.isEmpty() == true)
24✔
238
        return false;
×
239

240
    // cache the map path to be used when composing the fixture
241
    // definition absolute path
242
    m_mapAbsolutePath = dir.absolutePath();
24✔
243

244
    QXmlStreamReader *doc = QLCFile::getXMLReader(mapPath);
24✔
245
    if (doc == NULL || doc->device() == NULL || doc->hasError())
24✔
246
    {
247
        qWarning() << Q_FUNC_INFO << "Unable to read from" << mapPath;
×
248
        return false;
×
249
    }
250

251
    while (!doc->atEnd())
48✔
252
    {
253
        if (doc->readNext() == QXmlStreamReader::DTD)
48✔
254
            break;
24✔
255
    }
256

257
    if (doc->hasError())
24✔
258
    {
259
        QLCFile::releaseXMLReader(doc);
×
260
        return false;
×
261
    }
262

263
    // make sure the doc type is FixtureMap
264
    if (doc->dtdName() != KXMLQLCFixtureMap)
24✔
265
    {
266
        qWarning() << Q_FUNC_INFO << mapPath << "is not a fixture map file";
×
267
        QLCFile::releaseXMLReader(doc);
×
268
        return false;
×
269
    }
270

271
    if (doc->readNextStartElement() == false)
24✔
272
    {
273
        QLCFile::releaseXMLReader(doc);
×
274
        return false;
×
275
    }
276

277
    // make sure the root tag is FixtureMap
278
    if (doc->name() != KXMLQLCFixtureMap)
24✔
279
    {
280
        qWarning() << Q_FUNC_INFO << mapPath << "is not a fixture map file";
×
281
        QLCFile::releaseXMLReader(doc);
×
282
        return false;
×
283
    }
284

285
    int fxCount = 0;
24✔
286
    QString manufacturer = "";
24✔
287

288
    while (doc->readNextStartElement())
3,288✔
289
    {
290
        if (doc->name() == QString("M"))
3,264✔
291
        {
292
            if (doc->attributes().hasAttribute("n"))
3,264✔
293
            {
294
                manufacturer = doc->attributes().value("n").toString();
3,264✔
295
                fxCount += loadMapManufacturer(doc, manufacturer);
3,264✔
296
            }
297
        }
298
        else
299
        {
300
            qWarning() << Q_FUNC_INFO << "Unknown Fixture Map tag: " << doc->name();
×
301
            doc->skipCurrentElement();
×
302
        }
303
    }
304
    qDebug() << fxCount << "fixtures found in map";
24✔
305

306
#if 0
307
    /* Attempt to read all files not in FixtureMap */
308
    QStringList definitionPaths;
309

310
    // Gather a list of manufacturers
311
    QListIterator <QLCFixtureDef*> mfit(m_defs);
312
    while (mfit.hasNext() == true)
313
        definitionPaths << mfit.next()->definitionSourceFile();
314

315
    QStringListIterator it(dir.entryList());
316
    while (it.hasNext() == true)
317
    {
318
        QString path(dir.absoluteFilePath(it.next()));
319
        if (definitionPaths.contains(path))
320
            continue;
321

322
        qWarning() << path << "not in" << FIXTURES_MAP_NAME;
323

324
        if (path.toLower().endsWith(KExtFixture) == true)
325
            loadQXF(path);
326
        else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
327
            loadD4(path);
328
        else
329
            qWarning() << Q_FUNC_INFO << "Unrecognized fixture extension:" << path;
330
    }
331
#endif
332
    return true;
24✔
333
}
334

335
void QLCFixtureDefCache::clear()
35,519✔
336
{
337
    while (m_defs.isEmpty() == false)
35,519✔
338
        delete m_defs.takeFirst();
35,336✔
339
}
183✔
340

341
QDir QLCFixtureDefCache::systemDefinitionDirectory()
1✔
342
{
343
    return QLCFile::systemDirectory(QString(FIXTUREDIR), QString(KExtFixture));
2✔
344
}
345

346
QDir QLCFixtureDefCache::userDefinitionDirectory()
1✔
347
{
348
    QStringList filters;
1✔
349
    filters << QString("*%1").arg(KExtFixture);
1✔
350
    filters << QString("*%1").arg(KExtAvolitesFixture);
1✔
351

352
    return QLCFile::userDirectory(QString(USERFIXTUREDIR), QString(FIXTUREDIR), filters);
3✔
353
}
354

355
bool QLCFixtureDefCache::loadQXF(const QString& path, bool isUser)
9✔
356
{
357
    QLCFixtureDef *fxi = new QLCFixtureDef();
9✔
358
    Q_ASSERT(fxi != NULL);
9✔
359

360
    QFile::FileError error = fxi->loadXML(path);
9✔
361
    if (error == QFile::NoError)
9✔
362
    {
363
        fxi->setIsUser(isUser);
1✔
364

365
        /* Delete the def if it's a duplicate. */
366
        if (addFixtureDef(fxi) == false)
1✔
367
            delete fxi;
1✔
368
        fxi = NULL;
1✔
369
    }
370
    else
371
    {
372
        qWarning() << Q_FUNC_INFO << "Fixture definition loading from"
8✔
373
                   << path << "failed:" << QLCFile::errorString(error);
8✔
374
        delete fxi;
8✔
375
        fxi = NULL;
8✔
376
        return false;
8✔
377
    }
378
    return true;
1✔
379
}
380

381
bool QLCFixtureDefCache::loadD4(const QString& path)
1✔
382
{
383
    QLCFixtureDef *fxi = new QLCFixtureDef();
1✔
384
    AvolitesD4Parser parser;
2✔
385
    if (parser.loadXML(path, fxi) == false)
1✔
386
    {
387
        qWarning() << Q_FUNC_INFO << "Unable to load D4 fixture from" << path
1✔
388
                   << ":" << parser.lastError();
1✔
389
        delete fxi;
1✔
390
        return false;
1✔
391
    }
392

393
    // a D4 personality is always a user-made fixture
394
    fxi->setIsUser(true);
×
395

396
    /* Delete the def if it's a duplicate. */
397
    if (addFixtureDef(fxi) == false)
×
398
    {
399
        qDebug() << Q_FUNC_INFO << "Deleting duplicate" << path;
×
400
        delete fxi;
×
401
    }
402
    fxi = NULL;
×
403

404
    return true;
×
405
}
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