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

mcallegari / qlcplus / 15805077468

22 Jun 2025 08:36AM UTC coverage: 31.876% (-0.01%) from 31.89%
15805077468

push

github

mcallegari
plugins/dmxusb: fix RDM discovery and commands while DMX is running

0 of 1 new or added line in 1 file covered. (0.0%)

3722 existing lines in 175 files now uncovered.

16438 of 51569 relevant lines covered (31.88%)

19266.08 hits per line

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

0.0
/ui/src/cuestackmodel.cpp
1
/*
2
  Q Light Controller Plus
3
  cuestackmodel.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 <QApplication>
24
#include <QMimeData>
25
#include <QPalette>
26
#include <QBuffer>
27
#include <QBrush>
28
#include <QDebug>
29
#include <QIcon>
30

31
#include "cuestackmodel.h"
32
#include "cuestack.h"
33
#include "function.h"
34

35
#define MIMEDATA_ROOT       QString("MimeData")
36
#define MIMEDATA_DRAGINDEX  QString("DragIndex")
37

38
CueStackModel::CueStackModel(QObject* parent)
×
39
    : QAbstractItemModel(parent)
40
    , m_cueStack(NULL)
×
41
{
42
}
×
43

44
CueStackModel::~CueStackModel()
×
45
{
46
}
×
47

48
void CueStackModel::setCueStack(CueStack* cs)
×
49
{
50
    //qDebug() << Q_FUNC_INFO << "old:" << (void*)m_cueStack << "new:" << (void*) cs;
51

52
    if (m_cueStack != NULL)
×
53
    {
54
        // Don't attempt to remove anything if there's nothing to remove
55
        int last = m_cueStack->cues().size() - 1;
×
56
        if (last >= 0)
×
57
            beginRemoveRows(QModelIndex(), 0, last);
×
58

59
        disconnect(m_cueStack, SIGNAL(added(int)), this, SLOT(slotAdded(int)));
×
60
        disconnect(m_cueStack, SIGNAL(removed(int)), this, SLOT(slotRemoved(int)));
×
61
        disconnect(m_cueStack, SIGNAL(changed(int)), this, SLOT(slotChanged(int)));
×
62
        disconnect(m_cueStack, SIGNAL(currentCueChanged(int)), this, SLOT(slotCurrentCueChanged(int)));
×
63
        m_cueStack = NULL;
×
64

65
        if (last >= 0)
×
66
            endRemoveRows();
×
67
    }
68

69
    if (cs != NULL)
×
70
    {
71
        // Don't attempt to insert anything if there's nothing to insert
72
        if (cs->cues().size() > 0)
×
73
            beginInsertRows(QModelIndex(), 0, cs->cues().size() - 1);
×
74
        m_cueStack = cs;
×
75
        connect(m_cueStack, SIGNAL(added(int)), this, SLOT(slotAdded(int)));
×
76
        connect(m_cueStack, SIGNAL(removed(int)), this, SLOT(slotRemoved(int)));
×
77
        connect(m_cueStack, SIGNAL(changed(int)), this, SLOT(slotChanged(int)));
×
78
        connect(m_cueStack, SIGNAL(currentCueChanged(int)), this, SLOT(slotCurrentCueChanged(int)));
×
79
        if (cs->cues().size() > 0)
×
80
            endInsertRows();
×
81
    }
82
}
×
83

84
CueStack* CueStackModel::cueStack() const
×
85
{
86
    return m_cueStack;
×
87
}
88

89
/****************************************************************************
90
 * CueStack slots
91
 ****************************************************************************/
92

93
void CueStackModel::slotAdded(int index)
×
94
{
UNCOV
95
    Q_ASSERT(m_cueStack != NULL);
×
96
    beginInsertRows(QModelIndex(), index, index);
×
97
    endInsertRows();
×
98
}
×
99

100
void CueStackModel::slotRemoved(int index)
×
101
{
UNCOV
102
    Q_ASSERT(m_cueStack != NULL);
×
103
    beginRemoveRows(QModelIndex(), index, index);
×
104
    endRemoveRows();
×
105
}
×
106

107
void CueStackModel::slotChanged(int index)
×
108
{
UNCOV
109
    Q_ASSERT(m_cueStack != NULL);
×
110
    emit dataChanged(createIndex(index, 0, quintptr(0)), createIndex(index, 1, quintptr(0)));
×
111
}
×
112

