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

mcallegari / qlcplus / 7252848206

18 Dec 2023 07:26PM UTC coverage: 32.067% (+0.001%) from 32.066%
7252848206

push

github

mcallegari
Code style review #1427

199 of 628 new or added lines in 101 files covered. (31.69%)

8 existing lines in 2 files now uncovered.

15169 of 47304 relevant lines covered (32.07%)

23733.74 hits per line

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

91.45
/engine/src/doc.cpp
1
/*
2
  Q Light Controller Plus
3
  doc.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 <QStringList>
24
#include <QString>
25
#include <QDebug>
26
#include <QList>
27
#include <QTime>
28
#include <QDir>
29
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
30
#include <QRandomGenerator>
31
#endif
32

33
#include "qlcfixturemode.h"
34
#include "qlcfixturedef.h"
35

36
#include "monitorproperties.h"
37
#include "audioplugincache.h"
38
#include "rgbscriptscache.h"
39
#include "channelsgroup.h"
40
#include "scriptwrapper.h"
41
#include "collection.h"
42
#include "function.h"
43
#include "universe.h"
44
#include "sequence.h"
45
#include "fixture.h"
46
#include "chaser.h"
47
#include "show.h"
48
#include "doc.h"
49
#include "bus.h"
50

51
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
52
 #if defined(__APPLE__) || defined(Q_OS_MAC)
53
  #include "audiocapture_portaudio.h"
54
 #elif defined(WIN32) || defined (Q_OS_WIN)
55
  #include "audiocapture_wavein.h"
56
 #else
57
  #include "audiocapture_alsa.h"
58
 #endif
59
#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
60
 #include "audiocapture_qt5.h"
61
#else
62
 #include "audiocapture_qt6.h"
63
#endif
64

65
Doc::Doc(QObject* parent, int universes)
176✔
66
    : QObject(parent)
67
    , m_wsPath("")
68
    , m_fixtureDefCache(new QLCFixtureDefCache)
176✔
69
    , m_modifiersCache(new QLCModifiersCache)
176✔
70
    , m_rgbScriptsCache(new RGBScriptsCache(this))
176✔
71
    , m_ioPluginCache(new IOPluginCache(this))
176✔
72
    , m_audioPluginCache(new AudioPluginCache(this))
176✔
73
    , m_masterTimer(new MasterTimer(this))
176✔
74
    , m_ioMap(new InputOutputMap(this, universes))
176✔
75
    , m_monitorProps(NULL)
76
    , m_mode(Design)
77
    , m_kiosk(false)
78
    , m_loadStatus(Cleared)
79
    , m_clipboard(new QLCClipboard(this))
176✔
80
    , m_fixturesListCacheUpToDate(false)
81
    , m_latestFixtureId(0)
82
    , m_latestFixtureGroupId(0)
83
    , m_latestChannelsGroupId(0)
84
    , m_latestPaletteId(0)
85
    , m_latestFunctionId(0)
86
    , m_startupFunctionId(Function::invalidId())
1,584✔
87
{
88
    Bus::init(this);
176✔
89
    resetModified();
176✔
90
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
91
    qsrand(QTime::currentTime().msec());
92
#endif
93
    
94
}
176✔
95

96
Doc::~Doc()
312✔
97
{
98
    delete m_masterTimer;
176✔
99
    m_masterTimer = NULL;
176✔
100

101
    clearContents();
176✔
102

103
    if (isKiosk() == false)
176✔
104
    {
105
        // TODO: is this still needed ??
106
        //m_ioMap->saveDefaults();
107
    }
108
    delete m_ioMap;
176✔
109
    m_ioMap = NULL;
176✔
110

111
    delete m_ioPluginCache;
176✔
112
    m_ioPluginCache = NULL;
176✔
113

114
    delete m_modifiersCache;
176✔
115
    m_modifiersCache = NULL;
176✔
116

117
    delete m_fixtureDefCache;
176✔
118
    m_fixtureDefCache = NULL;
176✔
119
}
312✔
120

121
void Doc::clearContents()
449✔
122
{
123
    emit clearing();
449✔
124

125
    m_clipboard->resetContents();
449✔
126

127
    if (m_monitorProps != NULL)
449✔
128
        m_monitorProps->reset();
9✔
129

130
    destroyAudioCapture();
449✔
131

132
    // Delete all function instances
133
    QListIterator <quint32> funcit(m_functions.keys());
1,347✔
134
    while (funcit.hasNext() == true)
692✔
135
    {
136
        Function* func = m_functions.take(funcit.next());
243✔
137
        if (func == NULL)
243✔
138
            continue;
×
139
        emit functionRemoved(func->id());
243✔
140
        delete func;
243✔
141
    }
142

143
    // Delete all palettes
144
    QListIterator <quint32> palIt(m_palettes.keys());
1,347✔
145
    while (palIt.hasNext() == true)
449✔
146
    {
147
        QLCPalette *palette = m_palettes.take(palIt.next());
×
148
        emit paletteRemoved(palette->id());
×
149
        delete palette;
×
150
    }
151

152
    // Delete all channel groups
153
    QListIterator <quint32> grpchans(m_channelsGroups.keys());
1,347✔
154
    while (grpchans.hasNext() == true)
452✔
155
    {
156
        ChannelsGroup* grp = m_channelsGroups.take(grpchans.next());
3✔
157
        emit channelsGroupRemoved(grp->id());
3✔
158
        delete grp;
3✔
159
    }
160

161
    // Delete all fixture groups
162
    QListIterator <quint32> grpit(m_fixtureGroups.keys());
1,347✔
163
    while (grpit.hasNext() == true)
460✔
164
    {
165
        FixtureGroup* grp = m_fixtureGroups.take(grpit.next());
11✔
166
        quint32 grpID = grp->id();
11✔
167
        delete grp;
11✔
168
        emit fixtureGroupRemoved(grpID);
11✔
169
    }
170

171
    // Delete all fixture instances
172
    QListIterator <quint32> fxit(m_fixtures.keys());
1,347✔
173
    while (fxit.hasNext() == true)
17,222✔
174
    {
175
        Fixture* fxi = m_fixtures.take(fxit.next());
16,773✔
176
        quint32 fxID = fxi->id();
16,773✔
177
        delete fxi;
16,773✔
178
        emit fixtureRemoved(fxID);
16,773✔
179
    }
180
    m_fixturesListCacheUpToDate = false;
449✔
181

182
    m_orderedGroups.clear();
449✔
183

184
    m_latestFunctionId = 0;
449✔
185
    m_latestFixtureId = 0;
449✔
186
    m_latestFixtureGroupId = 0;
449✔
187
    m_latestChannelsGroupId = 0;
449✔
188
    m_latestPaletteId = 0;
449✔
189
    m_addresses.clear();
449✔
190
    m_loadStatus = Cleared;
449✔
191

192
    emit cleared();
449✔
193
}
449✔
194

195
void Doc::setWorkspacePath(QString path)
4✔
196
{
197
    m_wsPath = path;
4✔
198
}
4✔
199

200
QString Doc::getWorkspacePath() const
23✔
201
{
202
    return m_wsPath;
23✔
203
}
204

205
QString Doc::normalizeComponentPath(const QString& filePath) const
7✔
206
{
207
    if (filePath.isEmpty())
7✔
208
        return filePath;
1✔
209

210
    QFileInfo f(filePath);
12✔
211

212
    if (f.absolutePath().startsWith(getWorkspacePath()))
6✔
213
    {
214
        return QDir(getWorkspacePath()).relativeFilePath(f.absoluteFilePath());
8✔
215
    }
216
    else
217
    {
218
        return f.absoluteFilePath();
2✔
219
    }
220
}
221

222
QString Doc::denormalizeComponentPath(const QString& filePath) const
8✔
223
{
224
    if (filePath.isEmpty())
8✔
225
        return filePath;
2✔
226

227
    return QFileInfo(QDir(getWorkspacePath()), filePath).absoluteFilePath();
12✔
228
}
229

230
/*****************************************************************************
231
 * Engine components
232
 *****************************************************************************/
