• 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

95.71
/engine/src/fixturegroup.cpp
1
/*
2
  Q Light Controller Plus
3
  fixturegroup.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 <QDebug>
24

25
#include "fixturegroup.h"
26
#include "qlcpoint.h"
27
#include "fixture.h"
28
#include "doc.h"
29

30
#define KXMLQLCFixtureGroupHead QString("Head")
31
#define KXMLQLCFixtureGroupSize QString("Size")
32
#define KXMLQLCFixtureGroupName QString("Name")
33

34
/****************************************************************************
35
 * Initialization
36
 ****************************************************************************/
37

38
FixtureGroup::FixtureGroup(Doc* parent)
30✔
39
    : QObject(parent)
40
    , m_id(FixtureGroup::invalidId())
30✔
41
{
42
    Q_ASSERT(parent != NULL);
43

44
    // Listen to fixture removals
45
    connect(parent, SIGNAL(fixtureRemoved(quint32)),
30✔
46
            this, SLOT(slotFixtureRemoved(quint32)));
47
}
30✔
48

49
FixtureGroup::~FixtureGroup()
44✔
50
{
51
}
44✔
52

53
void FixtureGroup::copyFrom(const FixtureGroup* grp)
1✔
54
{
55
    // Don't copy ID
56
    m_name = grp->name();
1✔
57
    m_size = grp->size();
1✔
58
    m_heads = grp->headsMap();
2✔
59
}
1✔
60

61
Doc* FixtureGroup::doc() const
188✔
62
{
63
    return qobject_cast<Doc*> (parent());
188✔
64
}
65

66
/****************************************************************************
67
 * ID
68
 ****************************************************************************/
69

70
void FixtureGroup::setId(quint32 id)
18✔
71
{
72
    m_id = id;
18✔
73
}
18✔
74

75
quint32 FixtureGroup::id() const
269✔
76
{
77
    return m_id;
269✔
78
}
79

80
quint32 FixtureGroup::invalidId()
89✔
81
{
82
    return UINT_MAX;
89✔
83
}
84

85
/****************************************************************************
86
 * Name
87
 ****************************************************************************/
88

89
void FixtureGroup::setName(const QString& name)
8✔
90
{
91
    if (m_name == name)
8✔
92
        return;
93

94
    m_name = name;
8✔
95
    emit nameChanged();
8✔
96
    emit changed(this->id());
8✔
97
}
98

99
QString FixtureGroup::name() const
11✔
100
{
101
    return m_name;
11✔
102
}
103

104
/****************************************************************************
105
 * Fixtures
106
 ****************************************************************************/
107

108
bool FixtureGroup::assignFixture(quint32 id, const QLCPoint& pt)
188✔
109
{
110
    Fixture* fxi = doc()->fixture(id);
188✔
111
    Q_ASSERT(fxi != NULL);
112
    QLCPoint tmp = pt;
188✔
113
    int headAddedcount = 0;
114

115
    for (int i = 0; i < fxi->heads(); i++)
627✔
116
    {
117
        if (pt.isNull())
118
        {
119
            if (assignHead(pt, GroupHead(fxi->id(), i)) == true)
432✔
120
                headAddedcount++;
192✔
121
        }
122
        else
123
        {
124
            if (assignHead(tmp, GroupHead(fxi->id(), i)) == true)
7✔
125
                headAddedcount++;
5✔
126

127
            tmp.setX(tmp.x() + 1);
7✔
128
            if (tmp.x() >= size().width())
7✔
129
            {
130
                tmp.setX(0);
131
                tmp.setY(tmp.y() + 1);
4✔
132
            }
133
        }
134
    }
135

136
    return headAddedcount ? true : false;
188✔
137
}
138

139
bool FixtureGroup::assignHead(const QLCPoint& pt, const GroupHead& head)
440✔
140
{
141
    if (m_heads.values().contains(head) == true)
880✔
142
        return false;
143

144
    if (size().isValid() == false)
396✔
145
        setSize(QSize(1, 1));
1✔
146

147
    if (pt.isNull() == false)
148
    {
149
        m_heads[pt] = head;
5✔
150
    }
151
    else
152
    {
153
        int y = 0;
154
        int x = 0;
155
        int xmax = size().width();
193✔
156
        int ymax = size().height();
193✔
157

158
        while (1)
159
        {
160
            for (; y < ymax; y++)
1,137✔
161
            {
162
                for (x = 0; x < xmax; x++)
2,610✔
163
                {
164
                    QLCPoint tmp(x, y);
2,177✔
165
                    if (m_heads.contains(tmp) == false)
2,177✔
166
                    {
167
                        m_heads[tmp] = head;
193✔
168
                        emit changed(this->id());
193✔
169
                        return true;
193✔
170
                    }
171
                }
172
            }
173

174
            ymax++;
78✔
175
        }
78✔
176
    }
177

178
    emit changed(this->id());
5✔
179
    return true;
5✔
180
}
181