113
void CueStackModel::slotCurrentCueChanged(int index)
×
114
{
115
    emit dataChanged(createIndex(index, 0, quintptr(0)), createIndex(index, 1, quintptr(0)));
×
116
}
×
117

118
/****************************************************************************
119
 * QAbstractItemModel
120
 ****************************************************************************/
121

122
int CueStackModel::columnCount(const QModelIndex& index) const
×
123
{
124
    Q_UNUSED(index);
125
    return CueStackModel::ColumnCount;
×
126
}
127

128
QVariant CueStackModel::headerData(int section, Qt::Orientation orientation, int role) const
×
129
{
130
    if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
×
UNCOV
131
        return QVariant();
×
132

133
    switch(section)
×
134
    {
135
    case IndexColumn:
×
136
        return tr("Number");
×
137
    case FadeInColumn:
×
138
        return tr("Fade In");
×
139
    case FadeOutColumn:
×
140
        return tr("Fade Out");
×
141
    case DurationColumn:
×
142
        return tr("Duration");
×
143
    case NameColumn:
×
144
        return tr("Cue");
×
UNCOV
145
    default:
×
UNCOV
146
        return QVariant();
×
147
    }
148
}
149

150
QModelIndex CueStackModel::index(int row, int column, const QModelIndex& parent) const
×
151
{
152
    if (m_cueStack == NULL || parent.isValid() == true) // No parents
×
UNCOV
153
        return QModelIndex();
×
154
    else
155
        return createIndex(row, column, quintptr(0));
×
156
}
157

158
QModelIndex CueStackModel::parent(const QModelIndex& index) const
×
159
{
160
    Q_UNUSED(index);
161
    return QModelIndex();
×
162
}
163

164
int CueStackModel::rowCount(const QModelIndex& parent) const
×
165
{
166
    if (m_cueStack == NULL || parent.isValid() == true) // No parents
×
UNCOV
167
        return 0;
×
168
    else
169
        return m_cueStack->cues().size();
×
170
}
171

172
QVariant CueStackModel::data(const QModelIndex& index, int role) const
×
173
{
174
    if (m_cueStack == NULL)
×
UNCOV
175
        return QVariant();
×
176

UNCOV
177
    QVariant var;
×
178
    if (role == Qt::DisplayRole || role == Qt::ToolTipRole)
×
179
    {
180
        switch (index.column())
×
181
        {
UNCOV
182
        case IndexColumn:
×
183
            var = QVariant(index.row() + 1);
×
184
            break;
×
185
        case NameColumn:
×
186
            var = QVariant(m_cueStack->cues()[index.row()].name());
×
187
            break;
×
188
        case FadeInColumn:
×
189
        {
190
            uint ms = m_cueStack->cues()[index.row()].fadeInSpeed();
×
191
            if (ms > 0)
×
192
                var = QVariant(Function::speedToString(ms));
×
193
            else
194
                var = QVariant();
×
UNCOV
195
            break;
×
196
        }
197
        case FadeOutColumn:
×
198
        {
199
            uint ms = m_cueStack->cues()[index.row()].fadeOutSpeed();
×
200
            if (ms > 0)
×
201
                var = QVariant(Function::speedToString(ms));
×
202
            else
203
                var = QVariant();
×
UNCOV
204
            break;
×
205
        }
206
        case DurationColumn:
×
207
        {
208
            uint ms = m_cueStack->cues()[index.row()].duration();
×
209
            if (ms > 0)
×
210
                var = QVariant(Function::speedToString(ms));
×
211
            else
212
                var = QVariant();
×
UNCOV
213
            break;
×
214
        }
UNCOV
215
        default:
×
216
            var = QVariant();
×
217
            break;
×
218
        }
UNCOV
219
    }
×
220
    else if (role == Qt::DecorationRole)
×
221
    {
222
        if (m_cueStack->currentIndex() == index.row() && index.column() == 0)
×
223
            var = QVariant(QIcon(":/current.png"));
×
224
    }
225

UNCOV
226
    return var;
×
227
}
×
228

229
QStringList CueStackModel::mimeTypes () const
×
230
{
231
    return QStringList() << QString("text/plain");
×
232
}
233

234
Qt::DropActions CueStackModel::supportedDropActions() const
×
235
{
236
    return Qt::MoveAction | Qt::CopyAction;
×
237
}
238