233

234
QLCFixtureDefCache* Doc::fixtureDefCache() const
1,581✔
235
{
236
    return m_fixtureDefCache;
1,581✔
237
}
238

239
void Doc::setFixtureDefinitionCache(QLCFixtureDefCache *cache)
×
240
{
241
    m_fixtureDefCache = cache;
×
242
}
×
243

244
QLCModifiersCache* Doc::modifiersCache() const
1✔
245
{
246
    return m_modifiersCache;
1✔
247
}
248

249
RGBScriptsCache* Doc::rgbScriptsCache() const
68✔
250
{
251
    return m_rgbScriptsCache;
68✔
252
}
253

254
IOPluginCache* Doc::ioPluginCache() const
287✔
255
{
256
    return m_ioPluginCache;
287✔
257
}
258

259
AudioPluginCache *Doc::audioPluginCache() const
1✔
260
{
261
    return m_audioPluginCache;
1✔
262
}
263

264
InputOutputMap* Doc::inputOutputMap() const
2,598✔
265
{
266
    return m_ioMap;
2,598✔
267
}
268

269
MasterTimer* Doc::masterTimer() const
1,097✔
270
{
271
    return m_masterTimer;
1,097✔
272
}
273

274
QSharedPointer<AudioCapture> Doc::audioInputCapture()
7✔
275
{
276
    if (!m_inputCapture)
7✔
277
    {
278
        qDebug() << "Creating new audio capture";
2✔
279
        m_inputCapture = QSharedPointer<AudioCapture>(
4✔
280
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
281
#if defined(__APPLE__) || defined(Q_OS_MAC)
282
            new AudioCapturePortAudio()
283
#elif defined(WIN32) || defined (Q_OS_WIN)
284
            new AudioCaptureWaveIn()
285
#else
286
            new AudioCaptureAlsa()
287
#endif
288
#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
289
            new AudioCaptureQt6()
2✔
290
#else
291
            new AudioCaptureQt6()
292
#endif
293
            );
2✔
294
    }
295
    return m_inputCapture;
7✔
296
}
297

298
void Doc::destroyAudioCapture()
449✔
299
{
300
    if (m_inputCapture.isNull() == false)
449✔
301
    {
302
        qDebug() << "Destroying audio capture";
2✔
303
        m_inputCapture.clear();
2✔
304
    }
305
}
449✔
306

307
/*****************************************************************************
308
 * Modified status
309
 *****************************************************************************/
310
Doc::LoadStatus Doc::loadStatus() const
2✔
311
{
312
    return m_loadStatus;
2✔
313
}
314

315
bool Doc::isModified() const
29✔
316
{
317
    return m_modified;
29✔
318
}
319

320
void Doc::setModified()
1,239✔
321
{
322
    m_modified = true;
1,239✔
323
    emit modified(true);
1,239✔
324
}
1,239✔
325

326
void Doc::resetModified()
191✔
327
{
328
    m_modified = false;
191✔
329
    emit modified(false);
191✔
330
}
191✔
331

332
/*****************************************************************************
333
 * Main operating mode
334
 *****************************************************************************/
335

336
void Doc::setMode(Doc::Mode mode)
23✔
337
{
338
    /* Don't do mode switching twice */
339
    if (m_mode == mode)
23✔
340
        return;
2✔
341
    m_mode = mode;
21✔
342

343
    // Run startup function
344
    if (m_mode == Operate && m_startupFunctionId != Function::invalidId())
21✔
345
    {
346
        Function *func = function(m_startupFunctionId);
×
347
        if (func != NULL)
×
348
        {
349
            qDebug() << Q_FUNC_INFO << "Starting startup function. (" << m_startupFunctionId << ")";
×
350
            func->start(masterTimer(), FunctionParent::master());
×
351
        }
352
        else
353
        {
354
            qWarning() << Q_FUNC_INFO << "Startup function does not exist, erasing. (" << m_startupFunctionId << ")";
×
355
            m_startupFunctionId = Function::invalidId();
×
356
        }
357
    }
358

359
    emit modeChanged(m_mode);
21✔
360
}
361

362
Doc::Mode Doc::mode() const
323✔
363
{
364
    return m_mode;
323✔
365
}
366

367
void Doc::setKiosk(bool state)
1✔
368
{
369
    m_kiosk = state;
1✔
370
}
1✔
371

372
bool Doc::isKiosk() const
178✔
373
{
374
    return m_kiosk;
178✔
375
}
376

377
/*********************************************************************
378
 * Clipboard
379
 *********************************************************************/
380

381
QLCClipboard *Doc::clipboard()
1✔
382
{
383
    return m_clipboard;
1✔
384
}
385

386
/*****************************************************************************
387
 * Fixtures
388
 *****************************************************************************/
389

