• 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

87.43
/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()
179✔
42
{
43
}
179✔
44

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

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

64
    return NULL;
65
}
66

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

71
    // Gather a list of manufacturers
72
    QListIterator <QLCFixtureDef*> it(m_defs);
38✔
73
    while (it.hasNext() == true)
32,301✔
74
        makers << it.next()->manufacturer();
64,526✔
75

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

81
    return list;
38✔
82
}
83

84
QStringList QLCFixtureDefCache::models(const QString& manufacturer) const
77,183✔
85
{
86
    QSet <QString> models;
87
    QListIterator <QLCFixtureDef*> it(m_defs);
77,183✔
88
    while (it.hasNext() == true)
63,358,285✔
89
    {
90
        QLCFixtureDef* def = it.next();
63,281,102✔
91
        if (def->manufacturer() == manufacturer)
63,281,102✔
92
            models << def->model();
4,975,114✔
93
    }
94

95
    // Bounce the QSet into a QStringList
96
    QStringList list;
97
    foreach (QString model, models)
2,564,740✔
98
        list << model;
2,487,557✔
99

100
    return list;
77,183✔
101
}
102

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

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

114
    return map;
2✔
115
}
×
116

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

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

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

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

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

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

149
    return true;
1✔
150
}
1✔
151

152
bool QLCFixtureDefCache::reloadFixtureDef(QLCFixtureDef *fixtureDef)
1✔
153
{
154
    int idx = m_defs.indexOf(fixtureDef);
1✔
155
    if (idx == -1)
1✔
156
        return false;
157

158
    QLCFixtureDef *def = m_defs.takeAt(idx);
1✔
159
    QString absPath = def->definitionSourceFile();
1✔
160
    delete def;
1✔
161

162
    QLCFixtureDef *origDef = new QLCFixtureDef();
1✔
163
    origDef->loadXML(absPath);
1✔
164
    m_defs << origDef;
165

166
    return true;
167
}
1✔
168

169
bool QLCFixtureDefCache::load(const QDir& dir)
9✔
170
{
171
    qDebug() << Q_FUNC_INFO << dir.path();
172

173
    if (dir.exists() == false || dir.isReadable() == false)
9✔
174
        return false;
7✔
175

176
    /* Attempt to read all specified files from the given directory */
177
    QStringListIterator it(dir.entryList());
2✔
178
    while (it.hasNext() == true)
3✔
179
    {
180
        QString path(dir.absoluteFilePath(it.next()));
1✔
181

182
        if (path.toLower().endsWith(KExtFixture) == true)
1✔
183
            loadQXF(path, true);
1✔
184
        else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
×
185
            loadD4(path);
×
186
        else
187
            qWarning() << Q_FUNC_INFO << "Unrecognized fixture extension:" << path;
×
188
    }
1✔
189

190
    return true;
191
}
192

193
int QLCFixtureDefCache::loadMapManufacturer(QXmlStreamReader *doc, QString manufacturer)
6,580✔
194
{
195
    int count = 0;
196
    QString spacedManufacturer = manufacturer;
197
    spacedManufacturer.replace("_", " ");
6,580✔
198

199
    while (doc->readNextStartElement())
82,344✔
200
    {
201
        if (doc->name() == QString("F"))
151,528✔
202
        {
203
            QString defFile = "";
75,764✔
204
            QString model = "";
75,764✔
205

206
            if (doc->attributes().hasAttribute("n"))
75,764✔
207
            {
208
                defFile = QString("%1%2%3%4")
151,528✔
209
                            .arg(manufacturer).arg(QDir::separator())
151,528✔
210
                            .arg(doc->attributes().value("n").toString()).arg(KExtFixture);
75,764✔
211
                //qDebug() << "Manufacturer" << spacedManufacturer << "file" << defFile;
212
            }
213

214
            if (doc->attributes().hasAttribute("m"))
75,764✔
215
                model = doc->attributes().value("m").toString();
75,764✔
216

217
            if (defFile.isEmpty() == false &&
75,764✔
218
                spacedManufacturer.isEmpty() == false &&
151,528✔
219
                model.isEmpty() == false)
220
            {
221
                QLCFixtureDef *fxi = new QLCFixtureDef();
75,764✔
222
                Q_ASSERT(fxi != NULL);
223

224
                fxi->setDefinitionSourceFile(defFile);
75,764✔
225
                fxi->setManufacturer(spacedManufacturer);
75,764✔
226
                fxi->setModel(model);
75,764✔
227

228
                /* Delete the def if it's a duplicate. */
229
                if (addFixtureDef(fxi) == false)
75,764✔
230
                    delete fxi;
47✔
231
                fxi = NULL;
232
                count++;
75,764✔
233
            }
234
        }
75,764✔
235
        else
236
        {
237
            qWarning() << Q_FUNC_INFO << "Unknown manufacturer tag: " << doc->name();
×
238
        }
239
        doc->skipCurrentElement();
75,764✔
240
    }
241

242
    return count;
6,580✔
243
}
6,580✔
244

