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

mcallegari / qlcplus / 7252848206

18 Dec 2023 07:26PM UTC coverage: 32.067% (+0.001%) from 32.066%
7252848206

push

github

mcallegari
Code style review #1427

199 of 628 new or added lines in 101 files covered. (31.69%)

8 existing lines in 2 files now uncovered.

15169 of 47304 relevant lines covered (32.07%)

23733.74 hits per line

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

0.0
/ui/src/virtualconsole/vcxypadproperties.cpp
1
/*
2
  Q Light Controller
3
  vcxypadproperties.h
4

5
  Copyright (C) Stefan Krumm, Heikki Junnila
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 <QTreeWidgetItem>
21
#include <QTreeWidget>
22
#include <QMessageBox>
23
#include <QHeaderView>
24
#include <QSettings>
25
#include <QDebug>
26
#include <QAction>
27

28
#include "qlcfixturemode.h"
29
#include "qlcchannel.h"
30
#include "qlcmacros.h"
31

32
#include "vcxypadfixtureeditor.h"
33
#include "inputselectionwidget.h"
34
#include "vcxypadproperties.h"
35
#include "functionselection.h"
36
#include "fixtureselection.h"
37
#include "vcxypadfixture.h"
38
#include "vcxypadpreset.h"
39
#include "vcxypadarea.h"
40
#include "vcxypad.h"
41
#include "apputil.h"
42
#include "scene.h"
43
#include "doc.h"
44
#include "efx.h"
45

46
#define SETTINGS_GEOMETRY "vcxypad/geometry"
47

48
#define KColumnFixture   0
49
#define KColumnXAxis     1
50
#define KColumnYAxis     2
51

52
/****************************************************************************
53
 * Initialization
54
 ****************************************************************************/
55

56
VCXYPadProperties::VCXYPadProperties(VCXYPad* xypad, Doc* doc)
×
57
    : QDialog(xypad)
58
    , m_xypad(xypad)
59
    , m_doc(doc)