390
quint32 Doc::createFixtureId()
33,413✔
391
{
392
    /* This results in an endless loop if there are UINT_MAX-1 fixtures. That,
393
       however, seems a bit unlikely. Are there even 4294967295-1 fixtures in
394
       total in the whole world? */
395
    while (m_fixtures.contains(m_latestFixtureId) == true ||
50,193✔
396
           m_latestFixtureId == Fixture::invalidId())
16,780✔
397
    {
398
        m_latestFixtureId++;
16,633✔
399
    }
400

401
    return m_latestFixtureId;
16,780✔
402
}
403

404
bool Doc::addFixture(Fixture* fixture, quint32 id)
405✔
405
{
406
    Q_ASSERT(fixture != NULL);
405✔
407

408
    quint32 i;
409
    quint32 uni = fixture->universe();
405✔
410

411
    // No ID given, this method can assign one
412
    if (id == Fixture::invalidId())
405✔
413
        id = createFixtureId();
396✔
414

415
    if (m_fixtures.contains(id) == true || id == Fixture::invalidId())
405✔
416
    {
417
        qWarning() << Q_FUNC_INFO << "a fixture with ID" << id << "already exists!";
1✔
418
        return false;
1✔
419
    }
420

421
    /* Check for overlapping address */
422
    for (i = fixture->universeAddress();
2,954✔
423
         i < fixture->universeAddress() + fixture->channels(); i++)
2,954✔
424
    {
425
        if (m_addresses.contains(i))
2,554✔
426
        {
427
            qWarning() << Q_FUNC_INFO << "fixture" << id << "overlapping with fixture" << m_addresses[i] << "@ channel" << i;
4✔
428
            return false;
4✔
429
        }
430
    }
431

432
    fixture->setID(id);
400✔
433
    m_fixtures.insert(id, fixture);
400✔
434
    m_fixturesListCacheUpToDate = false;
400✔
435

436
    /* Patch fixture change signals thru Doc */
437
    connect(fixture, SIGNAL(changed(quint32)),
400✔
438
            this, SLOT(slotFixtureChanged(quint32)));
439

440
    /* Keep track of fixture addresses */
441
    for (i = fixture->universeAddress();
400✔
442
         i < fixture->universeAddress() + fixture->channels(); i++)
2,950✔
443
    {
444
        m_addresses[i] = id;
2,550✔
445
    }
446

447
    if (uni >= inputOutputMap()->universesCount())
400✔
448
    {
449
        for (i = inputOutputMap()->universesCount(); i <= uni; i++)
×
450
            inputOutputMap()->addUniverse(i);
×
451
        inputOutputMap()->startUniverses();
×
452
    }
453

454
    // Add the fixture channels capabilities to the universe they belong
455
    QList<Universe *> universes = inputOutputMap()->claimUniverses();
800✔
456

457
    QList<int> forcedHTP = fixture->forcedHTPChannels();
800✔
458
    QList<int> forcedLTP = fixture->forcedLTPChannels();
400✔
459
    quint32 fxAddress = fixture->address();
400✔
460

461
    for (i = 0; i < fixture->channels(); i++)
2,950✔
462
    {
463
        const QLCChannel *channel(fixture->channel(i));
2,550✔
464

465
        // Inform Universe of any HTP/LTP forcing
466
        if (forcedHTP.contains(int(i)))
2,550✔
467
            universes.at(uni)->setChannelCapability(fxAddress + i, channel->group(), Universe::HTP);
×
468
        else if (forcedLTP.contains(int(i)))
2,550✔
469
            universes.at(uni)->setChannelCapability(fxAddress + i, channel->group(), Universe::LTP);
1✔
470
        else
471
            universes.at(uni)->setChannelCapability(fxAddress + i, channel->group());
2,549✔
472

473
        // Apply the default value BEFORE modifiers
474
        universes.at(uni)->setChannelDefaultValue(fxAddress + i, channel->defaultValue());
2,550✔
475

476
        // Apply a channel modifier, if defined
477
        ChannelModifier *mod = fixture->channelModifier(i);
2,550✔
478
        universes.at(uni)->setChannelModifier(fxAddress + i, mod);
2,550✔
479
    }
480
    inputOutputMap()->releaseUniverses(true);
400✔
481

482
    emit fixtureAdded(id);
400✔
483
    setModified();
400✔
484

485
    return true;
400✔
486
}
487

488
bool Doc::deleteFixture(quint32 id)
16✔
489
{
490
    if (m_fixtures.contains(id) == true)
16✔
491
    {
492
        Fixture* fxi = m_fixtures.take(id);
10✔
493
        Q_ASSERT(fxi != NULL);
10✔
494
        m_fixturesListCacheUpToDate = false;
10✔
495

496
        /* Keep track of fixture addresses */
497
        QMutableHashIterator <uint,uint> it(m_addresses);
10✔
498
        while (it.hasNext() == true)
102✔
499
        {
500
            it.next();
92✔
501
            if (it.value() == id)
92✔
502
                it.remove();
47✔
503
        }
504
        if (m_monitorProps != NULL)
10✔
505
            m_monitorProps->removeFixture(id);
×
506

507
        emit fixtureRemoved(id);
10✔
508
        setModified();
10✔
509
        delete fxi;
10✔
510

511
        if (m_fixtures.count() == 0)
10✔
512
            m_latestFixtureId = 0;
6✔
513

514
        return true;
10✔
515
    }
516
    else
517
    {
518
        qWarning() << Q_FUNC_INFO << "No fixture with id" << id;
6✔
519
        return false;
6✔
520
    }
521
}
522

