• 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

88.32
/engine/src/qlcfixturemode.cpp
1
/*
2
  Q Light Controller Plus
3
  qlcfixturemode.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 <iostream>
23
#include <QString>
24
#include <QDebug>
25
#include <QVector>
26

27
#include "qlcfixturemode.h"
28
#include "qlcfixturehead.h"
29
#include "qlcfixturedef.h"
30
#include "qlcchannel.h"
31
#include "qlcphysical.h"
32

33
QLCFixtureMode::QLCFixtureMode(QLCFixtureDef *fixtureDef)
404✔
34
    : m_fixtureDef(fixtureDef)
404✔
35
    , m_masterIntensityChannel(QLCChannel::invalid())
404✔
36
    , m_useGlobalPhysical(true)
404✔
37
{
38
    Q_ASSERT(fixtureDef != NULL);
39
}
404✔
40

41
QLCFixtureMode::QLCFixtureMode(QLCFixtureDef *fixtureDef, const QLCFixtureMode *mode)
3✔
42
    : m_fixtureDef(fixtureDef)
3✔
43
    , m_masterIntensityChannel(QLCChannel::invalid())
3✔
44
    , m_useGlobalPhysical(true)
3✔
45
{
46
    Q_ASSERT(fixtureDef != NULL);
47
    Q_ASSERT(mode != NULL);
48

49
    if (mode != NULL)
3✔
50
        *this = *mode;
3✔
51
}
3✔
52

53
QLCFixtureMode::~QLCFixtureMode()
342✔
54
{
55
}
342✔
56

57
QLCFixtureMode& QLCFixtureMode::operator=(const QLCFixtureMode& mode)
3✔
58
{
59
    if (this != &mode)
3✔
60
    {
61
        m_name = mode.m_name;
3✔
62
        m_useGlobalPhysical = mode.m_useGlobalPhysical;
3✔
63
        m_physical = mode.m_physical;
3✔
64
        m_heads = mode.m_heads;
3✔
65
        m_masterIntensityChannel = QLCChannel::invalid();
3✔
66

67
        m_actsOnMap.clear();
3✔
68
        QMapIterator<quint32, quint32> ait(mode.m_actsOnMap);
3✔
69
        while (ait.hasNext())
3✔
70
        {
71
            ait.next();
×
72
            m_actsOnMap.insert(ait.key(), ait.value());
×
73
        }
74

75
        /* Clear the existing list of channels */
76
        m_channels.clear();
3✔
77

78
        Q_ASSERT(m_fixtureDef != NULL);
79

80
        quint32 i = 0;
81
        QVectorIterator <QLCChannel*> it(mode.m_channels);
3✔
82
        while (it.hasNext() == true)
12✔
83
        {
84
            /* Since m_fixtureDef might not be the same as
85
               mode.m_fixtureDef, we need to search for a
86
               channel with the same name from m_fixtureDef and
87
               not from mode.m_fixtureDef. If the channel in the
88
               other mode is deleted, the one in this copied mode
89
               will be invalid and we end up in a crash. */
90
            QLCChannel* ch = it.next();
9✔
91
            QLCChannel* actual = m_fixtureDef->channel(ch->name());
9✔
92
            if (actual != NULL)
9✔
93
                insertChannel(actual, i++);
7✔
94
            else
95
                qWarning() << Q_FUNC_INFO << "Unable to find channel"
4✔
96
                           << ch->name() << "for mode"
4✔
97
                           << m_name << "from its fixture definition";
2✔
98
        }
99
    }
100

101
    return *this;
3✔
102
}
103

104
/****************************************************************************
105
 * Name
106
 ****************************************************************************/
107

108
void QLCFixtureMode::setName(const QString &name)
381✔
109
{
110
    m_name = name;
381✔
111
}
381✔
112

113
QString QLCFixtureMode::name() const
109✔
114
{
115
    return m_name;
109✔
116
}
117

118
/*****************************************************************************
119
 * Fixture definition
120
 *****************************************************************************/
121

122
QLCFixtureDef* QLCFixtureMode::fixtureDef() const
56✔
123
{
124
    return m_fixtureDef;
56✔
125
}
126

127
/****************************************************************************
128
 * Channels
129
 ****************************************************************************/
130

