• 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

68.34
/engine/src/show.cpp
1
/*
2
  Q Light Controller Plus
3
  show.cpp
4

5
  Copyright (c) Massimo Callegari
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 <QXmlStreamReader>
21
#include <QXmlStreamWriter>
22
#include <QString>
23
#include <QDebug>
24
#include <QFile>
25
#include <QList>
26

27
#include "showrunner.h"
28
#include "function.h"
29
#include "show.h"
30
#include "doc.h"
31

32
#define KXMLQLCShowTimeDivision QString("TimeDivision")
33
#define KXMLQLCShowTimeType     QString("Type")
34
#define KXMLQLCShowTimeBPM      QString("BPM")
35

36
/*****************************************************************************
37
 * Initialization
38
 *****************************************************************************/
39

40
Show::Show(Doc* doc) : Function(doc, Function::ShowType)
8✔
41
    , m_timeDivisionType(Time)
42
    , m_timeDivisionBPM(120)
43
    , m_latestTrackId(0)
44
    , m_latestShowFunctionID(0)
45
    , m_runner(NULL)
8✔
46
{
47
    setName(tr("New Show"));
8✔
48

49
    // Clear attributes here. I want attributes to be mapped
50
    // exactly like the Show tracks
51
    unregisterAttribute(tr("Intensity"));
8✔
52
}
8✔
53

54
Show::~Show()
8✔
55
{
56
    m_tracks.clear();
8✔
57
}
8✔
58

59
QIcon Show::getIcon() const
×
60
{
61
    return QIcon(":/show.png");
×
62
}
63

64
quint32 Show::totalDuration()
2✔
65
{
66
    quint32 totalDuration = 0;
2✔
67

68
    foreach (Track *track, tracks())
8✔
69
    {
70
        foreach (ShowFunction *sf, track->showFunctions())
8✔
71
        {
72
            if (sf->startTime() + sf->duration(doc()) > totalDuration)
2✔
73
                totalDuration = sf->startTime() + sf->duration(doc());
2✔
74
        }
75
    }
76

77
    return totalDuration;
2✔
78
}
79

80
/*****************************************************************************
81
 * Copying
82
 *****************************************************************************/
83

84
Function* Show::createCopy(Doc* doc, bool addToDoc)
×
85
{
86
    Q_ASSERT(doc != NULL);
×
87

88
    Function* copy = new Show(doc);
×
89
    if (copy->copyFrom(this) == false)
×
90
    {
91
        delete copy;
×
92
        copy = NULL;
×
93
    }
94
    if (addToDoc == true && doc->addFunction(copy) == false)
×
95
    {
96
        delete copy;
×
97
        copy = NULL;
×
98
    }
99

100
    return copy;
×
101
}
102

103
bool Show::copyFrom(const Function* function)
1✔
104
{
105
    const Show* show = qobject_cast<const Show*> (function);
1✔
106
    if (show == NULL)
1✔
107
        return false;
×
108

109
    m_timeDivisionType = show->m_timeDivisionType;
1✔
110
    m_timeDivisionBPM = show->m_timeDivisionBPM;
1✔
111
    m_latestTrackId = show->m_latestTrackId;
1✔
112

113
    // create a copy of each track
114
    foreach (Track *track, show->tracks())
4✔
115
    {
116
        quint32 sceneID = track->getSceneID();
1✔
117
        Track* newTrack = new Track(sceneID, this);
1✔
118
        newTrack->setName(track->name());
1✔
119
        addTrack(newTrack);
1✔
120

121
        // create a copy of each sequence/audio in a track
122
        foreach (ShowFunction *sfunc, track->showFunctions())
4✔
123
        {
124
            Function* function = doc()->function(sfunc->functionID());
1✔
125
            if (function == NULL)
1✔
126
                continue;
×
127

128
            /* Attempt to create a copy of the function to Doc */
129
            Function* copy = function->createCopy(doc());
1✔
130
            if (copy != NULL)
1✔
131
            {
132
                copy->setName(tr("Copy of %1").arg(function->name()));
1✔
133
                ShowFunction *showFunc = newTrack->createShowFunction(copy->id());
1✔
134
                showFunc->setStartTime(sfunc->startTime());
1✔
135
                showFunc->setDuration(sfunc->duration());
1✔
136
                showFunc->setColor(sfunc->color());
1✔
137
                showFunc->setLocked(sfunc->isLocked());
1✔
138
            }
139
        }
140
    }
141

142
    return Function::copyFrom(function);
1✔
143
}
144