523
bool Doc::replaceFixtures(QList<Fixture*> newFixturesList)
1✔
524
{
525
    // Delete all fixture instances
526
    QListIterator <quint32> fxit(m_fixtures.keys());
2✔
527
    while (fxit.hasNext() == true)
4✔
528
    {
529
        Fixture* fxi = m_fixtures.take(fxit.next());
3✔
530
        disconnect(fxi, SIGNAL(changed(quint32)),
3✔
531
                   this, SLOT(slotFixtureChanged(quint32)));
532
        delete fxi;
3✔
533
        m_fixturesListCacheUpToDate = false;
3✔
534
    }
535
    m_latestFixtureId = 0;
1✔
536
    m_addresses.clear();
1✔
537

538
    foreach (Fixture *fixture, newFixturesList)
5✔
539
    {
540
        quint32 id = fixture->id();
2✔
541
        // create a copy of the original cause remapping will
542
        // destroy it later
543
        Fixture *newFixture = new Fixture(this);
2✔
544
        newFixture->setID(id);
2✔
545
        newFixture->setName(fixture->name());
2✔
546
        newFixture->setAddress(fixture->address());
2✔
547
        newFixture->setUniverse(fixture->universe());
2✔
548

549
        if (fixture->fixtureDef() == NULL ||
5✔
550
            (fixture->fixtureDef()->manufacturer() == KXMLFixtureGeneric &&
5✔
551
             fixture->fixtureDef()->model() == KXMLFixtureGeneric))
3✔
552
        {
553
            // Generic dimmers just need to know the number of channels
554
            newFixture->setChannels(fixture->channels());
1✔
555
        }
556
        else if (fixture->fixtureDef() == NULL ||
2✔
557
            (fixture->fixtureDef()->manufacturer() == KXMLFixtureGeneric &&
2✔
558
             fixture->fixtureDef()->model() == KXMLFixtureRGBPanel))
1✔
559
        {
560
            // RGB Panels definitions are not cached or shared, so
561
            // let's make a deep copy of them
562
            QLCFixtureDef *fixtureDef = new QLCFixtureDef();
×
563
            *fixtureDef = *fixture->fixtureDef();
×
564
            QLCFixtureMode *mode = new QLCFixtureMode(fixtureDef);
×
565
            *mode = *fixture->fixtureMode();
×
566
            newFixture->setFixtureDefinition(fixtureDef, mode);
×
567
        }
568
        else
569
        {
570
            QLCFixtureDef *def = fixtureDefCache()->fixtureDef(fixture->fixtureDef()->manufacturer(),
2✔
571
                                                               fixture->fixtureDef()->model());
2✔
572
            QLCFixtureMode *mode = NULL;
1✔
573
            if (def != NULL)
1✔
574
                mode = def->mode(fixture->fixtureMode()->name());
1✔
575
            newFixture->setFixtureDefinition(def, mode);
1✔
576
        }
577

578
        newFixture->setExcludeFadeChannels(fixture->excludeFadeChannels());
2✔
579
        newFixture->setForcedHTPChannels(fixture->forcedHTPChannels());
2✔
580
        newFixture->setForcedLTPChannels(fixture->forcedLTPChannels());
2✔
581

582
        m_fixtures.insert(id, newFixture);
2✔
583
        m_fixturesListCacheUpToDate = false;
2✔
584

585
        /* Patch fixture change signals thru Doc */
586
        connect(newFixture, SIGNAL(changed(quint32)),
2✔
587
                this, SLOT(slotFixtureChanged(quint32)));
588

589
        /* Keep track of fixture addresses */
590
        for (uint i = newFixture->universeAddress();
2✔
591
             i < newFixture->universeAddress() + newFixture->channels(); i++)
13✔
592
        {
593
            m_addresses[i] = id;
11✔
594
        }
595
        m_latestFixtureId = id;
2✔
596
    }
597
    return true;
2✔
598
}
599

600
bool Doc::updateFixtureChannelCapabilities(quint32 id, QList<int> forcedHTP, QList<int> forcedLTP)
2✔
601
{
602
    if (m_fixtures.contains(id) == false)
2✔
603
        return false;
1✔
604

605
    Fixture* fixture = m_fixtures[id];
1✔
606
    // get exclusive access to the universes list
607
    QList<Universe *> universes = inputOutputMap()->claimUniverses();
1✔
608
    Universe *universe = universes.at(fixture->universe());
1✔
609
    quint32 fxAddress = fixture->address();
1✔
610

611
    // Set forced HTP channels
612
    fixture->setForcedHTPChannels(forcedHTP);
1✔
613

614
    // Set forced LTP channels
615
    fixture->setForcedLTPChannels(forcedLTP);
1✔
616

617
    // Update the Fixture Universe with the current channel states
618
    for (quint32 i = 0 ; i < fixture->channels(); i++)
7✔
619
    {
620
        const QLCChannel *channel(fixture->channel(i));
6✔
621

622
        // Inform Universe of any HTP/LTP forcing
623
        if (forcedHTP.contains(int(i)))
6✔
624
            universe->setChannelCapability(fxAddress + i, channel->group(), Universe::HTP);
2✔
625
        else if (forcedLTP.contains(int(i)))
4✔
626
            universe->setChannelCapability(fxAddress + i, channel->group(), Universe::LTP);
1✔
627
        else
628
            universe->setChannelCapability(fxAddress + i, channel->group());
3✔
629

630
        // Apply the default value BEFORE modifiers
631
        universe->setChannelDefaultValue(fxAddress + i, channel->defaultValue());
6✔
632

633
        // Apply a channel modifier, if defined
634
        ChannelModifier *mod = fixture->channelModifier(i);
6✔
635
        universe->setChannelModifier(fxAddress + i, mod);
6✔
636
    }
637

638
    inputOutputMap()->releaseUniverses(true);
1✔
639

640
    return true;
1✔
641
}
642

643
QList<Fixture*> const& Doc::fixtures() const
71✔
644
{
645
    if (!m_fixturesListCacheUpToDate)
71✔
646
    {
647
        // Sort fixtures by id
648
        QMap <quint32, Fixture*> fixturesMap;
80✔
649
        QHashIterator <quint32, Fixture*> hashIt(m_fixtures);
40✔
650
        while (hashIt.hasNext())
75✔
651
        {
652
            hashIt.next();
35✔
653
            fixturesMap.insert(hashIt.key(), hashIt.value());
35✔
654
        }
655
        const_cast<QList<Fixture*>&>(m_fixturesListCache) = fixturesMap.values();
40✔
656
        const_cast<bool&>(m_fixturesListCacheUpToDate) = true;
40✔
657
    }
658
    return m_fixturesListCache;
71✔
659
}
660

661
Fixture* Doc::fixture(quint32 id) const
796,448✔
662
{
663
    return m_fixtures.value(id, NULL);
796,448✔
664
}
665

666
quint32 Doc::fixtureForAddress(quint32 universeAddress) const
80✔
667
{
668
    return m_addresses.value(universeAddress, Fixture::invalidId());
80✔
669
}
670

