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

mcallegari / qlcplus / 9022369978

09 May 2024 07:16PM UTC coverage: 31.498% (-0.6%) from 32.068%
9022369978

push

github

mcallegari
coverage: exclude enttecwing from coverage

15000 of 47622 relevant lines covered (31.5%)

16841.64 hits per line

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

77.04
/engine/src/sequence.cpp
1
/*
2
  Q Light Controller Plus
3
  sequence.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 <QDebug>
23

24
#include "sequence.h"
25

26
#define KXMLQLCSequenceBoundScene "BoundScene"
27

28
Sequence::Sequence(Doc* doc)
10✔
29
    : Chaser(doc)
30
    , m_boundSceneID(Function::invalidId())
20✔
31
    , m_needFixup(true)
10✔
32
{
33
    m_type = Function::SequenceType;
10✔
34
    setName(tr("New Sequence"));
10✔
35
}
10✔
36

37
Sequence::~Sequence()
17✔
38
{
39
}
17✔
40

41
QIcon Sequence::getIcon() const
×
42
{
43
    return QIcon(":/sequence.png");
×
44
}
45

46
Function *Sequence::createCopy(Doc *doc, bool addToDoc)
1✔
47
{
48
    Q_ASSERT(doc != NULL);
1✔
49

50
    Function* copy = new Sequence(doc);
1✔
51
    if (copy->copyFrom(this) == false)
1✔
52
    {
53
        delete copy;
×
54
        copy = NULL;
×
55
    }
56
    if (addToDoc == true && doc->addFunction(copy) == false)
1✔
57
    {
58
        delete copy;
×
59
        copy = NULL;
×
60
    }
61

62
    return copy;
1✔
63
}
64

65
bool Sequence::copyFrom(const Function *function)
1✔
66
{
67
    const Sequence* sequence = qobject_cast<const Sequence*> (function);
1✔
68
    if (sequence == NULL)
1✔
69
        return false;
×
70

71
    // Copy sequence stuff
72
    m_steps = sequence->m_steps;
1✔
73
    m_fadeInMode = sequence->m_fadeInMode;
1✔
74
    m_fadeOutMode = sequence->m_fadeOutMode;
1✔
75
    m_holdMode = sequence->m_holdMode;
1✔
76
    m_boundSceneID = sequence->m_boundSceneID;
1✔
77

78
    // Copy common function stuff
79
    return Function::copyFrom(function);
1✔
80
}
81

82
void Sequence::setBoundSceneID(quint32 sceneID)
6✔
83
{
84
    m_boundSceneID = sceneID;
6✔
85
}
6✔
86

87
quint32 Sequence::boundSceneID() const
23✔
88
{
89
    return m_boundSceneID;
23✔
90
}
91

92
QList<quint32> Sequence::components()
×
93
{
94
    QList<quint32> ids;
×
95
    if (m_boundSceneID != Function::invalidId())
×
96
        ids.append(m_boundSceneID);
×
97
    return ids;
×
98
}
99

100
/*****************************************************************************
101
 * Save & Load
102
 *****************************************************************************/
103

104
bool Sequence::saveXML(QXmlStreamWriter *doc)
1✔
105
{
106
    Q_ASSERT(doc != NULL);
1✔
107

108
    /* Function tag */
109
    doc->writeStartElement(KXMLQLCFunction);
1✔
110

111
    /* Common attributes */
112
    saveXMLCommon(doc);
1✔
113

114
    doc->writeAttribute(KXMLQLCSequenceBoundScene, QString::number(boundSceneID()));
2✔
115

116
    /* Speed */
117
    saveXMLSpeed(doc);
1✔
118

119
    /* Direction */
120
    saveXMLDirection(doc);
1✔
121

122
    /* Run order */
123
    saveXMLRunOrder(doc);
1✔
124

125
    /* Speed modes */
126
    doc->writeStartElement(KXMLQLCChaserSpeedModes);
1✔
127
    doc->writeAttribute(KXMLQLCFunctionSpeedFadeIn, speedModeToString(fadeInMode()));
1✔
128
    doc->writeAttribute(KXMLQLCFunctionSpeedFadeOut, speedModeToString(fadeOutMode()));
1✔
129
    doc->writeAttribute(KXMLQLCFunctionSpeedDuration, speedModeToString(durationMode()));
1✔
130
    doc->writeEndElement();
1✔
131

132
    /* Steps */
133
    for (int i = 0; i < m_steps.count(); i++)
4✔
134
        m_steps.at(i).saveXML(doc, i, true);
3✔
135

136
    /* End the <Function> tag */
137
    doc->writeEndElement();
1✔
138

139
    return true;
1✔
140
}
141