245
bool QLCFixtureDefCache::loadMap(const QDir &dir)
47✔
246
{
247
    qDebug() << Q_FUNC_INFO << dir.path();
248

249
    if (dir.exists() == false || dir.isReadable() == false)
47✔
250
        return false;
×
251

252
    QString mapPath(dir.absoluteFilePath(FIXTURES_MAP_NAME));
94✔
253

254
    if (mapPath.isEmpty() == true)
47✔
255
        return false;
256

257
    // cache the map path to be used when composing the fixture
258
    // definition absolute path
259
    m_mapAbsolutePath = dir.absolutePath();
47✔
260

261
    QXmlStreamReader *doc = QLCFile::getXMLReader(mapPath);
47✔
262
    if (doc == NULL || doc->device() == NULL || doc->hasError())
94✔
263
    {
264
        qWarning() << Q_FUNC_INFO << "Unable to read from" << mapPath;
×
265
        return false;
×
266
    }
267

268
    while (!doc->atEnd())
94✔
269
    {
270
        if (doc->readNext() == QXmlStreamReader::DTD)
94✔
271
            break;
272
    }
273

274
    if (doc->hasError())
47✔
275
    {
276
        QLCFile::releaseXMLReader(doc);
×
277
        return false;
278
    }
279

280
    // make sure the doc type is FixtureMap
281
    if (doc->dtdName() != KXMLQLCFixtureMap)
94✔
282
    {
283
        qWarning() << Q_FUNC_INFO << mapPath << "is not a fixture map file";
×
284
        QLCFile::releaseXMLReader(doc);
×
285
        return false;
286
    }
287

288
    if (doc->readNextStartElement() == false)
47✔
289
    {
290
        QLCFile::releaseXMLReader(doc);
×
291
        return false;
292
    }
293

294
    // make sure the root tag is FixtureMap
295
    if (doc->name() != KXMLQLCFixtureMap)
94✔
296
    {
297
        qWarning() << Q_FUNC_INFO << mapPath << "is not a fixture map file";
×
298
        QLCFile::releaseXMLReader(doc);
×
299
        return false;
300
    }
301

302
    int fxCount = 0;
303
    QString manufacturer = "";
47✔
304

305
    while (doc->readNextStartElement())
6,627✔
306
    {
307
        if (doc->name() == QString("M"))
13,160✔
308
        {
309
            if (doc->attributes().hasAttribute("n"))
6,580✔
310
            {
311
                manufacturer = doc->attributes().value("n").toString();
6,580✔
312
                fxCount += loadMapManufacturer(doc, manufacturer);
6,580✔
313
            }
314
        }
315
        else
316
        {
317
            qWarning() << Q_FUNC_INFO << "Unknown Fixture Map tag: " << doc->name();
×
318
            doc->skipCurrentElement();
×
319
        }
320
    }
321
    qDebug() << fxCount << "fixtures found in map";
322

323
#if 0
324
    /* Attempt to read all files not in FixtureMap */
325
    QStringList definitionPaths;
326

327
    // Gather a list of manufacturers
328
    QListIterator <QLCFixtureDef*> mfit(m_defs);
329
    while (mfit.hasNext() == true)
330
        definitionPaths << mfit.next()->definitionSourceFile();
331

332
    QStringListIterator it(dir.entryList());
333
    while (it.hasNext() == true)
334
    {
335
        QString path(dir.absoluteFilePath(it.next()));
336
        if (definitionPaths.contains(path))
337
            continue;
338

339
        qWarning() << path << "not in" << FIXTURES_MAP_NAME;
340

341
        if (path.toLower().endsWith(KExtFixture) == true)
342
            loadQXF(path);
343
        else if (path.toLower().endsWith(KExtAvolitesFixture) == true)
344
            loadD4(path);
345
        else
346
            qWarning() << Q_FUNC_INFO << "Unrecognized fixture extension:" << path;
347
    }
348
#endif
349
    return true;
350
}
47✔
351