671
int Doc::totalPowerConsumption(int& fuzzy) const
4✔
672
{
673
    int totalPowerConsumption = 0;
4✔
674

675
    // Make sure fuzzy starts from zero
676
    fuzzy = 0;
4✔
677

678
    QListIterator <Fixture*> fxit(fixtures());
4✔
679
    while (fxit.hasNext() == true)
14✔
680
    {
681
        Fixture* fxi(fxit.next());
10✔
682
        Q_ASSERT(fxi != NULL);
10✔
683

684
        if (fxi->fixtureMode() != NULL)
10✔
685
        {
686
            QLCPhysical phys = fxi->fixtureMode()->physical();
20✔
687
            if (phys.powerConsumption() > 0)
10✔
688
                totalPowerConsumption += phys.powerConsumption();
7✔
689
            else
690
                fuzzy++;
3✔
691
        }
692
        else
693
        {
694
            fuzzy++;
×
695
        }
696
    }
697

698
    return totalPowerConsumption;
8✔
699
}
700

701
void Doc::slotFixtureChanged(quint32 id)
4✔
702
{
703
    /* Keep track of fixture addresses */
704
    Fixture* fxi = fixture(id);
4✔
705

706
    // remove it
707
    QMutableHashIterator <uint,uint> it(m_addresses);
4✔
708
    while (it.hasNext() == true)
67✔
709
    {
710
        it.next();
63✔
711
        if (it.value() == id)
63✔
712
        {
713
            qDebug() << Q_FUNC_INFO << " remove: " << it.key() << " val: " << it.value();
19✔
714
            it.remove();
19✔
715
        }
716
    }
717

718
    for (uint i = fxi->universeAddress(); i < fxi->universeAddress() + fxi->channels(); i++)
23✔
719
    {
720
        /*
721
         * setting new universe and address calls this twice,
722
         * with an tmp wrong address after the first call (old address() + new universe()).
723
         * we only add if the channel is free, to prevent messing up things
724
         */
725
        Q_ASSERT(!m_addresses.contains(i));
19✔
726
        m_addresses[i] = id;
19✔
727
    }
728

729
    setModified();
4✔
730
    emit fixtureChanged(id);
4✔
731
}
4✔
732

733
/*****************************************************************************
734
 * Fixture groups
735
 *****************************************************************************/
736

737
bool Doc::addFixtureGroup(FixtureGroup* grp, quint32 id)
15✔
738
{
739
    Q_ASSERT(grp != NULL);
15✔
740

741
    // No ID given, this method can assign one
742
    if (id == FixtureGroup::invalidId())
15✔
743
        id = createFixtureGroupId();
8✔
744

745
    if (m_fixtureGroups.contains(id) == true || id == FixtureGroup::invalidId())
15✔
746
    {
747
        qWarning() << Q_FUNC_INFO << "a fixture group with ID" << id << "already exists!";
2✔
748
        return false;
2✔
749
    }
750
    else
751
    {
752
        grp->setId(id);
13✔
753
        m_fixtureGroups[id] = grp;
13✔
754

755
        /* Patch fixture group change signals thru Doc */
756
        connect(grp, SIGNAL(changed(quint32)),
13✔
757
                this, SLOT(slotFixtureGroupChanged(quint32)));
758

759
        emit fixtureGroupAdded(id);
13✔
760
        setModified();
13✔
761

762
        return true;
13✔
763
    }
764
}
765

766
bool Doc::deleteFixtureGroup(quint32 id)
4✔
767
{
768
    if (m_fixtureGroups.contains(id) == true)
4✔
769
    {
770
        FixtureGroup* grp = m_fixtureGroups.take(id);
2✔
771
        Q_ASSERT(grp != NULL);
2✔
772

773
        emit fixtureGroupRemoved(id);
2✔
774
        setModified();
2✔
775
        delete grp;
2✔
776

777
        return true;
2✔
778
    }
779
    else
780
    {
781
        qWarning() << Q_FUNC_INFO << "No fixture group with id" << id;
2✔
782
        return false;
2✔
783
    }
784
}
785

786
FixtureGroup* Doc::fixtureGroup(quint32 id) const
47✔
787
{
788
    if (m_fixtureGroups.contains(id) == true)
47✔
789
        return m_fixtureGroups[id];
21✔
790
    else
791
        return NULL;
26✔
792
}
793

794
QList <FixtureGroup*> Doc::fixtureGroups() const
34✔
795
{
796
    return m_fixtureGroups.values();
34✔
797
}
798

799
quint32 Doc::createFixtureGroupId()
12✔
800
{
801
    /* This results in an endless loop if there are UINT_MAX-1 fixture groups. That,
802
       however, seems a bit unlikely. Are there even 4294967295-1 fixtures in
803
       total in the whole world? */
804
    while (m_fixtureGroups.contains(m_latestFixtureGroupId) == true ||
20✔
805
           m_latestFixtureGroupId == FixtureGroup::invalidId())
8✔
806
    {
807
        m_latestFixtureGroupId++;
4✔
808
    }
809

810
    return m_latestFixtureGroupId;
8✔
811
}
812

813
void Doc::slotFixtureGroupChanged(quint32 id)
25✔
814
{
815
    setModified();
25✔
816
    emit fixtureGroupChanged(id);
25✔
817
}
25✔
818

819
/*********************************************************************
820
 * Channels groups
821
 *********************************************************************/
822
bool Doc::addChannelsGroup(ChannelsGroup *grp, quint32 id)
4✔
823
{
824
    Q_ASSERT(grp != NULL);
4✔
825

826
    // No ID given, this method can assign one
827
    if (id == ChannelsGroup::invalidId())
4✔
828
        id = createChannelsGroupId();
4✔
829

830
     grp->setId(id);
4✔
831
     m_channelsGroups[id] = grp;
4✔
832
     if (m_orderedGroups.contains(id) == false)
4✔
833
        m_orderedGroups.append(id);
4✔
834

835
     emit channelsGroupAdded(id);
4✔
836
     setModified();
4✔
837

838
     return true;
4✔
839
}
840

841
bool Doc::deleteChannelsGroup(quint32 id)
2✔
842
{
843
    if (m_channelsGroups.contains(id) == true)
2✔
844
    {
845
        ChannelsGroup* grp = m_channelsGroups.take(id);
1✔
846
        Q_ASSERT(grp != NULL);
1✔
847

848
        emit channelsGroupRemoved(id);
1✔
849
        setModified();
1✔
850
        delete grp;
1✔
851

852
        int idx = m_orderedGroups.indexOf(id);
1✔
853
        if (idx != -1)
1✔
854
            m_orderedGroups.takeAt(idx);
1✔
855

856
        return true;
1✔
857
    }
858
    else
859
    {
860
        qWarning() << Q_FUNC_INFO << "No channels group with id" << id;
1✔
861
        return false;
1✔
862
    }
863
}
864

