• 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

0.0
/ui/src/inputoutputmanager.cpp
1
/*
2
  Q Light Controller
3
  inputoutputmanager.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 <QListWidgetItem>
21
#include <QListWidget>
22
#include <QHeaderView>
23
#include <QStringList>
24
#include <QVBoxLayout>
25
#include <QMessageBox>
26
#include <QSettings>
27
#include <QSplitter>
28
#include <QLineEdit>
29
#include <QCheckBox>
30
#include <QToolBar>
31
#include <QAction>
32
#include <QTimer>
33
#include <QDebug>
34
#include <QLabel>
35
#include <QIcon>
36

37
#include "inputoutputpatcheditor.h"
38
#include "universeitemwidget.h"
39
#include "inputoutputmanager.h"
40
#include "inputoutputmap.h"
41
#include "outputpatch.h"
42
#include "inputpatch.h"
43
#include "doc.h"
44

45
#define KColumnUniverse     0
46
#define KColumnInput        1
47
#define KColumnOutput       2
48
#define KColumnFeedback     3
49
#define KColumnProfile      4
50
#define KColumnInputNum     5
51
#define KColumnOutputNum    6
52

53
#define SETTINGS_SPLITTER "inputmanager/splitter"
54

55
InputOutputManager* InputOutputManager::s_instance = NULL;
56

57
InputOutputManager::InputOutputManager(QWidget* parent, Doc* doc)
×
58
    : QWidget(parent)
59
    , m_doc(doc)
×
60
    , m_toolbar(NULL)
×
61
    , m_addUniverseAction(NULL)
×
62
    , m_deleteUniverseAction(NULL)
×
63
    , m_uniNameEdit(NULL)
×
64
    , m_uniPassthroughCheck(NULL)
×
65
    , m_editor(NULL)
×
66
    , m_editorUniverse(UINT_MAX)
×
67
{
68
    Q_ASSERT(s_instance == NULL);
69
    s_instance = this;
×
70

71
    Q_ASSERT(doc != NULL);
72

73
    m_ioMap = doc->inputOutputMap();
×
74

75
    /* Create a new layout for this widget */
76
    new QVBoxLayout(this);
×
77
    layout()->setContentsMargins(0, 0, 0, 0);
×
78
    layout()->setSpacing(0);
×
79

80
    m_splitter = new QSplitter(Qt::Horizontal, this);
×
81
    layout()->addWidget(m_splitter);
×
82

83
    m_addUniverseAction = new QAction(QIcon(":/edit_add.png"),
×
84
                                   tr("Add U&niverse"), this);
×
85
    m_addUniverseAction->setShortcut(QKeySequence("CTRL+N"));
×
86
    connect(m_addUniverseAction, SIGNAL(triggered(bool)),
×
87
            this, SLOT(slotAddUniverse()));
88

89
    m_deleteUniverseAction = new QAction(QIcon(":/edit_remove.png"),
×
90
                                   tr("&Delete Universe"), this);
×
91
    m_deleteUniverseAction->setShortcut(QKeySequence("CTRL+D"));
×
92
    connect(m_deleteUniverseAction, SIGNAL(triggered(bool)),
×
93
            this, SLOT(slotDeleteUniverse()));
94

95
    QWidget* ucontainer = new QWidget(this);
×
96
    m_splitter->addWidget(ucontainer);
×
97
    ucontainer->setLayout(new QVBoxLayout);
×
98
    ucontainer->layout()->setContentsMargins(0, 0, 0, 0);
×
99

100
    // Add a toolbar to the dock area
101
    m_toolbar = new QToolBar("Input Output Manager", this);
×
102
    m_toolbar->setFloatable(false);
×
103
    m_toolbar->setMovable(false);
×
104
    m_toolbar->setIconSize(QSize(32, 32));
×
105
    m_toolbar->addAction(m_addUniverseAction);
×
106
    m_toolbar->addAction(m_deleteUniverseAction);
×
107
    m_toolbar->addSeparator();
×
108

109
    QLabel *uniLabel = new QLabel(tr("Universe name:"));
×
110
    m_uniNameEdit = new QLineEdit(this);
×
111
    QFont font = QApplication::font();
×
112
    //font.setBold(true);
113
    font.setPixelSize(18);