×
60
{
61
    Q_ASSERT(doc != NULL);
×
62
    Q_ASSERT(xypad != NULL);
×
63

64
    setupUi(this);
×
65

66
    // IDs 0-15 are reserved for XYPad base controls
67
    m_lastAssignedID = 15;
×
68

69
    QAction* action = new QAction(this);
×
70
    action->setShortcut(QKeySequence(QKeySequence::Close));
×
71
    connect(action, SIGNAL(triggered(bool)), this, SLOT(reject()));
×
72
    addAction(action);
×
73

74
    /********************************************************************
75
     * General page
76
     ********************************************************************/
77

78
    m_nameEdit->setText(m_xypad->caption());
×
79

80
    if (m_xypad->invertedAppearance() == true)
×
81
        m_YInvertedRadio->setChecked(true);
×
82

83
    m_panInputWidget = new InputSelectionWidget(m_doc, this);
×
84
    m_panInputWidget->setTitle(tr("Pan / Horizontal Axis"));
×
85
    m_panInputWidget->setKeyInputVisibility(false);
×
86
    m_panInputWidget->setInputSource(m_xypad->inputSource(VCXYPad::panInputSourceId));
×
87
    m_panInputWidget->setWidgetPage(m_xypad->page());
×
88
    m_panInputWidget->emitOddValues(true);
×
89
    m_panInputWidget->show();
×
90
    m_extInputLayout->addWidget(m_panInputWidget);
×
91
    connect(m_panInputWidget, SIGNAL(autoDetectToggled(bool)),
×
92
            this, SLOT(slotPanAutoDetectToggled(bool)));
93
    connect(m_panInputWidget, SIGNAL(inputValueChanged(quint32,quint32)),
×
94
            this, SLOT(slotPanInputValueChanged(quint32,quint32)));
95

96
    m_tiltInputWidget = new InputSelectionWidget(m_doc, this);
×
97
    m_tiltInputWidget->setTitle(tr("Tilt / Vertical Axis"));
×
98
    m_tiltInputWidget->setKeyInputVisibility(false);
×
99
    m_tiltInputWidget->setInputSource(m_xypad->inputSource(VCXYPad::tiltInputSourceId));
×
100
    m_tiltInputWidget->setWidgetPage(m_xypad->page());
×
101
    m_tiltInputWidget->emitOddValues(true);
×
102
    m_tiltInputWidget->show();
×
103
    m_extInputLayout->addWidget(m_tiltInputWidget);
×
104
    connect(m_tiltInputWidget, SIGNAL(autoDetectToggled(bool)),
×
105
            this, SLOT(slotTiltAutoDetectToggled(bool)));
106
    connect(m_tiltInputWidget, SIGNAL(inputValueChanged(quint32,quint32)),
×
107
            this, SLOT(slotTiltInputValueChanged(quint32,quint32)));
108

109
    m_widthInputWidget = new InputSelectionWidget(m_doc, this);
×
110
    m_widthInputWidget->setTitle(tr("Width"));
×
111
    m_widthInputWidget->setKeyInputVisibility(false);
×
112
    m_widthInputWidget->setInputSource(m_xypad->inputSource(VCXYPad::widthInputSourceId));
×
113
    m_widthInputWidget->setWidgetPage(m_xypad->page());
×
114
    m_widthInputWidget->show();
×
115
    m_sizeInputLayout->addWidget(m_widthInputWidget);
×
116

117
    m_heightInputWidget = new InputSelectionWidget(m_doc, this);
×
118
    m_heightInputWidget->setTitle(tr("Height"));
×
119
    m_heightInputWidget->setKeyInputVisibility(false);
×
120
    m_heightInputWidget->setInputSource(m_xypad->inputSource(VCXYPad::heightInputSourceId));
×
121
    m_heightInputWidget->setWidgetPage(m_xypad->page());
×
122
    m_heightInputWidget->show();
×
123
    m_sizeInputLayout->addWidget(m_heightInputWidget);
×
124

125
    /********************************************************************
126
     * Fixtures page
127
     ********************************************************************/
128

129
    slotSelectionChanged(NULL);
×
130
    fillFixturesTree();
×
131

132
    connect(m_percentageRadio, SIGNAL(clicked(bool)),
×
133
            this, SLOT(slotPercentageRadioChecked()));
134
    connect(m_degreesRadio, SIGNAL(clicked(bool)),
×
135
            this, SLOT(slotDegreesRadioChecked()));
136
    connect(m_dmxRadio, SIGNAL(clicked(bool)),
×
137
            this, SLOT(slotDMXRadioChecked()));
138

139
    /********************************************************************
140
     * Presets page
141
     ********************************************************************/
142

143
    m_presetInputWidget = new InputSelectionWidget(m_doc, this);
×
144
    m_presetInputWidget->setCustomFeedbackVisibility(true);
×
145
    m_presetInputWidget->setWidgetPage(m_xypad->page());
×
146
    m_presetInputWidget->show();
×
147
    m_presetInputLayout->addWidget(m_presetInputWidget);
×
148

149
    connect(m_presetInputWidget, SIGNAL(inputValueChanged(quint32,quint32)),
×
150
            this, SLOT(slotInputValueChanged(quint32,quint32)));
151
    connect(m_presetInputWidget, SIGNAL(keySequenceChanged(QKeySequence)),
×
152
            this, SLOT(slotKeySequenceChanged(QKeySequence)));
153

154
    connect(m_addPositionButton, SIGNAL(clicked(bool)),
×
155
            this, SLOT(slotAddPositionClicked()));
156
    connect(m_addEfxButton, SIGNAL(clicked(bool)),
×
157
            this, SLOT(slotAddEFXClicked()));
158
    connect(m_addSceneButton, SIGNAL(clicked(bool)),
×
159
            this, SLOT(slotAddSceneClicked()));
160
    connect(m_addFxGroupButton, SIGNAL(clicked(bool)),
×
161
            this, SLOT(slotAddFixtureGroupClicked()));
162
    connect(m_removePresetButton, SIGNAL(clicked()),
×
163
            this, SLOT(slotRemovePresetClicked()));
164
    connect(m_moveUpPresetButton, SIGNAL(clicked()),
×
165
            this, SLOT(slotMoveUpPresetClicked()));
166
    connect(m_moveDownPresetButton, SIGNAL(clicked()),
×
167
            this, SLOT(slotMoveDownPresetClicked()));
168
    connect(m_presetNameEdit, SIGNAL(textEdited(QString const&)),
×
169
            this, SLOT(slotPresetNameEdited(QString const&)));
170
    connect(m_presetsTree, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
×
171
            this, SLOT(slotPresetSelectionChanged()));
172

173
    m_xyArea = new VCXYPadArea(this);
×
174
    //m_xyArea->setFixedSize(140, 140);
175
    m_xyArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
×
176
    m_xyArea->setMode(Doc::Operate);
×
177
    m_presetLayout->addWidget(m_xyArea);
×
178
    connect(m_xyArea, SIGNAL(positionChanged(QPointF)),
×
179
            this, SLOT(slotXYPadPositionChanged(QPointF)));
180

NEW
181
    foreach (const VCXYPadPreset *preset, m_xypad->presets())
×
182
    {
183
        m_presetList.append(new VCXYPadPreset(*preset));
×
184
        if (preset->m_id > m_lastAssignedID)
×
185
            m_lastAssignedID = preset->m_id;
×
186
    }
187

188
    updatePresetsTree();
×
189

190
    QSettings settings;
×
191
    QVariant var = settings.value(SETTINGS_GEOMETRY);
×
192
    if (var.isValid() == true)
×
193
        restoreGeometry(var.toByteArray());
×
194
    AppUtil::ensureWidgetIsVisible(this);
×
195

196
    m_doc->masterTimer()->registerDMXSource(this);
×
197
}
×
198

199
VCXYPadProperties::~VCXYPadProperties()
×
200
{
201
    QSettings settings;
×
202
    settings.setValue(SETTINGS_GEOMETRY, saveGeometry());
×
203
    m_doc->masterTimer()->unregisterDMXSource(this);
×
204
    foreach (QSharedPointer<GenericFader> fader, m_fadersMap.values())
×
205
    {
206
        if (!fader.isNull())
×
207
            fader->requestDelete();
×
208
    }
209
    m_fadersMap.clear();
×
210

211
    delete m_presetInputWidget;
×
212
}
×
213