239
Qt::ItemFlags CueStackModel::flags(const QModelIndex &index) const
×
240
{
241
    Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
×
UNCOV
242
    if (index.isValid() == true)
×
UNCOV
243
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
×
244
    else
245
        return Qt::ItemIsDropEnabled | defaultFlags;
×
246
}
247

248
bool CueStackModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row,
×
249
                                 int column, const QModelIndex& parent)
250
{
251
    qDebug() << Q_FUNC_INFO;
×
252

253
    Q_UNUSED(row);
254
    Q_UNUSED(column);
255

256
    if (m_cueStack == NULL || action != Qt::MoveAction)
×
UNCOV
257
        return false;
×
258

259
    if (data->hasText() == true)
×
260
    {
261
        QBuffer buffer;
×
262
        buffer.setData(data->text().toLatin1());
×
263
        buffer.open(QIODevice::ReadOnly | QIODevice::Text);
×
264
        QXmlStreamReader doc(&buffer);
×
265
        doc.readNextStartElement();
×
266
        if (doc.device() != NULL && doc.atEnd() == false && doc.hasError() == false)
×
267
        {
268
            if (doc.name() != MIMEDATA_ROOT)
×
269
            {
270
                qWarning() << Q_FUNC_INFO << "Invalid MIME data";
×
271
                return false;
×
272
            }
273

274
            // Dig the drag index from the XML
275
            int dragIndex = doc.attributes().value(MIMEDATA_DRAGINDEX).toString().toInt();
×
UNCOV
276
            int index = parent.row();
×
277
            if (dragIndex < index)
×
278
                index += 1; // Moving items from above drop index
×
279

280
            // Insert each dropped Cue as a new Cue since the originals are in fact
281
            // removed in removeRows().
282
            while (doc.readNextStartElement())
×
283
            {
284
                Cue cue;
×
285
                if (cue.loadXML(doc) == true)
×
286
                {
287
                    m_cueStack->insertCue(index, cue);
×
288
                    index++; // Shift insertion point forwards
×
289
                }
290
            }
×
291
        }
292

293
        return true;
×
294
    }
×
295
    else
296
    {
UNCOV
297
        return false;
×
298
    }
299
}
300

301
QMimeData* CueStackModel::mimeData(const QModelIndexList& indexes) const
×
302
{
303
    qDebug() << Q_FUNC_INFO << indexes;
×
304

305
    if (m_cueStack == NULL || indexes.size() == 0)
×
UNCOV
306
        return NULL;
×
307

308
    // MIME data is essentially a bunch of XML "Cue" entries (plus drag index)
309
    QBuffer buffer;
×
310
    buffer.open(QIODevice::WriteOnly | QIODevice::Text);
×
311
    QXmlStreamWriter doc(&buffer);
×
312
    doc.writeStartElement(MIMEDATA_ROOT);
×
313
    doc.writeAttribute(MIMEDATA_DRAGINDEX, QString::number(indexes.first().row()));
×
314

UNCOV
315
    QSet <int> rows;
×
316
    foreach (QModelIndex index, indexes)
×
317
    {
318
        // $indexes contains all rows' columns but we want to store one row only once.
319
        // So, discard $index if it appears more than once.
320
        if (rows.contains(index.row()) == true)
×
UNCOV
321
            continue;
×
322
        else if (index.row() >= 0 && index.row() < m_cueStack->cues().size())
×
323
            m_cueStack->cues().at(index.row()).saveXML(&doc);
×
UNCOV
324
        rows << index.row();
×
UNCOV
325
    }
×
326

327
    QMimeData* data = new QMimeData;
×
328
    doc.writeEndElement();
×
329
    doc.setDevice(NULL);
×
330
    buffer.close();
×
331

332
    data->setText(QString(buffer.data()));
×
UNCOV
333
    return data;
×
334
}
×
335

336
bool CueStackModel::removeRows(int row, int count, const QModelIndex& parent)
×
337
{
338
    if (m_cueStack == NULL || parent.isValid() == true)
×
UNCOV
339
        return false;
×
340

341
    for (int i = 0; i < count; i++)
×
342
        m_cueStack->removeCue(row);
×
343

UNCOV
344
    return true;
×
345
}
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

© 2026 Coveralls, Inc