×
114
    uniLabel->setFont(font);
×
115
    m_uniNameEdit->setFont(font);
×
116
    m_toolbar->addWidget(uniLabel);
×
117
    m_toolbar->addWidget(m_uniNameEdit);
×
118

119
    m_uniPassthroughCheck = new QCheckBox(tr("Passthrough"), this);
×
120
    m_uniPassthroughCheck->setLayoutDirection(Qt::RightToLeft);
×
121
    m_uniPassthroughCheck->setFont(font);
×
122
    m_toolbar->addWidget(m_uniPassthroughCheck);
×
123

124
    m_splitter->widget(0)->layout()->addWidget(m_toolbar);
×
125

126
    connect(m_uniNameEdit, SIGNAL(textChanged(QString)),
×
127
            this, SLOT(slotUniverseNameChanged(QString)));
128

129
    connect(m_uniPassthroughCheck, SIGNAL(toggled(bool)),
×
130
            this, SLOT(slotPassthroughChanged(bool)));
131

132
    /* Universes list */
133
    m_list = new QListWidget(this);
×
134
    m_list->setItemDelegate(new UniverseItemWidget(m_list));
×
135
    m_splitter->widget(0)->layout()->addWidget(m_list);
×
136

137
    QWidget* gcontainer = new QWidget(this);
×
138
    m_splitter->addWidget(gcontainer);
×
139
    gcontainer->setLayout(new QVBoxLayout);
×
140
    gcontainer->layout()->setContentsMargins(0, 0, 0, 0);
×
141

142
    connect(m_list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
×
143
            this, SLOT(slotCurrentItemChanged()));
144

145
    /* Timer that clears the input data icon after a while */
146
    m_icon = QIcon(":/input.png");
×
147
    m_timer = new QTimer(this);
×
148
    m_timer->setSingleShot(true);
149
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimerTimeout()));
×
150

151
    /* Listen to input map's input data signals */
152
    connect(m_ioMap, SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
153
            this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
154

155
    /* Listen to plugin configuration changes */
156
    connect(m_ioMap, SIGNAL(pluginConfigurationChanged(const QString&, bool)),
×
157
            this, SLOT(updateList()));
158

159
    connect(m_ioMap, SIGNAL(universeAdded(quint32)),
×
160
            this, SLOT(slotUniverseAdded(quint32)));
161

162
    updateList();
×
163
    m_list->setCurrentItem(m_list->item(0));
×
164

165
    QSettings settings;
×
166
    QVariant var = settings.value(SETTINGS_SPLITTER);
×
167
    if (var.isValid() == true)
×
168
        m_splitter->restoreState(var.toByteArray());
×
169
}
×
170

171
InputOutputManager::~InputOutputManager()
×
172
{
173
    QSettings settings;
×
174
    settings.setValue(SETTINGS_SPLITTER, m_splitter->saveState());
×
175

176
    s_instance = NULL;
×
177
}
×
178

179
InputOutputManager* InputOutputManager::instance()
×
180
{
181
    return s_instance;
×
182
}
183

184
/*****************************************************************************
185
 * Tree widget
186
 *****************************************************************************/
187

188
void InputOutputManager::updateList()
×
189
{
190
    m_list->blockSignals(true);
×
191
    m_list->clear();
×
192
    for (quint32 uni = 0; uni < m_ioMap->universesCount(); uni++)
×
193
        updateItem(new QListWidgetItem(m_list), uni);
×
194
    m_list->blockSignals(false);
×
195

196
    if (m_ioMap->universesCount() == 0)
×
197
    {
198
        if (m_editor != NULL)
×
199
        {
200
            m_splitter->widget(1)->layout()->removeWidget(m_editor);
×
201
            m_editor->deleteLater();
×
202
            m_editor = NULL;
×
203
        }
204
        m_deleteUniverseAction->setEnabled(false);
×
205
        m_uniNameEdit->setText("");
×
206
        m_uniNameEdit->setEnabled(false);
×
207
    }
208
    else
209
    {
210
        m_list->setCurrentItem(m_list->item(0));
×
211
        m_uniNameEdit->setEnabled(true);
×
212
        m_uniNameEdit->setText(m_ioMap->getUniverseNameByIndex(0));
×
213
        m_uniPassthroughCheck->setChecked(m_ioMap->getUniversePassthrough(0));
×
214
    }
215
}
×
216