214
/****************************************************************************
215
 * Fixtures page
216
 ****************************************************************************/
217

218
void VCXYPadProperties::fillFixturesTree()
×
219
{
220
    m_tree->clear();
×
221

222
    QListIterator <VCXYPadFixture> it(m_xypad->fixtures());
×
223
    while (it.hasNext() == true)
×
224
        updateFixtureItem(new QTreeWidgetItem(m_tree), it.next());
×
225
    m_tree->setCurrentItem(m_tree->topLevelItem(0));
×
226
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
227
}
×
228

229
void VCXYPadProperties::updateFixturesTree(VCXYPadFixture::DisplayMode mode)
×
230
{
NEW
231
    for (int i = 0; i < m_tree->topLevelItemCount(); i++)
×
232
    {
233
        QTreeWidgetItem *item = m_tree->topLevelItem(i);
×
234
        QVariant var(item->data(KColumnFixture, Qt::UserRole));
×
235
        VCXYPadFixture fx = VCXYPadFixture(m_doc, var);
×
236
        fx.setDisplayMode(mode);
×
237
        updateFixtureItem(item, fx);
×
238
    }
239
}
×
240

241
void VCXYPadProperties::updateFixtureItem(QTreeWidgetItem* item,
×
242
                                          const VCXYPadFixture& fxi)
243
{
244
    Q_ASSERT(item != NULL);
×
245

246
    item->setText(KColumnFixture, fxi.name());
×
247
    item->setText(KColumnXAxis, fxi.xBrief());
×
248
    item->setText(KColumnYAxis, fxi.yBrief());
×
249
    item->setData(KColumnFixture, Qt::UserRole, QVariant(fxi));
×
250
}
×
251

252
QList <VCXYPadFixture> VCXYPadProperties::selectedFixtures() const
×
253
{
254
    QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
255
    QList <VCXYPadFixture> list;
×
256

257
    /* Put all selected fixtures to a list and return it */
258
    while (it.hasNext() == true)
×
259
        list << VCXYPadFixture(m_doc, it.next()->data(KColumnFixture, Qt::UserRole));
×
260

261
    return list;
×
262
}
263

264
QTreeWidgetItem* VCXYPadProperties::fixtureItem(const VCXYPadFixture& fxi)
×
265
{
266
    QTreeWidgetItemIterator it(m_tree);
×
267
    while (*it != NULL)
×
268
    {
269
        QVariant var((*it)->data(KColumnFixture, Qt::UserRole));
×
270
        VCXYPadFixture another(m_doc, var);
×
271
        if (fxi.head() == another.head())
×
272
            return *it;
×
273
        else
274
            ++it;
×
275
    }
276

277
    return NULL;
×
278
}
279

280
void VCXYPadProperties::removeFixtureItem(GroupHead const & head)
×
281
{
282
    QTreeWidgetItemIterator it(m_tree);
×
283
    while (*it != NULL)
×
284
    {
285
        QVariant var((*it)->data(KColumnFixture, Qt::UserRole));
×
286
        VCXYPadFixture fxi(m_doc, var);
×
287
        if (fxi.head() == head)
×
288
        {
289
            delete (*it);
×
290
            break;
×
291
        }
292

293
        ++it;
×
294
    }
295
}
×
296

297
void VCXYPadProperties::slotAddClicked()
×
298
{
299
    /* Put all fixtures already present into a list of fixtures that
300
       will be disabled in the fixture selection dialog */
301
    QList <GroupHead> disabled;
×
302
    QTreeWidgetItemIterator twit(m_tree);
×
303
    while (*twit != NULL)
×
304
    {
305
        QVariant var((*twit)->data(KColumnFixture, Qt::UserRole));
×
306
        VCXYPadFixture fxi(m_doc, var);
×
307
        disabled << fxi.head();
×
308
        ++twit;
×
309
    }
310

311
    /* Disable all fixtures that don't have pan OR tilt channels */
312
    QListIterator <Fixture*> fxit(m_doc->fixtures());
×
313
    while (fxit.hasNext() == true)
×
314
    {
315
        Fixture* fixture(fxit.next());
×
316
        Q_ASSERT(fixture != NULL);
×
317

318
        // If a channel with pan or tilt group exists, don't disable this fixture
319
        if (fixture->channel(QLCChannel::Pan) == QLCChannel::invalid() &&
×
320
            fixture->channel(QLCChannel::Tilt) == QLCChannel::invalid())
×
321
        {
322
            // Disable all fixtures without pan or tilt channels
323
            disabled << fixture->id();
×
324
        }
325
        else
326
        {
327
            QVector <QLCFixtureHead> const& heads = fixture->fixtureMode()->heads();
×
328
            for (int i = 0; i < heads.size(); ++i)
×
329
            {
330
                if (heads[i].channelNumber(QLCChannel::Pan, QLCChannel::MSB) == QLCChannel::invalid() &&
×
331
                    heads[i].channelNumber(QLCChannel::Tilt, QLCChannel::MSB) == QLCChannel::invalid() &&
×
332
                    heads[i].channelNumber(QLCChannel::Pan, QLCChannel::LSB) == QLCChannel::invalid() &&
×
333
                    heads[i].channelNumber(QLCChannel::Tilt, QLCChannel::LSB) == QLCChannel::invalid())
×
334
                {
335
                    // Disable heads without pan or tilt channels
336
                    disabled << GroupHead(fixture->id(), i);
×
337
                }
338
            }
339
        }
340
    }
341

342
    /* Get a list of new fixtures to add to the pad */
343
    QTreeWidgetItem* item = NULL;
×
344
    FixtureSelection fs(this, m_doc);
×
345
    fs.setMultiSelection(true);
×
346
    fs.setSelectionMode(FixtureSelection::Heads);
×
347
    fs.setDisabledHeads(disabled);
×
348
    if (fs.exec() == QDialog::Accepted)
×
349
    {
350
        QListIterator <GroupHead> it(fs.selectedHeads());
×
351
        while (it.hasNext() == true)
×
352
        {
353
            VCXYPadFixture fxi(m_doc);
×
354
            fxi.setHead(it.next());
×
355
            item = new QTreeWidgetItem(m_tree);
×
356
            updateFixtureItem(item, fxi);
×
357
        }
358
    }
359

360
    if (item != NULL)
×
361
        m_tree->setCurrentItem(item);
×
362

363
    m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
364
}
×
365