352
void QLCFixtureDefCache::clear()
188✔
353
{
354
    while (m_defs.isEmpty() == false)
76,101✔
355
        delete m_defs.takeFirst();
75,725✔
356
}
188✔
357

358
QDir QLCFixtureDefCache::systemDefinitionDirectory()
1✔
359
{
360
    return QLCFile::systemDirectory(QString(FIXTUREDIR), QString(KExtFixture));
1✔
361
}
362

363
QDir QLCFixtureDefCache::userDefinitionDirectory()
4✔
364
{
365
    QStringList filters;
366
    filters << QString("*%1").arg(KExtFixture);
8✔
367
    filters << QString("*%1").arg(KExtAvolitesFixture);
8✔
368

369
    return QLCFile::userDirectory(QString(USERFIXTUREDIR), QString(FIXTUREDIR), filters);
4✔
370
}
371

372
bool QLCFixtureDefCache::loadQXF(const QString& path, bool isUser)
10✔
373
{
374
    QLCFixtureDef *fxi = new QLCFixtureDef();
10✔
375
    Q_ASSERT(fxi != NULL);
376

377
    QFile::FileError error = fxi->loadXML(path);
10✔
378
    if (error == QFile::NoError)
10✔
379
    {
380
        fxi->setIsUser(isUser);
2✔
381
        fxi->setDefinitionSourceFile(path);
2✔
382
        fxi->setLoaded(true);
2✔
383

384
        /* Delete the def if it's a duplicate. */
385
        if (addFixtureDef(fxi) == false)
2✔
386
            delete fxi;
2✔
387
        fxi = NULL;
388
    }
389
    else
390
    {
391
        qWarning() << Q_FUNC_INFO << "Fixture definition loading from"
8✔
392
                   << path << "failed:" << QLCFile::errorString(error);
8✔
393
        delete fxi;
8✔
394
        fxi = NULL;
395
        return false;
8✔
396
    }
397
    return true;
398
}
399

400
bool QLCFixtureDefCache::loadD4(const QString& path)
1✔
401
{
402
    QLCFixtureDef *fxi = new QLCFixtureDef();
1✔
403
    AvolitesD4Parser parser;
1✔
404
    if (parser.loadXML(path, fxi) == false)
1✔
405
    {
406
        qWarning() << Q_FUNC_INFO << "Unable to load D4 fixture from" << path
1✔
407
                   << ":" << parser.lastError();
1✔
408
        delete fxi;
1✔
409
        return false;
1✔
410
    }
411

412
    // a D4 personality is always a user-made fixture
413
    fxi->setIsUser(true);
×
414
    fxi->setDefinitionSourceFile(path);
×
415
    fxi->setLoaded(true);
×
416

417
    /* Delete the def if it's a duplicate. */
418
    if (addFixtureDef(fxi) == false)
×
419
    {
420
        qDebug() << Q_FUNC_INFO << "Deleting duplicate" << path;
421
        delete fxi;
×
422
    }
423
    fxi = NULL;
424

425
    return true;
426
}
1✔
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