865
bool Doc::moveChannelGroup(quint32 id, int direction)
3✔
866
{
867
    if (direction == 0 || m_orderedGroups.contains(id) == false)
3✔
868
        return false;
1✔
869

870
    int idx = m_orderedGroups.indexOf(id);
2✔
871

872
    if (idx + direction < 0 || idx + direction >= m_orderedGroups.count())
2✔
873
        return false;
1✔
874

875
    qDebug() << Q_FUNC_INFO << m_orderedGroups;
1✔
876
    m_orderedGroups.takeAt(idx);
1✔
877
    m_orderedGroups.insert(idx + direction, id);
1✔
878
    qDebug() << Q_FUNC_INFO << m_orderedGroups;
1✔
879

880
    setModified();
1✔
881
    return true;
1✔
882
}
883

884
ChannelsGroup* Doc::channelsGroup(quint32 id) const
2✔
885
{
886
    if (m_channelsGroups.contains(id) == true)
2✔
887
        return m_channelsGroups[id];
1✔
888
    else
889
        return NULL;
1✔
890
}
891

892
QList <ChannelsGroup*> Doc::channelsGroups() const
15✔
893
{
894
    QList <ChannelsGroup*> orderedList;
15✔
895

896
    for (int i = 0; i < m_orderedGroups.count(); i++)
37✔
897
    {
898
        orderedList.append(m_channelsGroups[m_orderedGroups.at(i)]);
22✔
899
    }
900
    return orderedList;
15✔
901
}
902

903
quint32 Doc::createChannelsGroupId()
6✔
904
{
905
    while (m_channelsGroups.contains(m_latestChannelsGroupId) == true ||
10✔
906
           m_latestChannelsGroupId == ChannelsGroup::invalidId())
4✔
907
    {
908
        m_latestChannelsGroupId++;
2✔
909
    }
910

911
    return m_latestChannelsGroupId;
4✔
912
}
913

914
/*********************************************************************
915
 * Palettes
916
 *********************************************************************/
917

918
bool Doc::addPalette(QLCPalette *palette, quint32 id)
2✔
919
{
920
    Q_ASSERT(palette != NULL);
2✔
921

922
    // No ID given, this method can assign one
923
    if (id == QLCPalette::invalidId())
2✔
924
        id = createPaletteId();
2✔
925

926
    if (m_palettes.contains(id) == true || id == QLCPalette::invalidId())
2✔
927
    {
928
        qWarning() << Q_FUNC_INFO << "a palette with ID" << id << "already exists!";
×
929
        return false;
×
930
    }
931
    else
932
    {
933
        palette->setID(id);
2✔
934
        m_palettes[id] = palette;
2✔
935

936
        emit paletteAdded(id);
2✔
937
        setModified();
2✔
938
    }
939

940
    return true;
2✔
941
}
942

943
bool Doc::deletePalette(quint32 id)
3✔
944
{
945
    if (m_palettes.contains(id) == true)
3✔
946
    {
947
        QLCPalette *palette = m_palettes.take(id);
2✔
948
        Q_ASSERT(palette != NULL);
2✔
949

950
        emit paletteRemoved(id);
2✔
951
        setModified();
2✔
952
        delete palette;
2✔
953

954
        return true;
2✔
955
    }
956
    else
957
    {
958
        qWarning() << Q_FUNC_INFO << "No palette with id" << id;
1✔
959
        return false;
1✔
960
    }
961
}
962

963
QLCPalette *Doc::palette(quint32 id) const
2✔
964
{
965
    if (m_palettes.contains(id) == true)
2✔
966
        return m_palettes[id];
1✔
967
    else
968
        return NULL;
1✔
969
}
970

971
QList<QLCPalette *> Doc::palettes() const
8✔
972
{
973
    return m_palettes.values();
8✔
974
}
975

976
quint32 Doc::createPaletteId()
3✔
977
{
978
    while (m_palettes.contains(m_latestPaletteId) == true ||
5✔
979
           m_latestPaletteId == FixtureGroup::invalidId())
2✔
980
    {
981
        m_latestPaletteId++;
1✔
982
    }
983

984
    return m_latestPaletteId;
2✔
985
}
986

987
/*****************************************************************************
988
 * Functions
989
 *****************************************************************************/
990

991
quint32 Doc::createFunctionId()
405✔
992
{
993
    /* This results in an endless loop if there are UINT_MAX-1 functions. That,
994
       however, seems a bit unlikely. Are there even 4294967295-1 functions in
995
       total in the whole world? */
996
    while (m_functions.contains(m_latestFunctionId) == true ||
645✔
997
           m_latestFunctionId == Fixture::invalidId())
240✔
998
    {
999
        m_latestFunctionId++;
165✔
1000
    }
1001

1002
    return m_latestFunctionId;
240✔
1003
}
1004

1005
bool Doc::addFunction(Function* func, quint32 id)
253✔
1006
{
1007
    Q_ASSERT(func != NULL);
253✔
1008

1009
    if (id == Function::invalidId())
253✔
1010
        id = createFunctionId();
240✔
1011

1012
    if (m_functions.contains(id) == true || id == Fixture::invalidId())
253✔
1013
    {
1014
        qWarning() << Q_FUNC_INFO << "a function with ID" << id << "already exists!";
2✔
1015
        return false;
2✔
1016
    }
1017
    else
1018
    {
1019
        // Listen to function changes
1020
        connect(func, SIGNAL(changed(quint32)),
251✔
1021
                this, SLOT(slotFunctionChanged(quint32)));
1022

1023
        // Listen to function name changes
1024
        connect(func, SIGNAL(nameChanged(quint32)),
251✔
1025
                this, SLOT(slotFunctionNameChanged(quint32)));
1026

1027
        // Make the function listen to fixture removals
1028
        connect(this, SIGNAL(fixtureRemoved(quint32)),
251✔
1029
                func, SLOT(slotFixtureRemoved(quint32)));
1030

1031
        // Place the function in the map and assign it the new ID
1032
        m_functions[id] = func;
251✔
1033
        func->setID(id);
251✔
1034
        emit functionAdded(id);
251✔
1035
        setModified();
251✔
1036

1037
        return true;
251✔
1038
    }
1039
}
1040

1041
QList <Function*> Doc::functions() const
49✔
1042
{
1043
    return m_functions.values();
49✔
1044
}
1045