366
void VCXYPadProperties::slotRemoveClicked()
×
367
{
368
    int r = QMessageBox::question(
×
369
                this, tr("Remove fixtures"),
×
370
                tr("Do you want to remove the selected fixtures?"),
×
371
                QMessageBox::Yes, QMessageBox::No);
372

373
    if (r == QMessageBox::Yes)
×
374
    {
375
        QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
376
        while (it.hasNext() == true)
×
377
            delete it.next();
×
378
    }
379
}
×
380

381
void VCXYPadProperties::slotEditClicked()
×
382
{
383
    /* Get a list of selected fixtures */
384
    QList <VCXYPadFixture> list(selectedFixtures());
×
385

386
    /* Start editor */
387
    VCXYPadFixtureEditor editor(this, list);
×
388
    if (editor.exec() == QDialog::Accepted)
×
389
    {
390
        QListIterator <VCXYPadFixture> it(editor.fixtures());
×
391
        while (it.hasNext() == true)
×
392
        {
393
            VCXYPadFixture fxi(it.next());
×
394
            QTreeWidgetItem* item = fixtureItem(fxi);
×
395

396
            updateFixtureItem(item, fxi);
×
397
        }
398
        m_tree->header()->resizeSections(QHeaderView::ResizeToContents);
×
399
    }
400
}
×
401

402
void VCXYPadProperties::slotSelectionChanged(QTreeWidgetItem* item)
×
403
{
404
    if (item == NULL)
×
405
    {
406
        m_removeButton->setEnabled(false);
×
407
        m_editButton->setEnabled(false);
×
408
    }
409
    else
410
    {
411
        m_removeButton->setEnabled(true);
×
412
        m_editButton->setEnabled(true);
×
413
    }
414
}
×
415

416
void VCXYPadProperties::slotPercentageRadioChecked()
×
417
{
418
    updateFixturesTree(VCXYPadFixture::Percentage);
×
419
}
×
420

421
void VCXYPadProperties::slotDegreesRadioChecked()
×
422
{
423
    updateFixturesTree(VCXYPadFixture::Degrees);
×
424
}
×
425

426
void VCXYPadProperties::slotDMXRadioChecked()
×
427
{
428
    updateFixturesTree(VCXYPadFixture::DMX);
×
429
}
×
430

431
/****************************************************************************
432
 * Input page
433
 ****************************************************************************/
434

435
void VCXYPadProperties::slotPanAutoDetectToggled(bool toggled)
×
436
{
437
    if (toggled == true && m_tiltInputWidget->isAutoDetecting())
×
438
        m_tiltInputWidget->stopAutoDetection();
×
439
}
×
440

441
void VCXYPadProperties::slotPanInputValueChanged(quint32 uni, quint32 ch)
×
442
{
443
    QSharedPointer<QLCInputSource> tmpSource = m_panInputWidget->inputSource();
×
444
    if (tmpSource->universe() != uni || tmpSource->channel() != ch)
×
445
        m_tiltInputWidget->setInputSource(
×
446
                    QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch)));
×
447
}
×
448

449
void VCXYPadProperties::slotTiltAutoDetectToggled(bool toggled)
×
450
{
451
    if (toggled == true && m_panInputWidget->isAutoDetecting())
×
452
        m_panInputWidget->stopAutoDetection();
×
453
}
×
454

455
void VCXYPadProperties::slotTiltInputValueChanged(quint32 uni, quint32 ch)
×
456
{
457
    QSharedPointer<QLCInputSource> tmpSource = m_tiltInputWidget->inputSource();
×
458
    if (tmpSource->universe() != uni || tmpSource->channel() != ch)
×
459
        m_panInputWidget->setInputSource(
×
460
                    QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch)));
×
461
}
×
462