131
bool QLCFixtureMode::insertChannel(QLCChannel* channel, quint32 index)
2,503✔
132
{
133
    if (channel == NULL)
2,503✔
134
    {
135
        qWarning() << Q_FUNC_INFO << "Will not add a NULL channel to mode"
2✔
136
                   << m_name;
1✔
137
        return false;
1✔
138
    }
139

140
    Q_ASSERT(m_fixtureDef != NULL);
141

142
    if (m_fixtureDef->channels().contains(channel) == true)
2,502✔
143
    {
144
        if (m_channels.contains(channel) == false)
2,501✔
145
        {
146
            if (index >= quint32(m_channels.size()))
2,500✔
147
                m_channels.append(channel);
2,498✔
148
            else
149
                m_channels.insert(index, channel);
2✔
150
            return true;
2,500✔
151
        }
152
        else
153
        {
154
            qWarning() << Q_FUNC_INFO << "Channel" << channel->name()
2✔
155
                       << "is already a member of mode" << m_name;
1✔
156
            return false;
1✔
157
        }
158
    }
159
    else
160
    {
161
        qWarning() << Q_FUNC_INFO << "Will not add channel" << channel->name()
2✔
162
                   << "to mode" << m_name
1✔
163
                   << "because the channel does not belong to mode's"
1✔
164
                   << "parent fixture definition.";
1✔
165
        return false;
1✔
166
    }
167
}
168

169
bool QLCFixtureMode::removeChannel(const QLCChannel* channel)
7✔
170
{
171
    QMutableVectorIterator <QLCChannel*> it(m_channels);
7✔
172
    while (it.hasNext() == true)
17✔
173
    {
174
        if (it.next() == channel)
15✔
175
        {
176
            /* Don't delete the channel since QLCFixtureModes
177
               don't own them. QLCFixtureDefs do. */
178
            it.remove();
5✔
179
            return true;
5✔
180
        }
181
    }
182

183
    return false;
184
}
185

186
bool QLCFixtureMode::replaceChannel(QLCChannel *currChannel, QLCChannel *newChannel)
×
187
{
188
    if (currChannel == NULL || newChannel == NULL)
×
189
        return false;
190

191
    int chIndex = m_channels.indexOf(currChannel);
×
192
    if (chIndex == -1)
×
193
        return false;
194

195
    m_channels.replace(chIndex, newChannel);
×
196

197
    return true;
×
198
}
199

200
void QLCFixtureMode::removeAllChannels()
×
201
{
202
    m_channels.clear();
×
203
}
×
204

205
QLCChannel* QLCFixtureMode::channel(const QString& name) const
6✔
206
{
207
    QVectorIterator <QLCChannel*> it(m_channels);
6✔
208
    while (it.hasNext() == true)
20✔
209
    {
210
        QLCChannel* ch = it.next();
18✔
211
        Q_ASSERT(ch != NULL);
212
        if (ch->name() == name)
18✔
213
            return ch;
4✔
214
    }
215

216
    return NULL;
217
}
218

219
QLCChannel* QLCFixtureMode::channel(quint32 ch) const
801,535✔
220
{
221
    return m_channels.value(ch, NULL);
801,535✔
222
}
223

224
QVector <QLCChannel*> QLCFixtureMode::channels() const
14,971✔
225
{
226
    return m_channels;
14,971✔
227
}
228

229
quint32 QLCFixtureMode::channelNumber(QLCChannel *channel) const
6✔
230
{
231
    if (channel == NULL)
6✔
232
        return QLCChannel::invalid();
1✔
233

234
    int idx = m_channels.indexOf(channel);
5✔
235
    return idx == -1 ? QLCChannel::invalid() : idx;
5✔
236
}
237

238
quint32 QLCFixtureMode::channelNumber(QLCChannel::Group group, QLCChannel::ControlByte cByte) const
3,904✔
239
{
240
    for (int i = 0; i < m_channels.size(); i++)
51,236✔
241
    {
242
        if (m_channels.at(i)->group() == group &&
47,691✔
243
            m_channels.at(i)->controlByte() == cByte)
308✔
244
            return i;
51✔
245
    }
246

247
    return QLCChannel::invalid();
3,853✔
248
}
249

250
quint32 QLCFixtureMode::masterIntensityChannel() const
40✔
251
{
252
    return m_masterIntensityChannel;
40✔
253
}
254

255
quint32 QLCFixtureMode::primaryChannel(quint32 chIndex)
795,214✔
256
{
257
    return m_secondaryMap.value(chIndex, QLCChannel::invalid());
795,214✔
258
}
259

260
quint32 QLCFixtureMode::channelActsOn(quint32 chIndex)
×
261
{
262
    return m_actsOnMap.value(chIndex, QLCChannel::invalid());
×
263
}
264