145
/*********************************************************************
146
 * Time division
147
 *********************************************************************/
148

149
void Show::setTimeDivision(Show::TimeDivision type, int BPM)
4✔
150
{
151
    qDebug() << "[setTimeDivision] type:" << type << ", BPM:" << BPM;
4✔
152
    m_timeDivisionType = type;
4✔
153
    m_timeDivisionBPM = BPM;
4✔
154
}
4✔
155

156
Show::TimeDivision Show::timeDivisionType()
4✔
157
{
158
    return m_timeDivisionType;
4✔
159
}
160

161
int Show::beatsDivision()
4✔
162
{
163
    switch(m_timeDivisionType)
4✔
164
    {
165
        case BPM_2_4: return 2;
1✔
166
        case BPM_3_4: return 3;
1✔
167
        case BPM_4_4: return 4;
1✔
168
        default: return 0;
1✔
169
    }
170
}
171

172
void Show::setTimeDivisionType(TimeDivision type)
3✔
173
{
174
    m_timeDivisionType = type;
3✔
175
}
3✔
176

177
int Show::timeDivisionBPM()
4✔
178
{
179
    return m_timeDivisionBPM;
4✔
180
}
181

182
void Show::setTimeDivisionBPM(int BPM)
×
183
{
184
    m_timeDivisionBPM = BPM;
×
185
}
×
186

187
QString Show::tempoToString(Show::TimeDivision type)
5✔
188
{
189
    switch(type)
5✔
190
    {
191
        case Time: return QString("Time"); break;
1✔
192
        case BPM_4_4: return QString("BPM_4_4"); break;
1✔
193
        case BPM_3_4: return QString("BPM_3_4"); break;
2✔
194
        case BPM_2_4: return QString("BPM_2_4"); break;
1✔
195
        case Invalid:
×
196
        default:
197
            return QString("Invalid"); break;
×
198
    }
199
    return QString();
200
}
201

202
Show::TimeDivision Show::stringToTempo(QString tempo)
5✔
203
{
204
    if (tempo == "Time")
5✔
205
        return Time;
1✔
206
    else if (tempo == "BPM_4_4")
4✔
207
        return BPM_4_4;
1✔
208
    else if (tempo == "BPM_3_4")
3✔
209
        return BPM_3_4;
1✔
210
    else if (tempo == "BPM_2_4")
2✔
211
        return BPM_2_4;
2✔
212
    else
213
        return Invalid;
×
214
}
215

216
/*****************************************************************************
217
 * Tracks
218
 *****************************************************************************/
219

220
bool Show::addTrack(Track *track, quint32 id)
9✔
221
{
222
    Q_ASSERT(track != NULL);
9✔
223

224
    // No ID given, this method can assign one
225
    if (id == Track::invalidId())
9✔
226
        id = createTrackId();
7✔
227

228
     track->setId(id);
9✔
229
     track->setShowId(this->id());
9✔
230
     m_tracks[id] = track;
9✔
231

232
     registerAttribute(track->name());
9✔
233

234
     return true;
9✔
235
}
236

237
bool Show::removeTrack(quint32 id)
3✔
238
{
239
    if (m_tracks.contains(id) == true)
3✔
240
    {
241
        Track* trk = m_tracks.take(id);
2✔
242
        Q_ASSERT(trk != NULL);
2✔
243

244
        unregisterAttribute(trk->name());
2✔
245

246
        //emit trackRemoved(id);
247
        delete trk;
2✔
248

249
        return true;
2✔
250
    }
251
    else
252
    {
253
        qWarning() << Q_FUNC_INFO << "No track found with id" << id;
1✔
254
        return false;
1✔
255
    }
256
}
257

258
Track* Show::track(quint32 id) const
5✔
259
{
260
    if (m_tracks.contains(id) == true)
5✔
261
        return m_tracks[id];
3✔
262
    else
263
        return NULL;
2✔
264
}
265

266
Track* Show::getTrackFromSceneID(quint32 id)
2✔
267
{
268
    foreach (Track *track, m_tracks)
4✔
269
    {
270
        if (track->getSceneID() == id)
2✔
271
            return track;
1✔
272
    }
273
    return NULL;
1✔
274
}
275

276
Track *Show::getTrackFromShowFunctionID(quint32 id)
×
277
{
278
    foreach (Track *track, m_tracks)
×
279
        if (track->showFunction(id) != NULL)
×
280
            return track;
×
281

282
    return NULL;
×
283
}
284