463
void VCXYPadProperties::writeDMX(MasterTimer *timer, QList<Universe *> universes)
×
464
{
465
    Q_UNUSED(timer);
466

467
    if (m_tab->currentIndex() != 2 || m_xyArea->hasPositionChanged() == false)
×
468
        return;
×
469

470
    //qDebug() << Q_FUNC_INFO;
471

472
    // This call also resets the m_changed flag in m_area
473
    QPointF pt = m_xyArea->position();
×
474

475
    /* Scale XY coordinate values to 0.0 - 1.0 */
476
    qreal x = SCALE(pt.x(), qreal(0), qreal(256), qreal(0), qreal(1));
×
477
    qreal y = SCALE(pt.y(), qreal(0), qreal(256), qreal(0), qreal(1));
×
478

479
    if (m_YInvertedRadio->isChecked())
×
480
        y = qreal(1) - y;
×
481

482
    QTreeWidgetItemIterator it(m_tree);
×
483
    while (*it != NULL)
×
484
    {
485
        QVariant var((*it)->data(KColumnFixture, Qt::UserRole));
×
486
        VCXYPadFixture fixture(m_doc, var);
×
487
        fixture.arm();
×
488
        quint32 universe = fixture.universe();
×
489
        if (universe == Universe::invalid())
×
490
            continue;
×
491

492
        QSharedPointer<GenericFader> fader = m_fadersMap.value(universe, QSharedPointer<GenericFader>());
×
493
        if (fader.isNull())
×
494
        {
495
            fader = universes[universe]->requestFader();
×
496
            m_fadersMap[universe] = fader;
×
497
        }
498
        fixture.writeDMX(x, y, fader, universes[universe]);
×
499
        fixture.disarm();
×
500
        ++it;
×
501
    }
502
}
503

504
/********************************************************************
505
 * Presets
506
 ********************************************************************/
507

508
void VCXYPadProperties::updatePresetsTree()
×
509
{
510
    m_presetsTree->blockSignals(true);
×
511
    m_presetsTree->clear();
×
512

513
    for (int i = 0; i < m_presetList.count(); i++)
×
514
    {
515
        VCXYPadPreset *preset = m_presetList.at(i);
×
516
        QTreeWidgetItem *item = new QTreeWidgetItem(m_presetsTree);
×
517
        item->setData(0, Qt::UserRole, preset->m_id);
×
518
        item->setText(0, preset->m_name);
×
519
        if (preset->m_type == VCXYPadPreset::EFX)
×
520
            item->setIcon(0, QIcon(":/efx.png"));
×
521
        else if (preset->m_type == VCXYPadPreset::Scene)
×
522
            item->setIcon(0, QIcon(":/scene.png"));
×
523
        else if (preset->m_type == VCXYPadPreset::Position)
×
524
            item->setIcon(0, QIcon(":/xypad.png"));
×
525
        else if (preset->m_type == VCXYPadPreset::FixtureGroup)
×
526
            item->setIcon(0, QIcon(":/group.png"));
×
527
    }
528
    m_presetsTree->resizeColumnToContents(0);
×
529
    m_presetsTree->blockSignals(false);
×
530
}
×
531

532
void VCXYPadProperties::selectItemOnPresetsTree(quint8 presetId)
×
533
{
534
    m_presetsTree->blockSignals(true);
×
535

536
    for (int i = 0; i < m_presetsTree->topLevelItemCount(); ++i)
×
537
    {
538
        QTreeWidgetItem* treeItem = m_presetsTree->topLevelItem(i);
×
539
        if (treeItem->data(0, Qt::UserRole).toUInt() == presetId)
×
540
        {
541
            treeItem->setSelected(true);
×
542
            break;
×
543
        }
544
    }
545

546
    m_presetsTree->blockSignals(false);
×
547
}
×
548

549
void VCXYPadProperties::updateTreeItem(const VCXYPadPreset &preset)
×
550
{
551
    m_presetsTree->blockSignals(true);
×
552

553
    for (int i = 0; i < m_presetsTree->topLevelItemCount(); ++i)
×
554
    {
555
        QTreeWidgetItem* treeItem = m_presetsTree->topLevelItem(i);
×
556
        if (treeItem->data(0, Qt::UserRole).toUInt() == preset.m_id)
×
557
        {
558
            treeItem->setText(0, preset.m_name);
×
559
            m_presetsTree->resizeColumnToContents(0);
×
560
            m_presetsTree->blockSignals(false);
×
561
            return;
×
562
        }
563
    }
564
    Q_ASSERT(false);
×
565
}
566

567
VCXYPadPreset *VCXYPadProperties::getSelectedPreset()
×
568
{
569
    if (m_presetsTree->selectedItems().isEmpty())
×
570
        return NULL;
×
571

572
    QTreeWidgetItem* item = m_presetsTree->selectedItems().first();
×
573
    if (item != NULL)
×
574
    {
575
        quint8 presetID = item->data(0, Qt::UserRole).toUInt();
×
NEW
576
        foreach (VCXYPadPreset* preset, m_presetList)
×
577
        {
578
            if (preset->m_id == presetID)
×
579
                return preset;
×
580
        }
581
    }
582

583
    Q_ASSERT(false);
×
584
    return NULL;
585
}
586