265
void QLCFixtureMode::setChannelActsOn(quint32 chIndex, quint32 actsOnIndex)
×
266
{
267
    if (m_actsOnMap.contains(chIndex))
×
268
        m_actsOnMap.remove(chIndex);
×
269

270
    if (actsOnIndex != QLCChannel::invalid())
×
271
        m_actsOnMap[chIndex] = actsOnIndex;
×
272
}
×
273

274
/*****************************************************************************
275
 * Heads
276
 *****************************************************************************/
277

278
void QLCFixtureMode::insertHead(int index, const QLCFixtureHead& head)
1,013✔
279
{
280
    if (index < 0 || index >= m_heads.size())
1,013✔
281
        m_heads.append(head);
1,012✔
282
    else
283
        m_heads.insert(index, head);
1✔
284
}
1,013✔
285

286
void QLCFixtureMode::removeHead(int index)
4✔
287
{
288
    if (index >= 0 && index < m_heads.size())
4✔
289
        m_heads.remove(index);
3✔
290
}
4✔
291

292
void QLCFixtureMode::replaceHead(int index, const QLCFixtureHead& head)
2✔
293
{
294
    if (index >= 0 && index < m_heads.size())
2✔
295
        m_heads[index] = head;
1✔
296
}
2✔
297

298
QVector <QLCFixtureHead> const& QLCFixtureMode::heads() const
2,008✔
299
{
300
    return m_heads;
2,008✔
301
}
302

303
int QLCFixtureMode::headForChannel(quint32 chnum) const
867✔
304
{
305
    for (int i = 0; i < m_heads.size(); i++)
3,533✔
306
    {
307
        if (m_heads[i].channels().contains(chnum) == true)
3,443✔
308
            return i;
777✔
309
    }
310

311
    return -1;
312
}
313

314
void QLCFixtureMode::cacheHeads()
590✔
315
{
316
    QLCChannel *lastChannel = NULL;
317

318
    for (int i = 0; i < m_heads.size(); i++)
1,954✔
319
    {
320
        QLCFixtureHead& head(m_heads[i]);
1,364✔
321
        head.cacheChannels(this);
1,364✔
322
    }
323

324
    for (quint32 i = 0; i < quint32(m_channels.size()); i++)
5,331✔
325
    {
326
        QLCChannel *channel = m_channels.at(i);
4,741✔
327

328
        /** Auto-detect master intensity channel */
329
        if (m_masterIntensityChannel == QLCChannel::invalid() &&
6,966✔
330
            channel->group() == QLCChannel::Intensity &&
3,945✔
331
            channel->controlByte() == QLCChannel::MSB &&
3,316✔
332
            channel->colour() == QLCChannel::NoColour &&
7,204✔
333
            headForChannel(i) == -1)
867✔
334
        {
335
            m_masterIntensityChannel = i;
90✔
336
        }
337

338
        /** Map secondary channels */
339
        if (lastChannel != NULL &&
4,151✔
340
            channel->group() == lastChannel->group() &&
6,568✔
341
            lastChannel->controlByte() == QLCChannel::MSB &&
9,450✔
342
            channel->controlByte() == QLCChannel::LSB)
2,292✔
343
        {
344
            //qDebug() << "Channel" << lastChannel->name() << "is primary and" << channel->name() << "is secondary";
345
            m_secondaryMap[i] = i - 1;
264✔
346
        }
347

348
        lastChannel = channel;
349
    }
350
}
590✔
351

352
/****************************************************************************
353
 * Physical
354
 ****************************************************************************/
355

356
void QLCFixtureMode::setPhysical(const QLCPhysical& physical)
235✔
357
{
358
    m_useGlobalPhysical = false;
235✔
359
    m_physical = physical;
235✔
360
}
235✔
361

362
void QLCFixtureMode::resetPhysical()
×
363
{
364
    m_useGlobalPhysical = true;
×
365
}
×
366

367
bool QLCFixtureMode::useGlobalPhysical()
2✔
368
{
369
    return m_useGlobalPhysical;
2✔
370
}
371

372
QLCPhysical QLCFixtureMode::physical() const
66✔
373
{
374
    if (m_useGlobalPhysical)
66✔
375
        return fixtureDef()->physical();
55✔
376

377
    return m_physical;
11✔
378
}
379

380
/****************************************************************************
381
 * Load & Save
382
 ****************************************************************************/