217
void InputOutputManager::updateItem(QListWidgetItem* item, quint32 universe)
×
218
{
219
    Q_ASSERT(item != NULL);
220

221
    InputPatch* ip = m_ioMap->inputPatch(universe);
×
222
    OutputPatch* op = m_ioMap->outputPatch(universe);
×
223
    OutputPatch* fp = m_ioMap->feedbackPatch(universe);
×
224

225
    QString uniName = m_ioMap->getUniverseNameByIndex(universe);
×
226
    if (uniName.isEmpty())
×
227
    {
228
        QString defUniName = tr("Universe %1").arg(universe + 1);
×
229
        m_ioMap->setUniverseName(universe, defUniName);
×
230
        item->setData(Qt::DisplayRole, defUniName);
×
231
    }
×
232
    else
233
        item->setData(Qt::DisplayRole, uniName);
×
234
    item->setSizeHint(QSize(m_list->width(), 50));
×
235
    item->setData(Qt::UserRole, universe);
×
236
    if (ip != NULL)
×
237
    {
238
        item->setData(Qt::UserRole + 1, ip->inputName());
×
239
        item->setData(Qt::UserRole + 2, ip->profileName());
×
240
    }
241
    else
242
    {
243
        item->setData(Qt::UserRole + 1, KInputNone);
×
244
        item->setData(Qt::UserRole + 2, KInputNone);
×
245
    }
246
    if (op != NULL)
×
247
        item->setData(Qt::UserRole + 3, op->outputName());
×
248
    else
249
        item->setData(Qt::UserRole + 3, KOutputNone);
×
250
    if (fp != NULL)
×
251
        item->setData(Qt::UserRole + 4, fp->outputName());
×
252
    else
253
        item->setData(Qt::UserRole + 4, KOutputNone);
×
254
}
×
255

256
void InputOutputManager::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
257
{
258
    Q_UNUSED(channel);
259
    Q_UNUSED(value);
260

261
    // If the manager is not visible, don't even waste CPU
262
    if (isVisible() == false)
×
263
        return;
264

265
    QListWidgetItem *item = m_list->item(universe);
×
266
    if (item == NULL)
×
267
        return;
268

269
    /* Show an icon on a universe row that received input data */
270
    item->setData(Qt::DecorationRole, m_icon);
×
271

272
    /* Restart the timer */
273
    m_timer->start(300);
×
274
}
275

276
void InputOutputManager::slotTimerTimeout()
×
277
{
278
    for (int i = 0; i < m_list->count(); i++)
×
279
    {
280
        QListWidgetItem *item = m_list->item(i);
×
281
        item->setData(Qt::DecorationRole, QIcon());
×
282
    }
283
}
×
284

285
void InputOutputManager::slotCurrentItemChanged()
×
286
{
287
    QListWidgetItem* item = m_list->currentItem();
×
288
    if (item == NULL)
×
289
    {
290
        if (m_ioMap->universesCount() == 0)
×
291
            return;
292

293
        m_list->setCurrentItem(m_list->item(0));
×
294
        item = m_list->currentItem();
×
295
    }
296
    if (item == NULL)
×
297
        return;
298

299
    quint32 universe = item->data(Qt::UserRole).toInt();
×
300
    if (m_editorUniverse == universe)
×
301
        return;
302

303
    if ((universe + 1) != m_ioMap->universesCount())
×
304
        m_deleteUniverseAction->setEnabled(false);
×
305
    else
306
        m_deleteUniverseAction->setEnabled(true);
×
307

308
    if (m_editor != NULL)
×
309
    {
310
        m_splitter->widget(1)->layout()->removeWidget(m_editor);
×
311
        m_editor->deleteLater();
×
312
        m_editor = NULL;
×
313
    }
314

315

316
    m_editor = new InputOutputPatchEditor(this, universe, m_ioMap, m_doc);
×
317
    m_editorUniverse = universe;
×
318
    m_splitter->widget(1)->layout()->addWidget(m_editor);
×
319
    connect(m_editor, SIGNAL(mappingChanged()), this, SLOT(slotMappingChanged()));
×
320
    connect(m_editor, SIGNAL(audioInputDeviceChanged()), this, SLOT(slotAudioInputChanged()));
×
321
    m_editor->show();
×
322
    int uniIdx = m_list->currentRow();
×
323
    m_uniNameEdit->setText(m_ioMap->getUniverseNameByIndex(uniIdx));
×
324
    m_uniPassthroughCheck->setChecked(m_ioMap->getUniversePassthrough(uniIdx));
×
325
}
326