587
void VCXYPadProperties::removePreset(quint8 id)
×
588
{
NEW
589
    for (int i = 0; i < m_presetList.count(); i++)
×
590
    {
591
        if (m_presetList.at(i)->m_id == id)
×
592
        {
593
            m_presetList.removeAt(i);
×
594
            return;
×
595
        }
596
    }
597
}
598

599
quint8 VCXYPadProperties::moveUpPreset(quint8 id)
×
600
{
NEW
601
    for (int i = 0; i < m_presetList.count(); i++)
×
602
    {
603
        if (m_presetList.at(i)->m_id == id)
×
604
        {
NEW
605
            if (i > 0)
×
606
            {
607
                //change order on hash preset structure.
608
                //presets are saved in hash and sort on id is used to create the preset list.
609
                //So swapping id change order every time that preset list is created (restore, dialog open, ...).
610
                quint8 dstPosID = m_presetList.at(i-1)->m_id;
×
611
                quint8 srcPosID = m_presetList.at(i)->m_id;
×
612

613
                m_presetList.at(i-1)->m_id = srcPosID;
×
614
                m_presetList.at(i)->m_id = dstPosID;
×
615

616
                //change order on current preset list...
617
                m_presetList.move(i, i-1);
×
618

619
                return dstPosID;
×
620
            }
621

622
            return id;
×
623
        }
624
    }
625

626
    return id;
×
627
}
628

629
quint8 VCXYPadProperties::moveDownPreset(quint8 id)
×
630
{
NEW
631
    for (int i = 0; i < m_presetList.count(); i++)
×
632
    {
633
        if (m_presetList.at(i)->m_id == id)
×
634
        {
NEW
635
            if (i < m_presetList.count() - 1)
×
636
            {
637
                //change order on hash preset structure.
638
                //presets are saved in hash and sort on id is used to create the preset list.
639
                //So swapping id change order every time that preset list is created (restore, dialog open, ...).
640
                quint8 dstPosID = m_presetList.at(i+1)->m_id;
×
641
                quint8 srcPosID = m_presetList.at(i)->m_id;
×
642

643
                m_presetList.at(i+1)->m_id = srcPosID;
×
644
                m_presetList.at(i)->m_id = dstPosID;
×
645

646
                //change order on current preset list...
647
                m_presetList.move(i, i+1);
×
648

649
                return dstPosID;
×
650
            }
651
            return id;
×
652
        }
653
    }
654

655
    return id;
×
656
}
657

658
void VCXYPadProperties::slotAddPositionClicked()
×
659
{
660
    VCXYPadPreset *newPreset = new VCXYPadPreset(++m_lastAssignedID);
×
661
    newPreset->m_type = VCXYPadPreset::Position;
×
662
    newPreset->m_dmxPos = m_xyArea->position();
×
663
    newPreset->m_name = QString("X:%1 - Y:%2").arg((int)newPreset->m_dmxPos.x()).arg((int)newPreset->m_dmxPos.y());
×
664
    m_presetList.append(newPreset);
×
665
    updatePresetsTree();
×
666
    selectItemOnPresetsTree(newPreset->m_id);
×
667
}
×
668

669
void VCXYPadProperties::slotAddEFXClicked()
×
670
{
671
    FunctionSelection fs(this, m_doc);
×
672
    fs.setMultiSelection(false);
×
673
    fs.setFilter(Function::EFXType, true);
×
674
    QList <quint32> ids;
×
675
    foreach (VCXYPadPreset *preset, m_presetList)
×
676
    {
677
        if (preset->m_type == VCXYPadPreset::EFX)
×
678
            ids.append(preset->m_funcID);
×
679
    }
680

681
    if (fs.exec() == QDialog::Accepted && fs.selection().size() > 0)
×
682
    {
683
        quint32 fID = fs.selection().first();
×
684
        Function *f = m_doc->function(fID);
×
685
        if (f == NULL || f->type() != Function::EFXType)
×
686
            return;
×
687
        VCXYPadPreset *newPreset = new VCXYPadPreset(++m_lastAssignedID);
×
688
        newPreset->m_type = VCXYPadPreset::EFX;
×
689
        newPreset->m_funcID = fID;
×
690
        newPreset->m_name = f->name();
×
691
        m_presetList.append(newPreset);
×
692
        updatePresetsTree();
×
693
        selectItemOnPresetsTree(newPreset->m_id);
×
694
    }
695
}
696