182
void FixtureGroup::resignFixture(quint32 id)
4✔
183
{
184
    foreach (QLCPoint pt, m_heads.keys())
70✔
185
    {
186
        if (m_heads[pt].fxi == id)
62✔
187
            m_heads.remove(pt);
2✔
188
    }
189

190
    emit changed(this->id());
4✔
191
}
4✔
192

193
bool FixtureGroup::resignHead(const QLCPoint& pt)
19✔
194
{
195
    if (m_heads.contains(pt) == true)
19✔
196
    {
197
        m_heads.remove(pt);
17✔
198
        emit changed(this->id());
17✔
199
        return true;
17✔
200
    }
201
    else
202
    {
203
        return false;
204
    }
205
}
206

207
void FixtureGroup::swap(const QLCPoint& a, const QLCPoint& b)
3✔
208
{
209
    GroupHead ah = m_heads.value(a);
3✔
210
    GroupHead bh = m_heads.value(b);
3✔
211

212
    if (ah.isValid() == true)
3✔
213
        m_heads[b] = ah;
2✔
214
    else
215
        m_heads.remove(b);
1✔
216

217
    if (bh.isValid() == true)
3✔
218
        m_heads[a] = bh;
2✔
219
    else
220
        m_heads.remove(a);
1✔
221

222
    emit changed(this->id());
3✔
223
}
3✔
224

225
void FixtureGroup::reset()
×
226
{
227
    m_heads.clear();
×
228
    emit changed(this->id());
×
229
}
×
230

231
GroupHead FixtureGroup::head(const QLCPoint& pt) const
96✔
232
{
233
    return m_heads.value(pt);
96✔
234
}
235

236
QList <GroupHead> FixtureGroup::headList() const
69✔
237
{
238
    return m_heads.values();
69✔
239
}
240

241
QMap<QLCPoint, GroupHead> FixtureGroup::headsMap() const
51✔
242
{
243
    return m_heads;
51✔
244
}
245

246
QList <quint32> FixtureGroup::fixtureList() const
35✔
247
{
248
    QList <quint32> list;
249
    foreach (GroupHead head, headList())
503✔
250
    {
251
        if (list.contains(head.fxi) == false)
433✔
252
            list << head.fxi;
253
    }
433✔
254
    return list;
35✔
255
}
×
256

257
void FixtureGroup::slotFixtureRemoved(quint32 id)
2✔
258
{
259
    // Remove the fixture from group records since it's no longer there
260
    resignFixture(id);
2✔
261
}
2✔
262

263
/****************************************************************************
264
 * Size
265
 ****************************************************************************/
266

267
void FixtureGroup::setSize(const QSize& sz)
13✔
268
{
269
    m_size = sz;
13✔
270
    emit changed(this->id());
13✔
271
}
13✔
272

273
QSize FixtureGroup::size() const
637✔
274
{
275
    return m_size;
637✔
276
}
277

278
/****************************************************************************
279
 * Load & Save
280
 ****************************************************************************/
281

282
bool FixtureGroup::loader(QXmlStreamReader &xmlDoc, Doc* doc)
5✔
283
{
284
    bool result = false;
285

286
    FixtureGroup* grp = new FixtureGroup(doc);
5✔
287
    Q_ASSERT(grp != NULL);
288

289
    if (grp->loadXML(xmlDoc) == true)
5✔
290
    {
291
        doc->addFixtureGroup(grp, grp->id());
4✔
292
        result = true;
293
    }
294
    else
295
    {
296
        qWarning() << Q_FUNC_INFO << "FixtureGroup" << grp->name() << "cannot be loaded.";
1✔
297
        delete grp;
1✔
298
        result = false;
299
    }
300

301
    return result;
5✔
302
}
303