327
void InputOutputManager::slotMappingChanged()
×
328
{
329
    QListWidgetItem* item = m_list->currentItem();
×
330
    if (item != NULL)
×
331
    {
332
        uint universe = item->data(Qt::UserRole).toInt();
×
333
        updateItem(item, universe);
×
334
        m_doc->inputOutputMap()->saveDefaults();
×
335
    }
336
}
×
337

338
void InputOutputManager::slotAudioInputChanged()
×
339
{
340
    m_doc->destroyAudioCapture();
×
341
}
×
342

343
void InputOutputManager::slotAddUniverse()
×
344
{
345
    m_ioMap->addUniverse();
×
346
    m_ioMap->startUniverses();
×
347
    m_doc->setModified();
×
348
}
×
349

350
void InputOutputManager::slotDeleteUniverse()
×
351
{
352
    int uniIdx = m_list->currentRow();
×
353

354
    Q_ASSERT((uniIdx + 1) == (int)(m_ioMap->universesCount()));
355

356
    // Check if the universe is patched
357
    if (m_ioMap->isUniversePatched(uniIdx) == true)
×
358
    {
359
        // Ask for user's confirmation
360
        if (QMessageBox::question(
×
361
                    this, tr("Delete Universe"),
×
362
                    tr("The universe you are trying to delete is patched. Are you sure you want to delete it?"),
×
363
                    QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
364
        {
365
            return;
366
        }
367
    }
368

369
    // Check if there are fixtures using this universe
370
    quint32 uniID = m_ioMap->getUniverseID(uniIdx);
×
371
    if (uniID == m_ioMap->invalidUniverse())
×
372
        return;
373

374
    foreach (Fixture *fx, m_doc->fixtures())
×
375
    {
376
        if (fx->universe() == uniID)
×
377
        {
378
            // Ask for user's confirmation
379
            if (QMessageBox::question(
×
380
                        this, tr("Delete Universe"),
×
381
                        tr("There are some fixtures using the universe you are trying to delete. Are you sure you want to delete it?"),
×
382
                        QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
383
            {
384
                return;
385
            }
386
            break;
387
        }
388
    }
389

390
    m_ioMap->removeUniverse(uniIdx);
×
391
    m_doc->setModified();
×
392
    updateList();
×
393
}
394

395
void InputOutputManager::slotUniverseNameChanged(QString name)
×
396
{
397
    QListWidgetItem *currItem = m_list->currentItem();
×
398
    if (currItem == NULL)
×
399
        return;
400

401
    int uniIdx = m_list->currentRow();
×
402
    if (name.isEmpty())
×
403
        name = tr("Universe %1").arg(uniIdx + 1);
×
404
    m_ioMap->setUniverseName(uniIdx, name);
×
405
    currItem->setData(Qt::DisplayRole, name);
×
406
}
407

408
void InputOutputManager::slotUniverseAdded(quint32 universe)
×
409
{
410
    QListWidgetItem *item = new QListWidgetItem(m_list);
×
411
    updateItem(item, universe);
×
412
}
×
413

414
void InputOutputManager::slotPassthroughChanged(bool checked)
×
415
{
416
    QListWidgetItem *currItem = m_list->currentItem();
×
417
    if (currItem == NULL)
×
418
        return;
419

420
    int uniIdx = m_list->currentRow();
×
421
    m_ioMap->setUniversePassthrough(uniIdx, checked);
×
422
    m_doc->inputOutputMap()->saveDefaults();
×
423
}
424

425
void InputOutputManager::showEvent(QShowEvent *ev)
×
426
{
427
    Q_UNUSED(ev);
428
    // force the recreation of the selected universe editor
429
    m_editorUniverse = UINT_MAX;
×
430
    updateList();
×
431
}
×
432

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