697
void VCXYPadProperties::slotAddSceneClicked()
×
698
{
699
    FunctionSelection fs(this, m_doc);
×
700
    fs.setMultiSelection(false);
×
701
    fs.setFilter(Function::SceneType, true);
×
702
    QList <quint32> ids;
×
703
    foreach (VCXYPadPreset *preset, m_presetList)
×
704
    {
705
        if (preset->m_type == VCXYPadPreset::Scene)
×
706
            ids.append(preset->m_funcID);
×
707
    }
708

709
    if (fs.exec() == QDialog::Accepted && fs.selection().size() > 0)
×
710
    {
711
        quint32 fID = fs.selection().first();
×
712
        Function *f = m_doc->function(fID);
×
713
        if (f == NULL || f->type() != Function::SceneType)
×
714
            return;
×
715
        Scene *scene = qobject_cast<Scene*>(f);
×
716
        bool panTiltFound = false;
×
NEW
717
        foreach (SceneValue scv, scene->values())
×
718
        {
719
            Fixture *fixture = m_doc->fixture(scv.fxi);
×
720
            if (fixture == NULL)
×
721
                continue;
×
722
            const QLCChannel *ch = fixture->channel(scv.channel);
×
723
            if (ch == NULL)
×
724
                continue;
×
725
            if (ch->group() == QLCChannel::Pan || ch->group() == QLCChannel::Tilt)
×
726
            {
727
                panTiltFound = true;
×
728
                break;
×
729
            }
730
        }
731
        if (panTiltFound == false)
×
732
        {
733
            QMessageBox::critical(this, tr("Error"),
×
734
                                  tr("The selected Scene does not include any Pan or Tilt channel.\n"
×
735
                                     "Please select one with such channels."),
736
                                  QMessageBox::Close);
737
            return;
×
738
        }
739
        VCXYPadPreset *newPreset = new VCXYPadPreset(++m_lastAssignedID);
×
740
        newPreset->m_type = VCXYPadPreset::Scene;
×
741
        newPreset->m_funcID = fID;
×
742
        newPreset->m_name = f->name();
×
743
        m_presetList.append(newPreset);
×
744
        updatePresetsTree();
×
745
        selectItemOnPresetsTree(newPreset->m_id);
×
746
    }
747
}
748

749
void VCXYPadProperties::slotAddFixtureGroupClicked()
×
750
{
751
    QList <GroupHead> enabled;
×
752
    QList <GroupHead> disabled;
×
753

754
    QTreeWidgetItemIterator it(m_tree);
×
755
    while (*it != NULL)
×
756
    {
757
        QVariant var((*it)->data(KColumnFixture, Qt::UserRole));
×
758
        VCXYPadFixture fxi(m_doc, var);
×
759
        enabled << fxi.head();
×
760
        ++it;
×
761
    }
762

NEW
763
    foreach (Fixture *fx, m_doc->fixtures())
×
764
    {
765
        for (int i = 0; i < fx->heads(); i++)
×
766
        {
767
            GroupHead gh(fx->id(), i);
×
768
            if (enabled.contains(gh) == false)
×
769
                disabled << gh;
×
770
        }
771
    }
772

773
    FixtureSelection fs(this, m_doc);
×
774
    fs.setMultiSelection(true);
×
775
    fs.setSelectionMode(FixtureSelection::Heads);
×
776
    fs.setDisabledHeads(disabled);
×
777
    if (fs.exec() == QDialog::Accepted)
×
778
    {
779
        QList<GroupHead> selectedGH = fs.selectedHeads();
×
780
        if (selectedGH.isEmpty())
×
781
        {
782
            QMessageBox::critical(this, tr("Error"),
×
783
                                  tr("Please select at least one fixture or head to create this type of preset!"),
×
784
                                  QMessageBox::Close);
785
            return;
×
786
        }
787

788
        VCXYPadPreset *newPreset = new VCXYPadPreset(++m_lastAssignedID);
×
789
        newPreset->m_type = VCXYPadPreset::FixtureGroup;
×
790
        newPreset->m_name = tr("Fixture Group");
×
791
        newPreset->setFixtureGroup(selectedGH);
×
792
        m_presetList.append(newPreset);
×
793
        updatePresetsTree();
×
794
        selectItemOnPresetsTree(newPreset->m_id);
×
795
    }
796
}
797

798
void VCXYPadProperties::slotRemovePresetClicked()
×
799
{
800
    if (m_presetsTree->selectedItems().isEmpty())
×
801
        return;
×
802
    QTreeWidgetItem *selItem = m_presetsTree->selectedItems().first();
×
803
    quint8 ctlID = selItem->data(0, Qt::UserRole).toUInt();
×
804
    removePreset(ctlID);
×
805
    updatePresetsTree();
×
806
}
807

808
void VCXYPadProperties::slotMoveUpPresetClicked()
×
809
{
810
    if (m_presetsTree->selectedItems().isEmpty())
×
811
        return;
×
812
    QTreeWidgetItem *selItem = m_presetsTree->selectedItems().first();
×
813
    quint8 ctlID = selItem->data(0, Qt::UserRole).toUInt();
×
814
    quint8 newID = moveUpPreset(ctlID);
×
815
    updatePresetsTree();
×
816

817
    //select item on new position. User can make multiple move up/down without need to select item everytime.
818
    selectItemOnPresetsTree(newID);
×
819
}
820

821
void VCXYPadProperties::slotMoveDownPresetClicked()
×
822
{
823
    if (m_presetsTree->selectedItems().isEmpty())
×
824
        return;
×
825
    QTreeWidgetItem *selItem = m_presetsTree->selectedItems().first();
×
826
    quint8 ctlID = selItem->data(0, Qt::UserRole).toUInt();
×
827
    quint8 newID =moveDownPreset(ctlID);
×
828
    updatePresetsTree();
×
829

830
    //select item on new position. User can make multiple move up/down without need to select item everytime.
831
    selectItemOnPresetsTree(newID);
×
832
}
833