304
bool FixtureGroup::loadXML(QXmlStreamReader &xmlDoc)
11✔
305
{
306
    if (xmlDoc.name() != KXMLQLCFixtureGroup)
22✔
307
    {
308
        qWarning() << Q_FUNC_INFO << "Fixture group node not found";
1✔
309
        return false;
1✔
310
    }
311

312
    bool ok = false;
10✔
313
    quint32 id = xmlDoc.attributes().value(KXMLQLCFixtureGroupID).toString().toUInt(&ok);
10✔
314
    if (ok == false)
10✔
315
    {
316
        qWarning() << "Invalid FixtureGroup ID:" << xmlDoc.attributes().value(KXMLQLCFixtureGroupID).toString();
1✔
317
        return false;
1✔
318
    }
319

320
    // Assign the ID to myself
321
    m_id = id;
9✔
322

323
    while (xmlDoc.readNextStartElement())
51✔
324
    {
325
        QXmlStreamAttributes attrs = xmlDoc.attributes();
42✔
326
        if (xmlDoc.name() == KXMLQLCFixtureGroupHead)
84✔
327
        {
328
            bool xok = false, yok = false, idok = false, headok = false;
37✔
329
            int x = attrs.value("X").toString().toInt(&xok);
37✔
330
            int y = attrs.value("Y").toString().toInt(&yok);
37✔
331
            quint32 id = attrs.value("Fixture").toString().toUInt(&idok);
37✔
332
            int head = xmlDoc.readElementText().toInt(&headok);
37✔
333

334
            // Don't use assignFixture() here because it assigns complete fixtures at once
335
            if (xok == true && yok == true && idok == true && headok == true)
37✔
336
                m_heads[QLCPoint(x, y)] = GroupHead(id, head);
33✔
337
        }
338
        else if (xmlDoc.name() == KXMLQLCFixtureGroupSize)
10✔
339
        {
340
            bool xok = false, yok = false;
1✔
341
            int x = attrs.value("X").toString().toInt(&xok);
1✔
342
            int y = attrs.value("Y").toString().toInt(&yok);
1✔
343

344
            if (xok == true && yok == true)
1✔
345
                m_size = QSize(x, y);
1✔
346
            xmlDoc.skipCurrentElement();
1✔
347
        }
348
        else if (xmlDoc.name() == KXMLQLCFixtureGroupName)
8✔
349
        {
350
            m_name = xmlDoc.readElementText();
4✔
351
        }
352
        else
353
        {
354
            qWarning() << Q_FUNC_INFO << "Unknown fixture group tag:" << xmlDoc.name();
×
355
            xmlDoc.skipCurrentElement();
×
356
        }
357
    }
358

359
    return true;
360
}
361

362
bool FixtureGroup::saveXML(QXmlStreamWriter *doc)
4✔
363
{
364
    Q_ASSERT(doc != NULL);
365

366
    /* Fixture Group entry */
367
    doc->writeStartElement(KXMLQLCFixtureGroup);
4✔
368
    doc->writeAttribute(KXMLQLCFixtureGroupID, QString::number(this->id()));
4✔
369

370
    /* Name */
371
    doc->writeTextElement(KXMLQLCFixtureGroupName, name());
4✔
372

373
    /* Matrix size */
374
    doc->writeStartElement(KXMLQLCFixtureGroupSize);
4✔
375
    doc->writeAttribute("X", QString::number(size().width()));
4✔
376
    doc->writeAttribute("Y", QString::number(size().height()));
4✔
377
    doc->writeEndElement();
4✔
378

379
    /* Fixture heads */
380
    QList<QLCPoint> pointsList = m_heads.keys();
4✔
381

382
    foreach (QLCPoint pt, pointsList)
68✔
383
    {
384
        GroupHead head = m_heads[pt];
64✔
385
        doc->writeStartElement(KXMLQLCFixtureGroupHead);
64✔
386
        doc->writeAttribute("X", QString::number(pt.x()));
64✔
387
        doc->writeAttribute("Y", QString::number(pt.y()));
64✔
388
        doc->writeAttribute("Fixture", QString::number(head.fxi));
64✔
389
        doc->writeCharacters(QString::number(head.head));
64✔
390
        doc->writeEndElement();
64✔
391
    }
64✔
392

393
    doc->writeEndElement();
4✔
394

395
    return true;
4✔
396
}
4✔
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