1046
QList<Function *> Doc::functionsByType(Function::Type type) const
1✔
1047
{
1048
    QList <Function*> list;
1✔
1049
    foreach (Function *f, m_functions)
19✔
1050
    {
1051
        if (f != NULL && f->type() == type)
9✔
1052
            list.append(f);
5✔
1053
    }
1054
    return list;
1✔
1055
}
1056

1057
Function *Doc::functionByName(QString name)
×
1058
{
NEW
1059
    foreach (Function *f, m_functions)
×
1060
    {
1061
        if (f != NULL && f->name() == name)
×
1062
            return f;
×
1063
    }
1064
    return NULL;
×
1065
}
1066

1067
bool Doc::deleteFunction(quint32 id)
10✔
1068
{
1069
    if (m_functions.contains(id) == true)
10✔
1070
    {
1071
        Function* func = m_functions.take(id);
8✔
1072
        Q_ASSERT(func != NULL);
8✔
1073

1074
        if (m_startupFunctionId == id)
8✔
1075
            m_startupFunctionId = Function::invalidId();
×
1076

1077
        emit functionRemoved(id);
8✔
1078
        setModified();
8✔
1079
        delete func;
8✔
1080

1081
        return true;
8✔
1082
    }
1083
    else
1084
    {
1085
        qWarning() << Q_FUNC_INFO << "No function with id" << id;
2✔
1086
        return false;
2✔
1087
    }
1088
}
1089

1090
Function* Doc::function(quint32 id) const
878✔
1091
{
1092
    if (m_functions.contains(id) == true)
878✔
1093
        return m_functions[id];
815✔
1094
    else
1095
        return NULL;
63✔
1096
}
1097

1098
quint32 Doc::nextFunctionID()
2✔
1099
{
1100
    quint32 tmpFID = m_latestFunctionId;
2✔
1101
    while (m_functions.contains(tmpFID) == true ||
5✔
1102
           tmpFID == Fixture::invalidId())
2✔
1103
    {
1104
        tmpFID++;
1✔
1105
    }
1106

1107
    return tmpFID;
2✔
1108
}
1109

1110
void Doc::setStartupFunction(quint32 fid)
1✔
1111
{
1112
    m_startupFunctionId = fid;
1✔
1113
}
1✔
1114

1115
quint32 Doc::startupFunction()
3✔
1116
{
1117
    return m_startupFunctionId;
3✔
1118
}
1119

1120
QList<quint32> Doc::getUsage(quint32 fid)
7✔
1121
{
1122
    QList<quint32> usageList;
7✔
1123

1124
    foreach (Function *f, m_functions)
133✔
1125
    {
1126
        if (f->id() == fid)
63✔
1127
            continue;
6✔
1128

1129
        switch(f->type())
57✔
1130
        {
1131
            case Function::CollectionType:
7✔
1132
            {
1133
                Collection *c = qobject_cast<Collection *>(f);
7✔
1134
                int pos = c->functions().indexOf(fid);
7✔
1135
                if (pos != -1)
7✔
1136
                {
1137
                    usageList.append(f->id());
2✔
1138
                    usageList.append(pos);
2✔
1139
                }
1140
            }
1141
            break;
7✔
1142
            case Function::ChaserType:
6✔
1143

1144
            {
1145
                Chaser *c = qobject_cast<Chaser *>(f);
6✔
1146
                for (int i = 0; i < c->stepsCount(); i++)
18✔
1147
                {
1148
                    ChaserStep *cs = c->stepAt(i);
12✔
1149
                    if (cs->fid == fid)
12✔
1150
                    {
1151
                        usageList.append(f->id());
2✔
1152
                        usageList.append(i);
2✔
1153
                    }
1154
                }
1155
            }
1156
            break;
6✔
1157
            case Function::SequenceType:
7✔
1158
            {
1159
                Sequence *s = qobject_cast<Sequence *>(f);
7✔
1160
                if (s->boundSceneID() == fid)
7✔
1161
                {
1162
                    usageList.append(f->id());
1✔
1163
                    usageList.append(0);
1✔
1164
                }
1165
            }
1166
            break;
7✔
1167
            case Function::ScriptType:
7✔
1168
            {
1169
                Script *s = qobject_cast<Script *>(f);
7✔
1170
                QList<quint32> l = s->functionList();
14✔
1171
                for (int i = 0; i < l.count(); i+=2)
14✔
1172
                {
1173
                    if (l.at(i) == fid)
7✔
1174
                    {
1175
                        if (i + 1 >= l.count()) {
1✔
1176
                            qDebug() << "Doc::getUsage: Index entry missing on " << f->name();
×
1177
                            break;
×
1178
                        }
1179
                        usageList.append(s->id());
1✔
1180
                        usageList.append(l.at(i + 1)); // line number
1✔
1181
                    }
1182
                }
1183
            }
1184
            break;
7✔
1185
            case Function::ShowType:
×
1186
            {
1187
                Show *s = qobject_cast<Show *>(f);
×
1188
                foreach (Track *t, s->tracks())
×
1189
                {
NEW
1190
                    foreach (ShowFunction *sf, t->showFunctions())
×
1191
                    {
1192
                        if (sf->functionID() == fid)
×
1193
                        {
1194
                            usageList.append(f->id());
×
1195
                            usageList.append(t->id());
×
1196
                        }
1197
                    }
1198
                }
1199
            }
1200
            break;
×
1201
            default:
30✔
1202
            break;
30✔
1203
        }
1204
    }
1205

1206
    return usageList;
7✔
1207
}
1208

1209
void Doc::slotFunctionChanged(quint32 fid)
109✔
1210
{
1211
    setModified();
109✔
1212
    emit functionChanged(fid);
109✔
1213
}
109✔
1214

1215
void Doc::slotFunctionNameChanged(quint32 fid)
2✔
1216
{
1217
    setModified();
2✔
1218
    emit functionNameChanged(fid);
2✔
1219
}
2✔
1220

1221
/*********************************************************************
1222
 * Monitor Properties
1223
 *********************************************************************/
1224

1225
MonitorProperties *Doc::monitorProperties()
1✔
1226
{
1227
    if (m_monitorProps == NULL)
1✔
1228
        m_monitorProps = new MonitorProperties();
1✔
1229

1230
    return m_monitorProps;
1✔
1231
}
1232

1233
/*****************************************************************************
1234
 * Load & Save
1235
 *****************************************************************************/
1236