834
void VCXYPadProperties::slotPresetNameEdited(const QString &newName)
×
835
{
836
    VCXYPadPreset* preset = getSelectedPreset();
×
837

838
    if (preset != NULL)
×
839
    {
840
        preset->m_name = newName;
×
841

842
        updateTreeItem(*preset);
×
843
    }
844
}
×
845

846
void VCXYPadProperties::slotPresetSelectionChanged()
×
847
{
848
    VCXYPadPreset *preset = getSelectedPreset();
×
849

850
    if (preset != NULL)
×
851
    {
852
        m_presetNameEdit->setText(preset->m_name);
×
853
        m_presetInputWidget->setInputSource(preset->m_inputSource);
×
854
        m_presetInputWidget->setKeySequence(preset->m_keySequence.toString(QKeySequence::NativeText));
×
855
        if (preset->m_type == VCXYPadPreset::EFX)
×
856
        {
857
            Function *f = m_doc->function(preset->functionID());
×
858
            if (f == NULL || f->type() != Function::EFXType)
×
859
                return;
×
860
            EFX *efx = qobject_cast<EFX*>(f);
×
861
            QPolygonF polygon;
×
862
            efx->preview(polygon);
×
863

864
            QVector <QPolygonF> fixturePoints;
×
865
            efx->previewFixtures(fixturePoints);
×
866

867
            m_xyArea->enableEFXPreview(true);
×
868
            m_xyArea->setEnabled(false);
×
869
            m_xyArea->setEFXPolygons(polygon, fixturePoints);
×
870
            m_xyArea->setEFXInterval(efx->duration());
×
871
        }
872
        else if (preset->m_type == VCXYPadPreset::Position)
×
873
        {
874
            m_xyArea->enableEFXPreview(false);
×
875
            m_xyArea->setEnabled(true);
×
876
            m_xyArea->blockSignals(true);
×
877
            m_xyArea->setPosition(preset->m_dmxPos);
×
878
            m_xyArea->repaint();
×
879
            m_xyArea->blockSignals(false);
×
880
        }
881
        else if (preset->m_type == VCXYPadPreset::Scene)
×
882
        {
883
            m_xyArea->enableEFXPreview(false);
×
884
            m_xyArea->setEnabled(false);
×
885
        }
886
    }
887
}
888

889
void VCXYPadProperties::slotXYPadPositionChanged(const QPointF &pt)
×
890
{
891
    VCXYPadPreset *preset = getSelectedPreset();
×
892

893
    if (preset != NULL)
×
894
    {
895
        preset->m_dmxPos = pt;
×
896
        if (preset->m_type == VCXYPadPreset::Position &&
×
897
            preset->m_name.startsWith("X:"))
×
898
        {
899
            preset->m_name = QString("X:%1 - Y:%2").arg((int)pt.x()).arg((int)pt.y());
×
900
            m_presetNameEdit->blockSignals(true);
×
901
            m_presetNameEdit->setText(preset->m_name);
×
902
            m_presetNameEdit->blockSignals(false);
×
903
        }
904
        updateTreeItem(*preset);
×
905
    }
906
}
×
907

908
void VCXYPadProperties::slotInputValueChanged(quint32 universe, quint32 channel)
×
909
{
910
    Q_UNUSED(universe);
911
    Q_UNUSED(channel);
912

913
    VCXYPadPreset *preset = getSelectedPreset();
×
914

915
    if (preset != NULL)
×
916
        preset->m_inputSource = m_presetInputWidget->inputSource();
×
917
}
×
918

919
void VCXYPadProperties::slotKeySequenceChanged(QKeySequence key)
×
920
{
921
    VCXYPadPreset *preset = getSelectedPreset();
×
922

923
    if (preset != NULL)
×
924
        preset->m_keySequence = key;
×
925
}
×
926

927
/****************************************************************************
928
 * OK/Cancel
929
 ****************************************************************************/
930

931
void VCXYPadProperties::accept()
×
932
{
933
    m_xypad->clearFixtures();
×
934
    m_xypad->setCaption(m_nameEdit->text());
×
935
    m_xypad->setInputSource(m_panInputWidget->inputSource(), VCXYPad::panInputSourceId);
×
936
    m_xypad->setInputSource(m_tiltInputWidget->inputSource(), VCXYPad::tiltInputSourceId);
×
937
    m_xypad->setInputSource(m_widthInputWidget->inputSource(), VCXYPad::widthInputSourceId);
×
938
    m_xypad->setInputSource(m_heightInputWidget->inputSource(), VCXYPad::heightInputSourceId);
×
939
    if (m_YNormalRadio->isChecked())
×
940
        m_xypad->setInvertedAppearance(false);
×
941
    else
942
        m_xypad->setInvertedAppearance(true);
×
943

944
    QTreeWidgetItemIterator it(m_tree);
×
945
    while (*it != NULL)
×
946
    {
947
        QVariant var((*it)->data(KColumnFixture, Qt::UserRole));
×
948
        m_xypad->appendFixture(VCXYPadFixture(m_doc, var));
×
949
        ++it;
×
950
    }
951

952
    /* Controls */
953
    m_xypad->resetPresets();
×
954
    for (int i = 0; i < m_presetList.count(); i++)
×
955
        m_xypad->addPreset(*m_presetList.at(i));
×
956

957
    QDialog::accept();
×
958
}
×
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