285
int Show::getTracksCount()
5✔
286
{
287
    return m_tracks.size();
5✔
288
}
289

290
void Show::moveTrack(Track *track, int direction)
3✔
291
{
292
    if (track == NULL)
3✔
293
        return;
×
294

295
    qint32 trkID = track->id();
3✔
296
    if (trkID == 0 && direction == -1)
3✔
297
        return;
1✔
298
    qint32 maxID = -1;
2✔
299
    Track *swapTrack = NULL;
2✔
300
    qint32 swapID = -1;
2✔
301
    if (direction > 0) swapID = INT_MAX;
2✔
302

303
    foreach (quint32 id, m_tracks.keys())
12✔
304
    {
305
        qint32 signedID = (qint32)id;
4✔
306
        if (signedID > maxID) maxID = signedID;
4✔
307
        if (direction == -1 && signedID > swapID && signedID < trkID)
4✔
308
            swapID = signedID;
2✔
309
        else if (direction == 1 && signedID < swapID && signedID > trkID)
2✔
310
            swapID = signedID;
×
311
    }
312

313
    qDebug() << Q_FUNC_INFO << "Direction:" << direction << ", trackID:" << trkID << ", swapID:" << swapID;
2✔
314
    if (swapID == trkID || (direction > 0 && trkID == maxID))
2✔
315
        return;
×
316

317
    swapTrack = m_tracks[swapID];
2✔
318
    m_tracks[swapID] = track;
2✔
319
    m_tracks[trkID] = swapTrack;
2✔
320
    track->setId(swapID);
2✔
321
    swapTrack->setId(trkID);
2✔
322
}
323

324
QList <Track*> Show::tracks() const
15✔
325
{
326
    return m_tracks.values();
15✔
327
}
328

329
quint32 Show::createTrackId()
9✔
330
{
331
    while (m_tracks.contains(m_latestTrackId) == true ||
16✔
332
           m_latestTrackId == Track::invalidId())
7✔
333
    {
334
        m_latestTrackId++;
2✔
335
    }
336

337
    return m_latestTrackId;
7✔
338
}
339

340
/*********************************************************************
341
 * Show Functions
342
 *********************************************************************/
343

344
quint32 Show::getLatestShowFunctionId()
3✔
345
{
346
    return m_latestTrackId++;
3✔
347
}
348

349
ShowFunction *Show::showFunction(quint32 id)
2✔
350
{
351
    foreach (Track *track, m_tracks)
4✔
352
    {
353
        ShowFunction *sf = track->showFunction(id);
2✔
354
        if (sf != NULL)
2✔
355
            return sf;
1✔
356
    }
357

358
    return NULL;
1✔
359
}
360

361
/*****************************************************************************
362
 * Load & Save
363
 *****************************************************************************/
364

365
bool Show::saveXML(QXmlStreamWriter *doc)
1✔
366
{
367
    Q_ASSERT(doc != NULL);
1✔
368

369
    /* Function tag */
370
    doc->writeStartElement(KXMLQLCFunction);
1✔
371

372
    /* Common attributes */
373
    saveXMLCommon(doc);
1✔
374

375
    doc->writeStartElement(KXMLQLCShowTimeDivision);
1✔
376
    doc->writeAttribute(KXMLQLCShowTimeType, tempoToString(m_timeDivisionType));
1✔
377
    doc->writeAttribute(KXMLQLCShowTimeBPM, QString::number(m_timeDivisionBPM));
1✔
378
    doc->writeEndElement();
1✔
379

380
    foreach (Track *track, m_tracks)
5✔
381
        track->saveXML(doc);
2✔
382

383
    /* End the <Function> tag */
384
    doc->writeEndElement();
1✔
385

386
    return true;
1✔
387
}
388