1237
bool Doc::loadXML(QXmlStreamReader &doc, bool loadIO)
2✔
1238
{
1239
    clearErrorLog();
2✔
1240

1241
    if (doc.name() != KXMLQLCEngine)
2✔
1242
    {
1243
        qWarning() << Q_FUNC_INFO << "Engine node not found";
1✔
1244
        return false;
1✔
1245
    }
1246

1247
    m_loadStatus = Loading;
1✔
1248
    emit loading();
1✔
1249

1250
    if (doc.attributes().hasAttribute(KXMLQLCStartupFunction))
1✔
1251
    {
1252
        quint32 sID = doc.attributes().value(KXMLQLCStartupFunction).toString().toUInt();
×
1253
        if (sID != Function::invalidId())
×
1254
            setStartupFunction(sID);
×
1255
    }
1256

1257
    while (doc.readNextStartElement())
17✔
1258
    {
1259
        //qDebug() << "Doc tag:" << doc.name();
1260
        if (doc.name() == KXMLFixture)
16✔
1261
        {
1262
            Fixture::loader(doc, this);
3✔
1263
        }
1264
        else if (doc.name() == KXMLQLCFixtureGroup)
13✔
1265
        {
1266
            FixtureGroup::loader(doc, this);
3✔
1267
        }
1268
        else if (doc.name() == KXMLQLCChannelsGroup)
10✔
1269
        {
1270
            ChannelsGroup::loader(doc, this);
×
1271
        }
1272
        else if (doc.name() == KXMLQLCPalette)
10✔
1273
        {
1274
            QLCPalette::loader(doc, this);
×
1275
            doc.skipCurrentElement();
×
1276
        }
1277
        else if (doc.name() == KXMLQLCFunction)
10✔
1278
        {
1279
            //qDebug() << doc.attributes().value("Name").toString();
1280
            Function::loader(doc, this);
4✔
1281
        }
1282
        else if (doc.name() == KXMLQLCBus)
6✔
1283
        {
1284
            /* LEGACY */
1285
            Bus::instance()->loadXML(doc);
5✔
1286
        }
1287
        else if (doc.name() == KXMLIOMap && loadIO)
1✔
1288
        {
1289
            m_ioMap->loadXML(doc);
×
1290
        }
1291
        else if (doc.name() == KXMLQLCMonitorProperties)
1✔
1292
        {
1293
            monitorProperties()->loadXML(doc, this);
×
1294
        }
1295
        else
1296
        {
1297
            qWarning() << Q_FUNC_INFO << "Unknown engine tag:" << doc.name();
1✔
1298
            doc.skipCurrentElement();
1✔
1299
        }
1300
    }
1301

1302
    postLoad();
1✔
1303

1304
    m_loadStatus = Loaded;
1✔
1305
    emit loaded();
1✔
1306

1307
    return true;
1✔
1308
}
1309

1310
bool Doc::saveXML(QXmlStreamWriter *doc)
1✔
1311
{
1312
    Q_ASSERT(doc != NULL);
1✔
1313

1314
    /* Create the master Engine node */
1315
    doc->writeStartElement(KXMLQLCEngine);
1✔
1316

1317
    if (startupFunction() != Function::invalidId())
1✔
1318
        doc->writeAttribute(KXMLQLCStartupFunction, QString::number(startupFunction()));
1✔
1319

1320
    m_ioMap->saveXML(doc);
1✔
1321

1322
    /* Write fixtures into an XML document */
1323
    QListIterator <Fixture*> fxit(fixtures());
2✔
1324
    while (fxit.hasNext() == true)
4✔
1325
    {
1326
        Fixture *fxi(fxit.next());
3✔
1327
        Q_ASSERT(fxi != NULL);
3✔
1328
        fxi->saveXML(doc);
3✔
1329
    }
1330

1331
    /* Write fixture groups into an XML document */
1332
    QListIterator <FixtureGroup*> grpit(fixtureGroups());
3✔
1333
    while (grpit.hasNext() == true)
3✔
1334
    {
1335
        FixtureGroup *grp(grpit.next());
2✔
1336
        Q_ASSERT(grp != NULL);
2✔
1337
        grp->saveXML(doc);
2✔
1338
    }
1339

1340
    /* Write channel groups into an XML document */
1341
    QListIterator <ChannelsGroup*> chanGroups(channelsGroups());
3✔
1342
    while (chanGroups.hasNext() == true)
1✔
1343
    {
1344
        ChannelsGroup *grp(chanGroups.next());
×
1345
        Q_ASSERT(grp != NULL);
×
1346
        grp->saveXML(doc);
×
1347
    }
1348

1349
    /* Write palettes into an XML document */
1350
    QListIterator <QLCPalette*> paletteIt(palettes());
3✔
1351
    while (paletteIt.hasNext() == true)
1✔
1352
    {
1353
        QLCPalette *palette(paletteIt.next());
×
1354
        Q_ASSERT(palette != NULL);
×
1355
        palette->saveXML(doc);
×
1356
    }
1357

1358
    /* Write functions into an XML document */
1359
    QListIterator <Function*> funcit(functions());
2✔
1360
    while (funcit.hasNext() == true)
5✔
1361
    {
1362
        Function *func(funcit.next());
4✔
1363
        Q_ASSERT(func != NULL);
4✔
1364
        func->saveXML(doc);
4✔
1365
    }
1366

1367
    if (m_monitorProps != NULL)
1✔
1368
        m_monitorProps->saveXML(doc, this);
1✔
1369

1370
    /* End the <Engine> tag */
1371
    doc->writeEndElement();
1✔
1372

1373
    return true;
2✔
1374
}
1375

1376
void Doc::appendToErrorLog(QString error)
8✔
1377
{
1378
    if (m_errorLog.contains(error))
8✔
1379
        return;
5✔
1380

1381
    m_errorLog.append(error);
3✔
1382
    m_errorLog.append("<br>");
3✔
1383
}
1384

1385
void Doc::clearErrorLog()
2✔
1386
{
1387
    m_errorLog = "";
2✔
1388
}
2✔
1389

1390
QString Doc::errorLog()
1✔
1391
{
1392
    return m_errorLog;
1✔
1393
}
1394

1395
void Doc::postLoad()
1✔
1396
{
1397
    QListIterator <Function*> functionit(functions());
3✔
1398
    while (functionit.hasNext() == true)
5✔
1399
    {
1400
        Function* function(functionit.next());
4✔
1401
        Q_ASSERT(function != NULL);
4✔
1402
        function->postLoad();
4✔
1403
    }
1404
}
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