142
bool Sequence::loadXML(QXmlStreamReader &root)
4✔
143
{
144
    if (root.name() != KXMLQLCFunction)
4✔
145
    {
146
        qWarning() << Q_FUNC_INFO << "Function node not found";
1✔
147
        return false;
1✔
148
    }
149

150
    QXmlStreamAttributes funcAttrs = root.attributes();
6✔
151

152
    if (funcAttrs.value(KXMLQLCFunctionType).toString() != typeToString(Function::SequenceType))
3✔
153
    {
154
        qWarning() << Q_FUNC_INFO << funcAttrs.value(KXMLQLCFunctionType).toString()
2✔
155
                   << "is not a Sequence";
1✔
156
        return false;
1✔
157
    }
158

159
    if (funcAttrs.hasAttribute(KXMLQLCSequenceBoundScene) == false)
2✔
160
    {
161
        qWarning() << Q_FUNC_INFO << "Sequence doesn't have a bound Scene ID";
×
162
        return false;
×
163
    }
164

165
    setBoundSceneID(funcAttrs.value(KXMLQLCSequenceBoundScene).toString().toUInt());
2✔
166

167
    Scene *scene = qobject_cast<Scene *>(doc()->function(boundSceneID()));
2✔
168
    QList<SceneValue> sceneValues;
×
169
    if (scene != NULL)
2✔
170
    {
171
        sceneValues = scene->values();
1✔
172
        std::sort(sceneValues.begin(), sceneValues.end());
1✔
173
        m_needFixup = false;
1✔
174
    }
175

176
    /* Load Sequence contents */
177
    while (root.readNextStartElement())
16✔
178
    {
179
        if (root.name() == KXMLQLCFunctionSpeed)
14✔
180
        {
181
            loadXMLSpeed(root);
2✔
182
        }
183
        else if (root.name() == KXMLQLCFunctionDirection)
12✔
184
        {
185
            loadXMLDirection(root);
2✔
186
        }
187
        else if (root.name() == KXMLQLCFunctionRunOrder)
10✔
188
        {
189
            loadXMLRunOrder(root);
2✔
190
        }
191
        else if (root.name() == KXMLQLCChaserSpeedModes)
8✔
192
        {
193
            loadXMLSpeedModes(root);
2✔
194
        }
195
        else if (root.name() == KXMLQLCFunctionStep)
6✔
196
        {
197
            //! @todo stepNumber is useless if the steps are in the wrong order
198
            ChaserStep step;
12✔
199
            int stepNumber = -1;
6✔
200

201
            if (sceneValues.isEmpty() == false)
6✔
202
                step.values = sceneValues;
3✔
203

204
            if (step.loadXML(root, stepNumber, doc()) == true)
6✔
205
            {
206
                step.fid = boundSceneID();
6✔
207

208
                if (stepNumber >= m_steps.size())
6✔
209
                    m_steps.append(step);
6✔
210
                else
211
                    m_steps.insert(stepNumber, step);
×
212
            }
213
        }
214
        else
215
        {
216
            qWarning() << Q_FUNC_INFO << "Unknown Sequence tag:" << root.name();
×
217
            root.skipCurrentElement();
×
218
        }
219
    }
220

221
    return true;
2✔
222
}
223

224
void Sequence::postLoad()
1✔
225
{
226
    if (m_needFixup == false)
1✔
227
        return;
×
228

229
    Doc* doc = this->doc();
1✔
230
    Q_ASSERT(doc != NULL);
1✔
231

232
    Scene *scene = qobject_cast<Scene *>(doc->function(boundSceneID()));
1✔
233
    QList<SceneValue> sceneValues;
×
234
    if (scene != NULL)
1✔
235
    {
236
        sceneValues = scene->values();
1✔
237

238
        if (sceneValues.count() == 0)
1✔
239
        {
240
            qDebug() << "The bound Scene is empty ! This should never happen. Trying to fix it...";
×
241
            if (stepsCount())
×
242
            {
243
                foreach (SceneValue value, m_steps.at(0).values)
×
244
                {
245
                    value.value = 0;
×
246
                    if (doc->fixture(value.fxi) != NULL)
×
247
                        scene->setValue(value);
×
248
                }
249
            }
250
            m_needFixup = false;
×
251
            return;
×
252
        }
253

254
        std::sort(sceneValues.begin(), sceneValues.end());
1✔
255
    }
256

257
    int stepIndex = 0;
1✔
258

259
    QMutableListIterator <ChaserStep> it(m_steps);
1✔
260
    while (it.hasNext() == true)
4✔
261
    {
262
        ChaserStep step(it.next());
3✔
263
        if (sceneValues.count() == step.values.count())
3✔
264
        {
265
            stepIndex++;
×
266
            continue;
×
267
        }
268

269
        QList <SceneValue> tmpList = step.values;
3✔
270
        step.values = sceneValues;
3✔
271
        for (int i = 0; i < tmpList.count(); i++)
21✔
272
        {
273
            int tmpIndex = step.values.indexOf(tmpList.at(i));
18✔
274
            if (tmpIndex == -1)
18✔
275
                continue;
×
276
            step.values.replace(tmpIndex, tmpList.at(i));
18✔
277
        }
278

279
        replaceStep(step, stepIndex);
3✔
280
        stepIndex++;
3✔
281
    }
282
    m_needFixup = false;
1✔
283

284
    qDebug() << "Sequence" << name() << "steps fixed. Values:" << sceneValues.count();
1✔
285
}
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