383

384
bool QLCFixtureMode::loadXML(QXmlStreamReader &doc)
141✔
385
{
386
    if (doc.name() != KXMLQLCFixtureMode)
282✔
387
    {
388
        qWarning() << Q_FUNC_INFO << "Mode tag not found";
1✔
389
        return false;
1✔
390
    }
391

392
    /* Mode name */
393
    QString str = doc.attributes().value(KXMLQLCFixtureModeName).toString();
140✔
394
    if (str.isEmpty() == true)
140✔
395
    {
396
        qWarning() << Q_FUNC_INFO << "Mode has no name";
1✔
397
        return false;
1✔
398
    }
399
    else
400
    {
401
        setName(str);
139✔
402
    }
403

404
    /* Subtags */
405
    while (doc.readNextStartElement())
1,780✔
406
    {
407
        if (doc.name() == KXMLQLCFixtureModeChannel)
3,282✔
408
        {
409
            /* Channel */
410
            Q_ASSERT(m_fixtureDef != NULL);
411
            str = doc.attributes().value(KXMLQLCFixtureModeChannelNumber).toString();
1,455✔
412

413
            quint32 actsOnChannelIndex = QLCChannel::invalid();
1,455✔
414

415
            if (doc.attributes().hasAttribute(KXMLQLCFixtureModeChannelActsOn))
1,455✔
416
                actsOnChannelIndex = doc.attributes().value(KXMLQLCFixtureModeChannelActsOn).toUInt();
×
417

418
            QLCChannel *currentChannel = m_fixtureDef->channel(doc.readElementText());
1,455✔
419

420
            if (actsOnChannelIndex != QLCChannel::invalid())
1,455✔
421
                m_actsOnMap[str.toInt()] = actsOnChannelIndex;
×
422

423
            insertChannel(currentChannel, str.toInt());
1,455✔
424
        }
425
        else if (doc.name() == KXMLQLCFixtureHead)
372✔
426
        {
427
            /* Head */
428
            QLCFixtureHead head;
184✔
429
            if (head.loadXML(doc) == true)
184✔
430
                insertHead(-1, head);
184✔
431
        }
184✔
432
        else if (doc.name() == KXMLQLCPhysical)
4✔
433
        {
434
            /* Physical */
435
            QLCPhysical physical;
1✔
436
            physical.loadXML(doc);
1✔
437
            setPhysical(physical);
1✔
438
        }
1✔
439
        else
440
        {
441
            qWarning() << Q_FUNC_INFO << "Unknown Fixture Mode tag:" << doc.name();
1✔
442
            doc.skipCurrentElement();
1✔
443
        }
444
    }
445

446
    // Cache all head channels
447
    cacheHeads();
139✔
448

449
    return true;
450
}
140✔
451

452
bool QLCFixtureMode::saveXML(QXmlStreamWriter *doc)
3✔
453
{
454
    int i = 0;
455

456
    Q_ASSERT(doc != NULL);
457

458
    /* Mode entry */
459
    doc->writeStartElement(KXMLQLCFixtureMode);
3✔
460
    doc->writeAttribute(KXMLQLCFixtureModeName, m_name);
3✔
461

462
    if (m_useGlobalPhysical == false)
3✔
463
        m_physical.saveXML(doc);
1✔
464

465
    /* Channels */
466
    QVectorIterator <QLCChannel*> it(m_channels);
3✔
467
    while (it.hasNext() == true)
8✔
468
    {
469
        QLCChannel *channel = it.next();
5✔
470
        quint32 actsOnIndex = m_actsOnMap.value(i, QLCChannel::invalid());
5✔
471

472
        doc->writeStartElement(KXMLQLCFixtureModeChannel);
5✔
473
        doc->writeAttribute(KXMLQLCFixtureModeChannelNumber, QString::number(i++));
5✔
474
        if (actsOnIndex != QLCChannel::invalid())
5✔
475
            doc->writeAttribute(KXMLQLCFixtureModeChannelActsOn, QString::number(actsOnIndex));
×
476

477
        doc->writeCharacters(channel->name());
5✔
478
        doc->writeEndElement();
5✔
479
    }
480

481
    /* Heads */
482
    QVectorIterator <QLCFixtureHead> hit(m_heads);
3✔
483
    while (hit.hasNext() == true)
6✔
484
        hit.next().saveXML(doc);
3✔
485

486
    doc->writeEndElement();
3✔
487

488
    return true;
3✔
489
}
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