389
bool Show::loadXML(QXmlStreamReader &root)
1✔
390
{
391
    if (root.name() != KXMLQLCFunction)
1✔
392
    {
393
        qWarning() << Q_FUNC_INFO << "Function node not found";
×
394
        return false;
×
395
    }
396

397
    if (root.attributes().value(KXMLQLCFunctionType).toString() != typeToString(Function::ShowType))
1✔
398
    {
399
        qWarning() << Q_FUNC_INFO << root.attributes().value(KXMLQLCFunctionType).toString()
×
400
                   << "is not a show";
×
401
        return false;
×
402
    }
403

404
    while (root.readNextStartElement())
4✔
405
    {
406
        if (root.name() == KXMLQLCShowTimeDivision)
3✔
407
        {
408
            QString type = root.attributes().value(KXMLQLCShowTimeType).toString();
3✔
409
            int bpm = root.attributes().value(KXMLQLCShowTimeBPM).toString().toInt();
1✔
410
            setTimeDivision(stringToTempo(type), bpm);
1✔
411
            root.skipCurrentElement();
1✔
412
        }
413
        else if (root.name() == KXMLQLCTrack)
2✔
414
        {
415
            Track *trk = new Track(Function::invalidId(), this);
2✔
416
            if (trk->loadXML(root) == true)
2✔
417
                addTrack(trk, trk->id());
2✔
418
        }
419
        else
420
        {
421
            qWarning() << Q_FUNC_INFO << "Unknown Show tag:" << root.name();
×
422
            root.skipCurrentElement();
×
423
        }
424
    }
425

426
    return true;
1✔
427
}
428

429
void Show::postLoad()
×
430
{
431
    foreach (Track* track, m_tracks)
×
432
    {
433
        if (track->postLoad(doc()))
×
434
            doc()->setModified();
×
435
    }
436
}
×
437

438
bool Show::contains(quint32 functionId)
3✔
439
{
440
    Doc *doc = this->doc();
3✔
441
    Q_ASSERT(doc != NULL);
3✔
442

443
    if (functionId == id())
3✔
444
        return true;
1✔
445

446
    foreach (Track* track, m_tracks)
4✔
447
    {
448
        if (track->contains(doc, functionId))
2✔
449
            return true;
1✔
450
    }
451

452
    return false;
1✔
453
}
454

455
QList<quint32> Show::components()
1✔
456
{
457
    QList<quint32> ids;
1✔
458

459
    foreach (Track* track, m_tracks)
3✔
460
        ids.append(track->components());
1✔
461

462
    return ids;
1✔
463
}
464

465
/*****************************************************************************
466
 * Running
467
 *****************************************************************************/
468

469
void Show::preRun(MasterTimer* timer)
×
470
{
471
    Function::preRun(timer);
×
472
    m_runningChildren.clear();
×
473
    if (m_runner != NULL)
×
474
    {
475
        m_runner->stop();
×
476
        delete m_runner;
×
477
    }
478

479
    m_runner = new ShowRunner(doc(), this->id(), elapsed());
×
480
    int i = 0;
×
NEW
481
    foreach (Track *track, m_tracks.values())
×
482
        m_runner->adjustIntensity(getAttributeValue(i++), track);
×
483

484
    connect(m_runner, SIGNAL(timeChanged(quint32)), this, SIGNAL(timeChanged(quint32)));
×
485
    connect(m_runner, SIGNAL(showFinished()), this, SIGNAL(showFinished()));
×
486
    m_runner->start();
×
487
}
×
488

489
void Show::setPause(bool enable)
×
490
{
491
    if (m_runner != NULL)
×
492
        m_runner->setPause(enable);
×
493
    Function::setPause(enable);
×
494
}
×
495

496
void Show::write(MasterTimer* timer, QList<Universe *> universes)
×
497
{
498
    Q_UNUSED(universes);
499

500
    if (isPaused())
×
501
        return;
×
502

503
    m_runner->write(timer);
×
504
}
505

506
void Show::postRun(MasterTimer* timer, QList<Universe *> universes)
×
507
{
508
    if (m_runner != NULL)
×
509
    {
510
        m_runner->stop();
×
511
        delete m_runner;
×
512
        m_runner = NULL;
×
513
    }
514
    Function::postRun(timer, universes);
×
515
}
×
516

517
void Show::slotChildStopped(quint32 fid)
×
518
{
519
    Q_UNUSED(fid);
520
}
×
521

522
/*****************************************************************************
523
 * Attributes
524
 *****************************************************************************/
525

526
int Show::adjustAttribute(qreal fraction, int attributeId)
×
527
{
528
    int attrIndex = Function::adjustAttribute(fraction, attributeId);
×
529

530
    if (m_runner != NULL)
×
531
    {
532
        QList<Track*> trkList = m_tracks.values();
×
533
        if (trkList.isEmpty() == false &&
×
534
            attrIndex >= 0 && attrIndex < trkList.count())
×
535
        {
536
            Track *track = trkList.at(attrIndex);
×
537
            if (track != NULL)
×
538
                m_runner->adjustIntensity(getAttributeValue(attrIndex), track);
×
539
        }
540
    }
541

542
    return attrIndex;
×
543
}
544

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