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

mcallegari / qlcplus / 26356589956

24 May 2026 08:40AM UTC coverage: 35.006% (-0.03%) from 35.037%
26356589956

Pull #2032

github

web-flow
Merge 77d3323dc into 100c1a70b
Pull Request #2032: engine/scene,ui/sceneditor: implement fixture reordering

4 of 56 new or added lines in 2 files covered. (7.14%)

1 existing line in 1 file now uncovered.

18296 of 52266 relevant lines covered (35.01%)

41115.32 hits per line

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

0.0
/ui/src/sceneeditor.cpp
1
/*
2
  Q Light Controller
3
  sceneeditor.cpp
4

5
  Copyright (c) Heikki Junnila, Stefan Krumm
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 <QColorDialog>
22
#include <QTreeWidget>
23
#include <QMessageBox>
24
#include <QToolButton>
25
#include <QScrollArea>
26
#include <QTabWidget>
27
#include <QComboBox>
28
#include <QSettings>
29
#include <QLineEdit>
30
#include <QToolBar>
31
#include <QLayout>
32
#include <qmath.h>
33
#include <QLabel>
34
#include <QDebug>
35

36
#include "genericdmxsource.h"
37
#include "fixtureselection.h"
38
#include "speeddialwidget.h"
39
#include "functionmanager.h"
40
#include "fixtureconsole.h"
41
#include "groupsconsole.h"
42
#include "qlcfixturedef.h"
43
#include "channelsgroup.h"
44
#include "qlcclipboard.h"
45
#include "positiontool.h"
46
#include "sceneeditor.h"
47
#include "qlcchannel.h"
48
#include "chaserstep.h"
49
#include "fixture.h"
50
#include "chaser.h"
51
#include "scene.h"
52
#include "doc.h"
53

54
#define KColumnName         0
55
#define KColumnManufacturer 1
56
#define KColumnModel        2
57
#define KColumnID           3
58

59
#define KTabGeneral         0
60

61
#define SETTINGS_CHASER "sceneeditor/chaser"
62

63
#define UI_STATE_TAB_INDEX "tabIndex"
64
#define UI_STATE_TAB_MODE  "tabMode"
65
#define UI_STATE_SHOW_DIAL "showDial"
66
#define UI_STATE_TABBED_FIXTURES  0
67
#define UI_STATE_ALL_FIXTURES     1
68

69
SceneEditor::SceneEditor(QWidget* parent, Scene* scene, Doc* doc, bool applyValues)
×
70
    : QWidget(parent)
71
    , m_doc(doc)
×
72
    , m_scene(scene)
×
73
    , m_source(NULL)
×
74
    , m_initFinished(false)
×
75
    , m_speedDials(NULL)
×
76
    , m_channelGroupsTab(-1)
×
77
    , m_currentTab(KTabGeneral)
×
78
    , m_fixtureFirstTabIndex(1)
×
79
    , m_copyFromSelection(false)
×
80
{
81
    qDebug() << Q_FUNC_INFO;
×
82

83
    Q_ASSERT(doc != NULL);
×
84
    Q_ASSERT(scene != NULL);
×
85

86
    setupUi(this);
×
87

88
    init(applyValues);
×
89

90
    // Start new (==empty) scenes from the first tab and ones with something in them
91
    // on the first fixture page.
92
    if (m_tab->count() == 0)
×
93
        slotTabChanged(KTabGeneral);
×
94
    else
95
    {
96
        QVariant tabIndex = scene->uiStateValue(UI_STATE_TAB_INDEX);
×
97
        if (tabIndex.isValid())
×
98
            m_tab->setCurrentIndex(tabIndex.toInt());
×
99
        else
100
            m_tab->setCurrentIndex(0);
×
101
    }
×
102

103
    QVariant showDial = scene->uiStateValue(UI_STATE_SHOW_DIAL);
×
104
    if (showDial.isNull() == false && showDial.toBool() == true)
×
105
        m_speedDialAction->setChecked(true);
×
106

107
    connect(m_doc, SIGNAL(fixtureRemoved(quint32)), this, SLOT(slotFixtureRemoved(quint32)));
×
108

109
    m_initFinished = true;
×
110

111
    // Set focus to the editor
112
    m_nameEdit->setFocus();
×
113
}
×
114

115
SceneEditor::~SceneEditor()
×
116
{
117
    qDebug() << Q_FUNC_INFO;
×
118

119
    delete m_source;
×
120

121
    QSettings settings;
×
122
    quint32 id = m_chaserCombo->itemData(m_chaserCombo->currentIndex()).toUInt();
×
123
    settings.setValue(SETTINGS_CHASER, id);
×
124
}
×
125

126
void SceneEditor::slotFunctionManagerActive(bool active)
×
127
{
128
    qDebug() << Q_FUNC_INFO;
×
129

130
    if (active == true)
×
131
    {
132
        if (m_speedDialAction->isChecked() && m_speedDials == NULL)
×
133
            createSpeedDials();
×
134
    }
135
    else
136
    {
137
        if (m_speedDials != NULL)
×
138
            m_speedDials->deleteLater();
×
139
        m_speedDials = NULL;
×
140
    }
141
}
×
142

143
void SceneEditor::slotSetSceneValues(QList <SceneValue>&sceneValues)
×
144
{
145
    QListIterator <SceneValue> it(sceneValues);
×
146

147
    while (it.hasNext() == true)
×
148
    {
149
        SceneValue sv(it.next());
×
150

151
        Fixture *fixture = m_doc->fixture(sv.fxi);
×
152
        Q_ASSERT(fixture != NULL);
×
153

154
        FixtureConsole *fc = fixtureConsole(fixture);
×
155
        if (fc != NULL)
×
156
            fc->setSceneValue(sv);
×
157
    }
×
158
}
×
159

160
void SceneEditor::slotFixtureRemoved(quint32 id)
×
161
{
162
    removeFixtureTab(id);
×
163
    removeFixtureItem(id);
×
164

165
    QListIterator <SceneValue> it(m_scene->values());
×
166

167
    while (it.hasNext() == true)
×
168
    {
169
        SceneValue sv(it.next());
×
170
        if (sv.fxi == id)
×
171
            m_scene->unsetValue(id, sv.channel);
×
172
    }
×
173
    m_scene->removeFixture(id);
×
174
}
×
175

176
void SceneEditor::init(bool applyValues)
×
177
{
178
    QVariant tabMode = m_scene->uiStateValue(UI_STATE_TAB_MODE);
×
179

180
    this->layout()->setContentsMargins(8, 3, 8, 3);
×
181

182
    /* Actions */
183
    m_enableCurrentAction = new QAction(QIcon(":/check.png"),
×
184
                                        tr("Enable all channels in current fixture"), this);
×
185
    m_disableCurrentAction = new QAction(QIcon(":/uncheck.png"),
×
186
                                         tr("Disable all channels in current fixture"), this);
×
187
    m_copyAction = new QAction(QIcon(":/editcopy.png"),
×
188
                               tr("Copy current values to clipboard"), this);
×
189
    m_pasteAction = new QAction(QIcon(":/editpaste.png"),
×
190
                                tr("Paste clipboard values to current fixture"), this);
×
191
    m_copyToAllAction = new QAction(QIcon(":/editcopyall.png"),
×
192
                                    tr("Copy current values to all fixtures"), this);
×
193
    m_colorToolAction = new QAction(QIcon(":/color.png"),
×
194
                                    tr("Color tool for CMY/RGB-capable fixtures"), this);
×
195
    m_positionToolAction = new QAction(QIcon(":/xypad.png"),
×
196
                                    tr("Position tool for moving heads/scanners"), this);
×
197
    m_tabViewAction = new QAction(QIcon(":/tabview.png"),
×
198
                                    tr("Switch between tab view and all channels view"), this);
×
199
    m_blindAction = new QAction(QIcon(":/blind.png"),
×
200
                                tr("Toggle blind mode"), this);
×
201
    m_speedDialAction = new QAction(QIcon(":/speed.png"),
×
202
                                    tr("Show/Hide speed dial window"), this);
×
203
    m_recordAction = new QAction(QIcon(":/record.png"),
×
204
                                 tr("Clone this scene and append as a new step to the selected chaser"), this);
×
205

206
    m_nextTabAction = new QAction(QIcon(":/forward.png"), tr("Go to next fixture tab"), this);
×
207
    m_nextTabAction->setShortcut(QKeySequence("Alt+Right"));
×
208
    connect(m_nextTabAction, SIGNAL(triggered(bool)),
×
209
            this, SLOT(slotGoToNextTab()));
210
    m_prevTabAction = new QAction(QIcon(":/back.png"), tr("Go to previous fixture tab"), this);
×
211
    m_prevTabAction->setShortcut(QKeySequence("Alt+Left"));
×
212
    connect(m_prevTabAction, SIGNAL(triggered(bool)),
×
213
            this, SLOT(slotGoToPreviousTab()));
214

215
    // Speed Dial initial state
216
    m_speedDialAction->setCheckable(true);
×
217

218
    // Blind initial state
219
    m_blindAction->setCheckable(true);
×
220

221
    m_tabViewAction->setCheckable(true);
×
222
    if (tabMode.isNull() || tabMode.toInt() == UI_STATE_TABBED_FIXTURES)
×
223
        m_tabViewAction->setChecked(true);
×
224

225
    // Chaser combo init
226
    quint32 selectId = Function::invalidId();
×
227
    QSettings settings;
×
228
    QVariant var = settings.value(SETTINGS_CHASER);
×
229
    if (var.isValid() == true)
×
230
        selectId = var.toUInt();
×
231
    m_chaserCombo = new QComboBox(this);
×
232
    m_chaserCombo->setMaximumWidth(250);
×
233
    m_chaserCombo->addItem(tr("None"), Function::invalidId());
×
234
    slotChaserComboActivated(0);
×
235
    foreach (Function *function, m_doc->functionsByType(Function::ChaserType))
×
236
    {
237
        m_chaserCombo->addItem(function->name(), function->id());
×
238
        if (function->id() == selectId)
×
239
        {
240
            int index = m_chaserCombo->count() - 1;
×
241
            m_chaserCombo->setCurrentIndex(index);
×
242
            slotChaserComboActivated(index);
×
243
        }
244
    }
×
245
    QLabel *nameLabel = new QLabel(tr("Scene name:"));
×
246
    m_nameEdit = new QLineEdit();
×
247

248
    // Connections
249
    connect(m_enableCurrentAction, SIGNAL(triggered(bool)),
×
250
            this, SLOT(slotEnableCurrent()));
251
    connect(m_disableCurrentAction, SIGNAL(triggered(bool)),
×
252
            this, SLOT(slotDisableCurrent()));
253
    connect(m_copyAction, SIGNAL(triggered(bool)),
×
254
            this, SLOT(slotCopy()));
255
    connect(m_pasteAction, SIGNAL(triggered(bool)),
×
256
            this, SLOT(slotPaste()));
257
    connect(m_copyToAllAction, SIGNAL(triggered(bool)),
×
258
            this, SLOT(slotCopyToAll()));
259
    connect(m_colorToolAction, SIGNAL(triggered(bool)),
×
260
            this, SLOT(slotColorTool()));
261
    connect(m_positionToolAction, SIGNAL(triggered(bool)),
×
262
            this, SLOT(slotPositionTool()));
263
    connect(m_speedDialAction, SIGNAL(toggled(bool)),
×
264
            this, SLOT(slotSpeedDialToggle(bool)));
265
    connect(m_tabViewAction, SIGNAL(toggled(bool)),
×
266
            this, SLOT(slotViewModeChanged(bool)));
267
    connect(m_blindAction, SIGNAL(toggled(bool)),
×
268
            this, SLOT(slotBlindToggled(bool)));
269
    connect(m_recordAction, SIGNAL(triggered(bool)),
×
270
            this, SLOT(slotRecord()));
271
    connect(m_chaserCombo, SIGNAL(activated(int)),
×
272
            this, SLOT(slotChaserComboActivated(int)));
273
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)),
×
274
            this, SLOT(slotModeChanged(Doc::Mode)));
275

276
    /* Toolbar */
277
    QToolBar* toolBar = new QToolBar(this);
×
278
    layout()->setMenuBar(toolBar);
×
279
    toolBar->addAction(m_enableCurrentAction);
×
280
    toolBar->addAction(m_disableCurrentAction);
×
281
    toolBar->addSeparator();
×
282
    toolBar->addAction(m_prevTabAction);
×
283
    toolBar->addAction(m_nextTabAction);
×
284
    toolBar->addSeparator();
×
285
    toolBar->addAction(m_copyAction);
×
286
    toolBar->addAction(m_pasteAction);
×
287
    toolBar->addAction(m_copyToAllAction);
×
288
    toolBar->addSeparator();
×
289
    toolBar->addAction(m_colorToolAction);
×
290
    toolBar->addAction(m_positionToolAction);
×
291
    toolBar->addSeparator();
×
292
    toolBar->addAction(m_speedDialAction);
×
293
    toolBar->addAction(m_tabViewAction);
×
294
    toolBar->addSeparator();
×
295
    toolBar->addAction(m_blindAction);
×
296
    toolBar->addSeparator();
×
297
    toolBar->addAction(m_recordAction);
×
298
    toolBar->addWidget(m_chaserCombo);
×
299
    toolBar->addSeparator();
×
300
    toolBar->addWidget(nameLabel);
×
301
    toolBar->addWidget(m_nameEdit);
×
302

303
    /* Tab widget */
304
    connect(m_tab, SIGNAL(currentChanged(int)),
×
305
            this, SLOT(slotTabChanged(int)));
306

307
    /* Add & remove buttons */
308
    connect(m_addFixtureButton, SIGNAL(clicked()),
×
309
            this, SLOT(slotAddFixtureClicked()));
310
    connect(m_removeFixtureButton, SIGNAL(clicked()),
×
311
            this, SLOT(slotRemoveFixtureClicked()));
NEW
312
    connect(m_moveFixtureUpButton, SIGNAL(clicked()),
×
313
            this, SLOT(slotMoveFixtureUpClicked()));
NEW
314
    connect(m_moveFixtureDownButton, SIGNAL(clicked()),
×
315
            this, SLOT(slotMoveFixtureDownClicked()));
316

317
    m_nameEdit->setText(m_scene->name());
×
318
    m_nameEdit->setSelection(0, m_nameEdit->text().length());
×
319
    connect(m_nameEdit, SIGNAL(textEdited(const QString&)),
×
320
            this, SLOT(slotNameEdited(const QString&)));
321

322
    // Channels groups tab
323
    QList<quint32> chGrpIds = m_scene->channelGroups();
×
324
    QListIterator <ChannelsGroup*> scg(m_doc->channelsGroups());
×
325
    while (scg.hasNext() == true)
×
326
    {
327
        QTreeWidgetItem* item = new QTreeWidgetItem(m_channelGroupsTree);
×
328
        ChannelsGroup *grp = scg.next();
×
329
        item->setText(KColumnName, grp->name());
×
330
        item->setData(KColumnName, Qt::UserRole, grp->id());
×
331

332
        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
×
333
        if (chGrpIds.contains(grp->id()))
×
334
            item->setCheckState(KColumnName, Qt::Checked);
×
335
        else
336
            item->setCheckState(KColumnName, Qt::Unchecked);
×
337
    }
338
    connect(m_channelGroupsTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
×
339
            this, SLOT(slotChannelGroupsChanged(QTreeWidgetItem*,int)));
340
    connect(m_enableChannelsButton, SIGNAL(clicked()),
×
341
            this, SLOT(slotEnableAll()));
342
    connect(m_disableChannelsButton, SIGNAL(clicked()),
×
343
            this, SLOT(slotDisableAll()));
344
    connect(m_selectAllGroups, SIGNAL(clicked()),
×
345
            this, SLOT(slotEnableAllChannelGroups()));
346
    connect(m_deselectAllGroups, SIGNAL(clicked()),
×
347
            this, SLOT(slotDisableAllChannelGroups()));
348
    updateChannelsGroupsTab();
×
349

350
    // Apply any mode related change
351
    slotModeChanged(m_doc->mode());
×
352

353
    // Fixtures & tabs
354
    // Fill the fixtures list from the Scene fixtures
355
    foreach (quint32 fixtureID, m_scene->fixtures())
×
356
    {
357
        if (fixtureItem(fixtureID) == NULL)
×
358
        {
359
            Fixture* fixture = m_doc->fixture(fixtureID);
×
360
            if (fixture == NULL)
×
361
                continue;
×
362
            addFixtureItem(fixture);
×
363
        }
364
    }
×
365

366
    // Complete the fixtures list from the Scene values
367
    // (This should be useless)
368
    QListIterator <SceneValue> it(m_scene->values());
×
369
    while (it.hasNext() == true)
×
370
    {
371
        SceneValue scv(it.next());
×
372

373
        if (fixtureItem(scv.fxi) == NULL)
×
374
        {
375
            qWarning() << Q_FUNC_INFO
×
376
                << "Fixture" << scv.fxi << "was not in the scene fixture list!";
×
377
            Fixture* fixture = m_doc->fixture(scv.fxi);
×
378
            if (fixture == NULL)
×
379
                continue;
×
380

381
            addFixtureItem(fixture);
×
382
        }
383
    }
×
384

385
    // Create the actual tab view
386
    if (tabMode.isNull() || tabMode.toInt() == UI_STATE_TABBED_FIXTURES)
×
387
        slotViewModeChanged(true, applyValues);
×
388
    else
389
        slotViewModeChanged(false, applyValues);
×
390
}
×
391

392
void SceneEditor::setSceneValue(const SceneValue& scv)
×
393
{
394
    FixtureConsole* fc;
395
    Fixture* fixture;
396

397
    fixture = m_doc->fixture(scv.fxi);
×
398
    Q_ASSERT(fixture != NULL);
×
399

400
    fc = fixtureConsole(fixture);
×
401
    if (fc != NULL)
×
402
        fc->setSceneValue(scv);
×
403
}
×
404

405

406
void SceneEditor::setBlindModeEnabled(bool active)
×
407
{
408
    m_blindAction->setChecked(active);
×
409
}
×
410

411
/*****************************************************************************
412
 * Common
413
 *****************************************************************************/
414

415
void SceneEditor::slotTabChanged(int tab)
×
416
{
417
    m_currentTab = tab;
×
418
    QLCClipboard *clipboard = m_doc->clipboard();
×
419

420
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, tab);
×
421

422
    if (tab == KTabGeneral)
×
423
    {
424
        m_enableCurrentAction->setEnabled(false);
×
425
        m_disableCurrentAction->setEnabled(false);
×
426

427
        m_copyAction->setEnabled(false);
×
428
        m_pasteAction->setEnabled(false);
×
429
        m_copyToAllAction->setEnabled(false);
×
430
        m_colorToolAction->setEnabled(false);
×
431
    }
432
    else
433
    {
434
        m_enableCurrentAction->setEnabled(true);
×
435
        m_disableCurrentAction->setEnabled(true);
×
436

437
        m_copyAction->setEnabled(true);
×
438
        if (clipboard->hasSceneValues())
×
439
            m_pasteAction->setEnabled(true);
×
440
        else
441
            m_pasteAction->setEnabled(false);
×
442

443
        if (m_tabViewAction->isChecked())
×
444
            m_copyToAllAction->setEnabled(true);
×
445
        else
446
            m_copyToAllAction->setEnabled(false);
×
447
        m_colorToolAction->setEnabled(isColorToolAvailable());
×
448
        m_positionToolAction->setEnabled(isPositionToolAvailable());
×
449
    }
450
}
×
451

452
void SceneEditor::slotEnableCurrent()
×
453
{
454
    if (m_tabViewAction->isChecked())
×
455
    {
456
        /* QObject cast fails unless the widget is a FixtureConsole */
457
        FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
458
        if (fc != NULL)
×
459
            fc->setChecked(true);
×
460
    }
461
    else
462
    {
463
        foreach (FixtureConsole *fc, m_consoleList)
×
464
        {
465
            if (fc == NULL)
×
466
                continue;
×
467
            fc->setChecked(true);
×
468
        }
×
469
    }
470
}
×
471

472
void SceneEditor::slotDisableCurrent()
×
473
{
474
    if (m_tabViewAction->isChecked())
×
475
    {
476
        /* QObject cast fails unless the widget is a FixtureConsole */
477
        FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
478
        if (fc != NULL)
×
479
            fc->setChecked(false);
×
480
    }
481
    else
482
    {
483
        foreach (FixtureConsole *fc, m_consoleList)
×
484
        {
485
            if (fc == NULL)
×
486
                continue;
×
487
            fc->setChecked(false);
×
488
        }
×
489
    }
490
}
×
491

492
void SceneEditor::slotCopy()
×
493
{
494
    QList <SceneValue> copyList;
×
495
    QLCClipboard *clipboard = m_doc->clipboard();
×
496

497
    /* QObject cast fails unless the widget is a FixtureConsole */
498
    if (m_tabViewAction->isChecked())
×
499
    {
500
        FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
501
        if (fc != NULL)
×
502
        {
503
            copyList = fc->values();
×
504
            m_copyFromSelection = fc->hasSelections();
×
505
            clipboard->copyContent(m_scene->id(), copyList);
×
506
        }
507
    }
508
    else
509
    {
510
        bool oneHasSelection = false;
×
511
        QList <SceneValue> selectedOnlyList;
×
512
        foreach (FixtureConsole *fc, m_consoleList)
×
513
        {
514
            if (fc == NULL)
×
515
                continue;
×
516
            copyList.append(fc->values());
×
517
            if (fc->hasSelections())
×
518
            {
519
                oneHasSelection = true;
×
520
                selectedOnlyList.append(fc->values());
×
521
            }
522
        }
×
523
        m_copyFromSelection = oneHasSelection;
×
524
        if (m_copyFromSelection == true)
×
525
            clipboard->copyContent(m_scene->id(), selectedOnlyList);
×
526
        else
527
            clipboard->copyContent(m_scene->id(), copyList);
×
528
    }
×
529
    if (copyList.count() > 0)
×
530
        m_pasteAction->setEnabled(true);
×
531
}
×
532

533
void SceneEditor::slotPaste()
×
534
{
535
    QLCClipboard *clipboard = m_doc->clipboard();
×
536

537
    if (clipboard->hasSceneValues() == false)
×
538
        return;
×
539

540
    if (m_tabViewAction->isChecked())
×
541
    {
542
        FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
543
        if (fc != NULL)
×
544
            fc->setValues(clipboard->getSceneValues(), m_copyFromSelection);
×
545
    }
546
    else
547
    {
548
        foreach (FixtureConsole *fc, m_consoleList)
×
549
        {
550
            if (fc == NULL)
×
551
                continue;
×
552
            quint32 fxi = fc->fixture();
×
553
            QList<SceneValue>thisFixtureVals;
×
554
            foreach (SceneValue val, clipboard->getSceneValues())
×
555
            {
556
                if (val.fxi == fxi)
×
557
                    thisFixtureVals.append(val);
×
558
            }
×
559
            fc->setValues(thisFixtureVals, m_copyFromSelection);
×
560
        }
×
561
    }
562
}
563

564
void SceneEditor::slotCopyToAll()
×
565
{
566
    slotCopy();
×
567

568
    QLCClipboard *clipboard = m_doc->clipboard();
×
569

570
    if (clipboard->hasSceneValues())
×
571
    {
572
        for (int i = m_fixtureFirstTabIndex; i < m_tab->count(); i++)
×
573
        {
574
            FixtureConsole* fc = fixtureConsoleTab(i);
×
575
            if (fc != NULL)
×
576
                fc->setValues(clipboard->getSceneValues(), m_copyFromSelection);
×
577
        }
578
    }
579

580
    //m_copy.clear();
581
    m_pasteAction->setEnabled(false);
×
582
}
×
583

584
void SceneEditor::slotColorTool()
×
585
{
586
    QColor color = slotColorSelectorChanged(QColor());
×
587

588
    QColorDialog dialog(color, this);
×
589
    connect(&dialog, SIGNAL(currentColorChanged(const QColor&)),
×
590
            this, SLOT(slotColorSelectorChanged(const QColor&)));
591

592
    int result = dialog.exec();
×
593
    if (result == QDialog::Rejected)
×
594
    {
595
        slotColorSelectorChanged(color); // reset color to what it previously was
×
596
    }
597
}
×
598

599
void SceneEditor::slotPositionTool()
×
600
{
601
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
602
    if (fc != NULL)
×
603
    {
604
        QList<SceneValue> origValues = fc->values();
×
605

606
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
607
        QPointF pos;
×
608
        QRectF range;
×
609
        bool panFound = false;
×
610
        bool tiltFound = false;
×
611

612
        Q_ASSERT(fxi != NULL);
×
613

614
        for (int i = 0; i < fxi->heads(); ++i)
×
615
        {
616
             if (!range.isValid())
×
617
                 range = fxi->degreesRange(i);
×
618

619
             quint32 panMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i);
×
620
             quint32 panLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, i);
×
621
             quint32 tiltMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i);
×
622
             quint32 tiltLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, i);
×
623

624
             if (panMsbChannel != QLCChannel::invalid())
×
625
             {
626
                 if (!panFound)
×
627
                 {
628
                     qDebug() << "panFound" << i;
×
629
                     panFound = true;
×
630
                     qreal v = qreal(fc->value(panMsbChannel));
×
631
                     if (panLsbChannel != QLCChannel::invalid())
×
632
                     {
633
                        v += qreal(fc->value(panLsbChannel)) / qreal(256);
×
634
                     }
635

636
                     pos.setX(v);
×
637
                 }
638
             }
639

640
             if (tiltMsbChannel != QLCChannel::invalid())
×
641
             {
642
                 if (!tiltFound)
×
643
                 {
644
                     tiltFound = true;
×
645
                     qDebug() << "tiltFound" << i;
×
646
                     qreal v = qreal(fc->value(tiltMsbChannel));
×
647
                     if (tiltLsbChannel != QLCChannel::invalid())
×
648
                     {
649
                        v += qreal(fc->value(tiltLsbChannel)) / qreal(256);
×
650
                     }
651

652
                     pos.setY(v);
×
653
                 }
654
             }
655
        }
656

657
        PositionTool dialog(pos, range);
×
658
        connect(&dialog, SIGNAL(currentPositionChanged(const QPointF&)),
×
659
            this, SLOT(slotPositionSelectorChanged(const QPointF&)));
660

661
        int result = dialog.exec();
×
662
        if (result == QDialog::Rejected)
×
663
        {
664
            fc->setValues(origValues, false); // reset position to what it previously was
×
665
        }
666
    }
×
667
}
×
668

669
QColor SceneEditor::slotColorSelectorChanged(const QColor& color)
×
670
{
671
    QColor returnColor = QColor();
×
672

673
    /* QObject cast fails unless the widget is a FixtureConsole */
674
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
675
    if (fc != NULL)
×
676
    {
677
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
678
        Q_ASSERT(fxi != NULL);
×
679

680
        QSet <quint32> cyan    = fxi->channels(QLCChannel::Intensity, QLCChannel::Cyan);
×
681
        QSet <quint32> magenta = fxi->channels(QLCChannel::Intensity, QLCChannel::Magenta);
×
682
        QSet <quint32> yellow  = fxi->channels(QLCChannel::Intensity, QLCChannel::Yellow);
×
683
        QSet <quint32> red     = fxi->channels(QLCChannel::Intensity, QLCChannel::Red);
×
684
        QSet <quint32> green   = fxi->channels(QLCChannel::Intensity, QLCChannel::Green);
×
685
        QSet <quint32> blue    = fxi->channels(QLCChannel::Intensity, QLCChannel::Blue);
×
686

687
        if (!cyan.isEmpty() && !magenta.isEmpty() && !yellow.isEmpty())
×
688
        {
689
            returnColor.setCmyk(fc->value(*cyan.begin()),
×
690
                                fc->value(*magenta.begin()),
×
691
                                fc->value(*yellow.begin()),
×
692
                                0);
693
            if (color.isValid() == true)
×
694
            {
695
                foreach (quint32 ch, cyan)
×
696
                {
697
                    fc->setChecked(true, ch);
×
698
                    fc->setValue(ch, color.cyan());
×
699
                }
×
700

701
                foreach (quint32 ch, magenta)
×
702
                {
703
                    fc->setChecked(true, ch);
×
704
                    fc->setValue(ch, color.magenta());
×
705
                }
×
706

707
                foreach (quint32 ch, yellow)
×
708
                {
709
                    fc->setChecked(true, ch);
×
710
                    fc->setValue(ch, color.yellow());
×
711
                }
×
712
            }
713
        }
714
        else if (!red.isEmpty() && !green.isEmpty() && !blue.isEmpty())
×
715
        {
716
            returnColor.setRgb(fc->value(*red.begin()),
×
717
                               fc->value(*green.begin()),
×
718
                               fc->value(*blue.begin()),
×
719
                               0);
720

721
            if (color.isValid() == true)
×
722
            {
723
                foreach (quint32 ch, red)
×
724
                {
725
                    fc->setChecked(true, ch);
×
726
                    fc->setValue(ch, color.red());
×
727
                }
×
728

729
                foreach (quint32 ch, green)
×
730
                {
731
                    fc->setChecked(true, ch);
×
732
                    fc->setValue(ch, color.green());
×
733
                }
×
734

735
                foreach (quint32 ch, blue)
×
736
                {
737
                    fc->setChecked(true, ch);
×
738
                    fc->setValue(ch, color.blue());
×
739
                }
×
740
            }
741
        }
742
        return returnColor;
×
743
    }
×
744

745
    /* QObject cast fails unless the widget is a GroupsConsole */
746
    GroupsConsole* gc = groupConsoleTab(m_currentTab);
×
747
    if (gc != NULL)
×
748
    {
749
        foreach (ConsoleChannel *cc, gc->groups())
×
750
        {
751
            Fixture* fxi = m_doc->fixture(cc->fixture());
×
752
            Q_ASSERT(fxi != NULL);
×
753
            const QLCChannel *ch = fxi->channel(cc->channelIndex());
×
754
            if (ch->group() == QLCChannel::Intensity)
×
755
            {
756
                if (ch->colour() == QLCChannel::Red)
×
757
                    cc->setValue(color.red());
×
758
                else if (ch->colour() == QLCChannel::Green)
×
759
                    cc->setValue(color.green());
×
760
                else if (ch->colour() == QLCChannel::Blue)
×
761
                    cc->setValue(color.blue());
×
762
                else if (ch->colour() == QLCChannel::Magenta)
×
763
                    cc->setValue(color.magenta());
×
764
                else if (ch->colour() == QLCChannel::Yellow)
×
765
                    cc->setValue(color.yellow());
×
766
                else if (ch->colour() == QLCChannel::Cyan)
×
767
                    cc->setValue(color.cyan());
×
768
            }
769
        }
×
770
    }
771

772
    return returnColor;
×
773
}
774

775
void SceneEditor::slotPositionSelectorChanged(const QPointF& position)
×
776
{
777
    qreal x = position.x();
×
778
    qreal y = position.y();
×
779

780
    uchar panMsbNew = x;
×
781
    uchar panLsbNew = (x - floor(x)) * 256;
×
782
    uchar tiltMsbNew = y;
×
783
    uchar tiltLsbNew = (y - floor(y)) * 256;
×
784

785
    /* QObject cast fails unless the widget is a FixtureConsole */
786
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
787
    if (fc != NULL)
×
788
    {
789
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
790
        Q_ASSERT(fxi != NULL);
×
791

792
        for (int i = 0; i < fxi->heads(); ++i)
×
793
        {
794
             quint32 panMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i);
×
795
             quint32 panLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, i);
×
796
             quint32 tiltMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i);
×
797
             quint32 tiltLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, i);
×
798

799
             if (panMsbChannel != QLCChannel::invalid())
×
800
             {
801
                 fc->setChecked(true, panMsbChannel);
×
802
                 fc->setValue(panMsbChannel, panMsbNew);
×
803

804
                 if (panLsbChannel != QLCChannel::invalid())
×
805
                 {
806
                     fc->setChecked(true, panLsbChannel);
×
807
                     fc->setValue(panLsbChannel, panLsbNew);
×
808
                 }
809
             }
810

811
             if (tiltMsbChannel != QLCChannel::invalid())
×
812
             {
813
                 fc->setChecked(true, tiltMsbChannel);
×
814
                 fc->setValue(tiltMsbChannel, tiltMsbNew);
×
815

816
                 if (tiltLsbChannel != QLCChannel::invalid())
×
817
                 {
818
                     fc->setChecked(true, tiltLsbChannel);
×
819
                     fc->setValue(tiltLsbChannel, tiltLsbNew);
×
820
                 }
821
             }
822
        }
823
    }
824

825
    /* QObject cast fails unless the widget is a GroupsConsole */
826
    GroupsConsole* gc = groupConsoleTab(m_currentTab);
×
827
    if (gc != NULL)
×
828
    {
829
        foreach (ConsoleChannel *cc, gc->groups())
×
830
        {
831
            Fixture* fxi = m_doc->fixture(cc->fixture());
×
832
            Q_ASSERT(fxi != NULL);
×
833
            const QLCChannel *ch = fxi->channel(cc->channelIndex());
×
834
            if (ch->group() == QLCChannel::Pan)
×
835
            {
836
                if (ch->controlByte() == QLCChannel::MSB)
×
837
                    cc->setValue(panMsbNew);
×
838
                else
839
                    cc->setValue(panLsbNew);
×
840
            }
841
            else if (ch->group() == QLCChannel::Tilt)
×
842
            {
843
                if (ch->controlByte() == QLCChannel::MSB)
×
844
                    cc->setValue(tiltMsbNew);
×
845
                else
846
                    cc->setValue(tiltLsbNew);
×
847
            }
848
        }
×
849
    }
850
}
×
851

852
void SceneEditor::slotSpeedDialToggle(bool state)
×
853
{
854
    if (state == true)
×
855
    {
856
        createSpeedDials();
×
857
    }
858
    else
859
    {
860
        if (m_speedDials != NULL)
×
861
            m_speedDials->deleteLater();
×
862
        m_speedDials = NULL;
×
863
    }
864

865
    m_scene->setUiStateValue(UI_STATE_SHOW_DIAL, state);
×
866
}
×
867

868
void SceneEditor::slotBlindToggled(bool state)
×
869
{
870
    if (m_doc->mode() == Doc::Operate)
×
871
    {
872
        delete m_source;
×
873
        m_source = NULL;
×
874

875
        if (m_scene != NULL && !m_scene->isRunning())
×
876
        {
877
            m_source = new GenericDMXSource(m_doc);
×
878
            foreach (SceneValue scv, m_scene->values())
×
879
                m_source->set(scv.fxi, scv.channel, scv.value);
×
880
        }
881
    }
882
    else
883
    {
884
        if (m_source == NULL)
×
885
            m_source = new GenericDMXSource(m_doc);
×
886
    }
887

888
    if (m_source != NULL)
×
889
        m_source->setOutputEnabled(!state);
×
890
}
×
891

892
void SceneEditor::slotModeChanged(Doc::Mode mode)
×
893
{
894
    if (mode == Doc::Operate)
×
895
    {
896
        m_blindAction->setChecked(true);
×
897
        slotBlindToggled(true);
×
898
    }
899
    else
900
    {
901
        m_blindAction->setChecked(false);
×
902
        slotBlindToggled(false);
×
903
    }
904

905
}
×
906

907
void SceneEditor::slotViewModeChanged(bool tabbed, bool applyValues)
×
908
{
909
    m_tab->blockSignals(true);
×
910
    for (int i = m_tab->count() - 1; i >= m_fixtureFirstTabIndex; i--)
×
911
    {
912
        QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(i));
×
913
        Q_ASSERT(area != NULL);
×
914
        m_tab->removeTab(i);
×
915
        delete area; // Deletes also FixtureConsole
×
916
    }
917
    m_consoleList.clear();
×
918
    m_tab->blockSignals(false);
×
919

920
    // all fixtures view mode
921
    if (tabbed == false)
×
922
    {
923
        QListIterator <Fixture*> it(selectedFixtures());
×
924
        if (it.hasNext() == true)
×
925
        {
926
            QScrollArea* scrollArea = new QScrollArea(m_tab);
×
927

928
            scrollArea->setWidgetResizable(true);
×
929
            int tIdx = m_tab->addTab(scrollArea, tr("All fixtures"));
×
930
            m_tab->setTabToolTip(tIdx, tr("All fixtures"));
×
931

932
            QGroupBox* grpBox = new QGroupBox(scrollArea);
×
933
            grpBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
×
934
            QHBoxLayout* fixturesLayout = new QHBoxLayout(grpBox);
×
935
            grpBox->setLayout(fixturesLayout);
×
936
            fixturesLayout->setSpacing(2);
×
937
            fixturesLayout->setContentsMargins(0, 2, 2, 2);
×
938

939
            int c = 0;
×
940
            while (it.hasNext() == true)
×
941
            {
942
                Fixture* fixture = it.next();
×
943
                Q_ASSERT(fixture != NULL);
×
944
                FixtureConsole* console = NULL;
×
945
                if (c%2 == 0)
×
946
                    console = new FixtureConsole(scrollArea, m_doc, FixtureConsole::GroupOdd);
×
947
                else
948
                    console = new FixtureConsole(scrollArea, m_doc, FixtureConsole::GroupEven);
×
949
                console->setFixture(fixture->id());
×
950
                console->setChecked(false);
×
951
                m_consoleList[fixture->id()] = console;
×
952

953
                connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
954
                        this, SLOT(slotValueChanged(quint32,quint32,uchar)));
955
                connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
956
                        this, SLOT(slotChecked(quint32,quint32,bool)));
957

958
                QListIterator <SceneValue> it(m_scene->values());
×
959
                while (it.hasNext() == true)
×
960
                {
961
                    SceneValue scv(it.next());
×
962
                    if (applyValues == false)
×
963
                        scv.value = 0;
×
964
                    if (scv.fxi == fixture->id())
×
965
                        console->setSceneValue(scv);
×
966
                }
×
967

968
                fixturesLayout->addWidget(console);
×
969
                c++;
×
970
            }
×
971
            fixturesLayout->addStretch(1);
×
972
            scrollArea->setWidget(grpBox);
×
973
        }
974
    }
×
975
    // tabbed fixtures view mode
976
    else
977
    {
978
        QListIterator <Fixture*> it(selectedFixtures());
×
979
        while (it.hasNext() == true)
×
980
        {
981
            Fixture* fixture = it.next();
×
982
            Q_ASSERT(fixture != NULL);
×
983

984
            addFixtureTab(fixture);
×
985

986
            QListIterator <SceneValue> it(m_scene->values());
×
987
            while (it.hasNext() == true)
×
988
            {
989
                SceneValue scv(it.next());
×
990
                if (applyValues == false)
×
991
                    scv.value = 0;
×
992
                if (scv.fxi == fixture->id())
×
993
                    setSceneValue(scv);
×
994
            }
×
995
        }
×
996
    }
×
997

998
    m_scene->setUiStateValue(UI_STATE_TAB_MODE, tabbed ? UI_STATE_TABBED_FIXTURES : UI_STATE_ALL_FIXTURES);
×
999

1000
    if (m_tab->count() == 0)
×
1001
    {
1002
        slotTabChanged(KTabGeneral);
×
1003
    }
1004
    else
1005
    {
1006
        QVariant tabIndex = m_scene->uiStateValue(UI_STATE_TAB_INDEX);
×
1007
        int prevTabIdx = tabIndex.isValid() ? tabIndex.toInt() : 0;
×
1008
        if (prevTabIdx > m_tab->count())
×
1009
            m_tab->setCurrentIndex(m_fixtureFirstTabIndex);
×
1010
        else
1011
            m_tab->setCurrentIndex(prevTabIdx);
×
1012
    }
×
1013

1014
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, m_tab->currentIndex());
×
1015
}
×
1016

1017
void SceneEditor::slotRecord()
×
1018
{
1019
    Chaser* chaser = selectedChaser();
×
1020
    if (chaser == NULL)
×
1021
        return;
×
1022

1023
    QString name = chaser->name() + QString(" - %1").arg(chaser->steps().size() + 1);
×
1024
    Scene* clone = new Scene(m_doc);
×
1025
    clone->copyFrom(m_scene);
×
1026
    clone->setName(name);
×
1027
    m_doc->addFunction(clone);
×
1028
    chaser->addStep(ChaserStep(clone->id()));
×
1029

1030
    // Switch to the cloned scene
1031
    FunctionManager::instance()->selectFunction(clone->id());
×
1032
}
×
1033

1034
void SceneEditor::slotChaserComboActivated(int index)
×
1035
{
1036
    quint32 id = m_chaserCombo->itemData(index).toUInt();
×
1037
    if (id == Function::invalidId())
×
1038
        m_recordAction->setEnabled(false);
×
1039
    else
1040
        m_recordAction->setEnabled(true);
×
1041
}
×
1042

1043
bool SceneEditor::isColorToolAvailable() const
×
1044
{
1045
    Fixture* fxi = NULL;
×
1046
    quint32 cyan = QLCChannel::invalid(), magenta = QLCChannel::invalid(), yellow = QLCChannel::invalid();
×
1047
    quint32 red = QLCChannel::invalid(), green = QLCChannel::invalid(), blue = QLCChannel::invalid();
×
1048

1049
    /* QObject cast fails unless the widget is a FixtureConsole */
1050
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
1051
    if (fc != NULL)
×
1052
    {
1053
        fxi = m_doc->fixture(fc->fixture());
×
1054
        Q_ASSERT(fxi != NULL);
×
1055

1056
        cyan = fxi->channel(QLCChannel::Intensity, QLCChannel::Cyan);
×
1057
        magenta = fxi->channel(QLCChannel::Intensity, QLCChannel::Magenta);
×
1058
        yellow = fxi->channel(QLCChannel::Intensity, QLCChannel::Yellow);
×
1059
        red = fxi->channel(QLCChannel::Intensity, QLCChannel::Red);
×
1060
        green = fxi->channel(QLCChannel::Intensity, QLCChannel::Green);
×
1061
        blue = fxi->channel(QLCChannel::Intensity, QLCChannel::Blue);
×
1062
    }
1063

1064
    GroupsConsole* gc = groupConsoleTab(m_currentTab);
×
1065
    if (gc != NULL)
×
1066
    {
1067
        cyan = magenta = yellow = red = green = blue = QLCChannel::invalid();
×
1068
        foreach (ConsoleChannel *cc, gc->groups())
×
1069
        {
1070
            fxi = m_doc->fixture(cc->fixture());
×
1071
            Q_ASSERT(fxi != NULL);
×
1072
            const QLCChannel *ch = fxi->channel(cc->channelIndex());
×
1073
            if (ch->group() == QLCChannel::Intensity)
×
1074
            {
1075
                if (ch->colour() == QLCChannel::Red)
×
1076
                    red = 1;
×
1077
                else if (ch->colour() == QLCChannel::Green)
×
1078
                    green = 1;
×
1079
                else if (ch->colour() == QLCChannel::Blue)
×
1080
                    blue = 1;
×
1081
                else if (ch->colour() == QLCChannel::Magenta)
×
1082
                    magenta = 1;
×
1083
                else if (ch->colour() == QLCChannel::Yellow)
×
1084
                    yellow = 1;
×
1085
                else if (ch->colour() == QLCChannel::Cyan)
×
1086
                    cyan = 1;
×
1087
            }
1088
        }
×
1089
    }
1090

1091
    if (cyan != QLCChannel::invalid() && magenta != QLCChannel::invalid() &&
×
1092
        yellow != QLCChannel::invalid())
×
1093
    {
1094
        return true;
×
1095
    }
1096
    else if (red != QLCChannel::invalid() && green != QLCChannel::invalid() &&
×
1097
             blue != QLCChannel::invalid())
×
1098
    {
1099
        return true;
×
1100
    }
1101
    else
1102
    {
1103
        return false;
×
1104
    }
1105
}
1106

1107
bool SceneEditor::isPositionToolAvailable() const
×
1108
{
1109
    Fixture* fxi = NULL;
×
1110

1111
    /* QObject cast fails unless the widget is a FixtureConsole */
1112
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
1113
    if (fc != NULL)
×
1114
    {
1115
        fxi = m_doc->fixture(fc->fixture());
×
1116
        Q_ASSERT(fxi != NULL);
×
1117

1118
        for (int i = 0; i < fxi->heads(); ++i)
×
1119
        {
1120
            if (fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i) != QLCChannel::invalid())
×
1121
                return true;
×
1122
            if (fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i) != QLCChannel::invalid())
×
1123
                return true;
×
1124
        }
1125
    }
1126

1127
    GroupsConsole* gc = groupConsoleTab(m_currentTab);
×
1128
    if (gc != NULL)
×
1129
    {
1130
        foreach (ConsoleChannel *cc, gc->groups())
×
1131
        {
1132
            fxi = m_doc->fixture(cc->fixture());
×
1133
            Q_ASSERT(fxi != NULL);
×
1134
            const QLCChannel *ch = fxi->channel(cc->channelIndex());
×
1135
            if (ch->group() == QLCChannel::Pan || ch->group() == QLCChannel::Tilt)
×
1136
                return true;
×
1137
        }
×
1138
    }
1139

1140
    return false;
×
1141
}
1142

1143
void SceneEditor::createSpeedDials()
×
1144
{
1145
    if (m_speedDials != NULL)
×
1146
        return;
×
1147

1148
    m_speedDials = new SpeedDialWidget(this);
×
1149
    m_speedDials->setAttribute(Qt::WA_DeleteOnClose);
×
1150
    m_speedDials->setWindowTitle(m_scene->name());
×
1151
    m_speedDials->setFadeInSpeed(m_scene->fadeInSpeed());
×
1152
    m_speedDials->setFadeOutSpeed(m_scene->fadeOutSpeed());
×
1153
    m_speedDials->setDurationEnabled(false);
×
1154
    m_speedDials->setDurationVisible(false);
×
1155
    connect(m_speedDials, SIGNAL(fadeInChanged(int)), this, SLOT(slotFadeInChanged(int)));
×
1156
    connect(m_speedDials, SIGNAL(fadeOutChanged(int)), this, SLOT(slotFadeOutChanged(int)));
×
1157
    connect(m_speedDials, SIGNAL(destroyed(QObject*)), this, SLOT(slotDialDestroyed(QObject*)));
×
1158
    m_speedDials->show();
×
1159
}
1160

1161
void SceneEditor::slotDialDestroyed(QObject *)
×
1162
{
1163
    m_speedDialAction->setChecked(false);
×
1164
}
×
1165

1166
Chaser* SceneEditor::selectedChaser() const
×
1167
{
1168
    QVariant var = m_chaserCombo->itemData(m_chaserCombo->currentIndex());
×
1169
    if (var.isValid() == false)
×
1170
        return NULL;
×
1171
    else
1172
        return qobject_cast<Chaser*> (m_doc->function(var.toUInt()));
×
1173
}
×
1174

1175
/*****************************************************************************
1176
 * General page
1177
 *****************************************************************************/
1178

1179
QTreeWidgetItem* SceneEditor::fixtureItem(quint32 fxi_id)
×
1180
{
1181
    QTreeWidgetItemIterator it(m_tree);
×
1182
    while (*it != NULL)
×
1183
    {
1184
        QTreeWidgetItem* item = *it;
×
1185
        if (item->text(KColumnID).toUInt() == fxi_id)
×
1186
            return item;
×
1187
        ++it;
×
1188
    }
1189

1190
    return NULL;
×
1191
}
×
1192

1193
QList <Fixture*> SceneEditor::selectedFixtures() const
×
1194
{
1195
    QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
1196
    QList <Fixture*> list;
×
1197

1198
    while (it.hasNext() == true)
×
1199
    {
1200
        QTreeWidgetItem* item;
1201
        quint32 fxi_id;
1202
        Fixture* fixture;
1203

1204
        item = it.next();
×
1205
        fxi_id = item->text(KColumnID).toInt();
×
1206
        fixture = m_doc->fixture(fxi_id);
×
1207
        Q_ASSERT(fixture != NULL);
×
1208

1209
        list.append(fixture);
×
1210
    }
1211

1212
    return list;
×
1213
}
×
1214

1215
bool SceneEditor::addFixtureItem(Fixture* fixture)
×
1216
{
1217
    Q_ASSERT(fixture != NULL);
×
1218

1219
    // check if the fixture is already there
1220
    for (int i = 0; i < m_tree->topLevelItemCount(); i++)
×
1221
    {
1222
        QTreeWidgetItem *fix = m_tree->topLevelItem(i);
×
1223
        if (fix != NULL)
×
1224
        {
1225
            quint32 fxid = fix->text(KColumnID).toUInt();
×
1226
            if (fxid == fixture->id())
×
1227
                return false;
×
1228
        }
1229
    }
1230

1231
    QTreeWidgetItem* item;
1232

1233
    item = new QTreeWidgetItem(m_tree);
×
1234
    item->setText(KColumnName, fixture->name());
×
1235
    item->setText(KColumnID, QString("%1").arg(fixture->id()));
×
1236

1237
    if (fixture->fixtureDef() == NULL)
×
1238
    {
1239
        item->setText(KColumnManufacturer, tr("Generic"));
×
1240
        item->setText(KColumnModel, tr("Generic"));
×
1241
    }
1242
    else
1243
    {
1244
        item->setText(KColumnManufacturer,
×
1245
                      fixture->fixtureDef()->manufacturer());
×
1246
        item->setText(KColumnModel, fixture->fixtureDef()->model());
×
1247
    }
1248

1249
    /* Select newly-added fixtures so that their channels can be
1250
       quickly disabled/enabled */
1251
    item->setSelected(true);
×
1252

1253
    return true;
×
1254
}
1255

1256
void SceneEditor::removeFixtureItem(quint32 fixtureID)
×
1257
{
1258
    QTreeWidgetItem *item;
1259

1260
    item = fixtureItem(fixtureID);
×
1261
    delete item;
×
1262
}
×
1263

1264
void SceneEditor::slotNameEdited(const QString& name)
×
1265
{
1266
    m_scene->setName(name);
×
1267
    if (m_speedDials != NULL)
×
1268
        m_speedDials->setWindowTitle(m_scene->name());
×
1269
}
×
1270

1271
void SceneEditor::slotAddFixtureClicked()
×
1272
{
1273
    /* Put all fixtures already present into a list of fixtures that
1274
       will be disabled in the fixture selection dialog */
1275
    QList <quint32> disabled;
×
1276
    QTreeWidgetItemIterator twit(m_tree);
×
1277
    while (*twit != NULL)
×
1278
    {
1279
        disabled.append((*twit)->text(KColumnID).toInt());
×
1280
        twit++;
×
1281
    }
1282

1283
    /* Get a list of new fixtures to add to the scene */
1284
    FixtureSelection fs(this, m_doc);
×
1285
    fs.setMultiSelection(true);
×
1286
    fs.setDisabledFixtures(disabled);
×
1287
    if (fs.exec() == QDialog::Accepted)
×
1288
    {
1289
        QListIterator <quint32> it(fs.selection());
×
1290
        while (it.hasNext() == true)
×
1291
        {
1292
            Fixture *fixture = m_doc->fixture(it.next());
×
1293
            Q_ASSERT(fixture != NULL);
×
1294

1295
            if (!m_scene->fixtures().contains(fixture->id()))
×
1296
            {
1297
                addFixtureItem(fixture);
×
1298
                addFixtureTab(fixture);
×
1299

1300
                // Add fixture in scene
1301
                m_scene->addFixture(fixture->id());
×
1302
            }
1303
        }
1304
    }
×
1305
}
×
1306

1307
void SceneEditor::slotRemoveFixtureClicked()
×
1308
{
1309
    int r = QMessageBox::question(
×
1310
                this, tr("Remove fixtures"),
×
1311
                tr("Do you want to remove the selected fixture(s)?"),
×
1312
                QMessageBox::Yes, QMessageBox::No);
1313

1314
    if (r == QMessageBox::Yes)
×
1315
    {
1316
        QListIterator <Fixture*> it(selectedFixtures());
×
1317
        while (it.hasNext() == true)
×
1318
        {
1319
            Fixture* fixture = it.next();
×
1320
            Q_ASSERT(fixture != NULL);
×
1321

1322
            removeFixtureTab(fixture->id());
×
1323
            removeFixtureItem(fixture->id());
×
1324

1325
            /* Remove all values associated to the fixture */
1326
            for (quint32 i = 0; i < fixture->channels(); i++)
×
1327
                m_scene->unsetValue(fixture->id(), i);
×
1328

1329
            // Remove fixture from scene
1330
            m_scene->removeFixture(fixture->id());
×
1331
        }
1332
    }
×
1333
}
×
1334

NEW
1335
void SceneEditor::moveFixture(int offset)
×
1336
{
NEW
1337
    if ((m_tree == NULL) || (m_scene == NULL) || (offset == 0))
×
NEW
1338
        return;
×
1339

NEW
1340
    QListIterator<QTreeWidgetItem*> it(m_tree->selectedItems());
×
NEW
1341
    if (!it.hasNext())
×
NEW
1342
        return;
×
1343

NEW
1344
    QTreeWidgetItem* item = it.next();
×
NEW
1345
    if (item == NULL)
×
NEW
1346
        return;
×
1347

1348
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
NEW
1349
    const QModelIndex modelIndex = m_tree->indexFromItem(item);
×
1350
#else
1351
    m_tree->setCurrentItem(item);
1352
    const QModelIndex modelIndex = m_tree->currentIndex();
1353
#endif
NEW
1354
    int row = modelIndex.row();
×
NEW
1355
    if (!m_scene->moveFixture(row, row+offset))
×
NEW
1356
        return;
×
1357

NEW
1358
    m_tree->takeTopLevelItem(row);
×
NEW
1359
    m_tree->insertTopLevelItem(row+offset, item);
×
NEW
1360
    m_tree->setCurrentItem(item);
×
1361

NEW
1362
    const QVariant tabMode = m_scene->uiStateValue(UI_STATE_TAB_MODE);
×
NEW
1363
    if (m_tab == NULL)
×
NEW
1364
        return;
×
1365

NEW
1366
    if (tabMode.isNull() || (tabMode.toInt() == UI_STATE_TABBED_FIXTURES))
×
1367
    {
NEW
1368
        QTabBar* tabBar = m_tab->tabBar();
×
NEW
1369
        if (tabBar == NULL)
×
NEW
1370
            return;
×
1371

NEW
1372
        const int from = m_fixtureFirstTabIndex + row;
×
NEW
1373
        tabBar->moveTab(from, from+offset);
×
1374
    } else {
NEW
1375
        QScrollArea* area = qobject_cast<QScrollArea*>(m_tab->widget(m_fixtureFirstTabIndex));
×
NEW
1376
        if (area == NULL)
×
NEW
1377
            return;
×
1378

NEW
1379
        QGroupBox* grpBox = qobject_cast<QGroupBox*>(area->widget());
×
NEW
1380
        if (grpBox == NULL)
×
NEW
1381
            return;
×
1382

NEW
1383
        QHBoxLayout* fixturesLayout = qobject_cast<QHBoxLayout*>(grpBox->layout());
×
NEW
1384
        if (fixturesLayout == NULL)
×
NEW
1385
            return;
×
1386

NEW
1387
        QLayoutItem* console = fixturesLayout->takeAt(row);
×
NEW
1388
        fixturesLayout->insertItem(row+offset, console);
×
1389
    }
NEW
1390
}
×
1391

NEW
1392
void SceneEditor::slotMoveFixtureUpClicked()
×
1393
{
NEW
1394
    moveFixture(-1);
×
NEW
1395
}
×
1396

NEW
1397
void SceneEditor::slotMoveFixtureDownClicked()
×
1398
{
NEW
1399
    moveFixture(1);
×
NEW
1400
}
×
1401

UNCOV
1402
void SceneEditor::slotEnableAll()
×
1403
{
1404
    foreach (FixtureConsole* fc, m_consoleList)
×
1405
    {
1406
        if (fc != NULL)
×
1407
            fc->setChecked(true);
×
1408
    }
×
1409
}
×
1410

1411
void SceneEditor::slotDisableAll()
×
1412
{
1413
    foreach (FixtureConsole* fc, m_consoleList)
×
1414
    {
1415
        if (fc != NULL)
×
1416
            fc->setChecked(false);
×
1417
    }
×
1418
}
×
1419

1420
void SceneEditor::slotFadeInChanged(int ms)
×
1421
{
1422
    m_scene->setFadeInSpeed(ms);
×
1423
}
×
1424

1425
void SceneEditor::slotFadeOutChanged(int ms)
×
1426
{
1427
    m_scene->setFadeOutSpeed(ms);
×
1428
}
×
1429

1430
void SceneEditor::slotEnableAllChannelGroups()
×
1431
{
1432
    for (int i = 0; i < m_channelGroupsTree->topLevelItemCount(); i++)
×
1433
    {
1434
        QTreeWidgetItem *item = m_channelGroupsTree->topLevelItem(i);
×
1435
        item->setCheckState(KColumnName, Qt::Checked);
×
1436
    }
1437
}
×
1438

1439
void SceneEditor::slotDisableAllChannelGroups()
×
1440
{
1441
    for (int i = 0; i < m_channelGroupsTree->topLevelItemCount(); i++)
×
1442
    {
1443
        QTreeWidgetItem *item = m_channelGroupsTree->topLevelItem(i);
×
1444
        item->setCheckState(KColumnName, Qt::Unchecked);
×
1445
    }
1446
}
×
1447

1448
void SceneEditor::slotChannelGroupsChanged(QTreeWidgetItem *item, int column)
×
1449
{
1450
    if (item == NULL)
×
1451
        return;
×
1452

1453
    quint32 grpID = item->data(column, Qt::UserRole).toUInt();
×
1454
    ChannelsGroup *grp = m_doc->channelsGroup(grpID);
×
1455
    if (grp == NULL)
×
1456
        return;
×
1457

1458
    if (item->checkState(column) == Qt::Checked)
×
1459
    {
1460
        m_scene->addChannelGroup(grpID);
×
1461
        foreach (SceneValue val, grp->getChannels())
×
1462
        {
1463
            Fixture *fixture = m_doc->fixture(val.fxi);
×
1464
            if (fixture != NULL)
×
1465
            {
1466
                if (addFixtureItem(fixture) == true)
×
1467
                    addFixtureTab(fixture, val.channel);
×
1468
                else
1469
                    setTabChannelState(true, fixture, val.channel);
×
1470
            }
1471
        }
×
1472
    }
1473
    else
1474
    {
1475
        m_scene->removeChannelGroup(grpID);
×
1476
        foreach (SceneValue val, grp->getChannels())
×
1477
        {
1478
            Fixture *fixture = m_doc->fixture(val.fxi);
×
1479
            if (fixture != NULL)
×
1480
                setTabChannelState(false, fixture, val.channel);
×
1481
        }
×
1482
    }
1483

1484
    qDebug() << Q_FUNC_INFO << "Groups in list: " << m_scene->channelGroups().count();
×
1485

1486
    updateChannelsGroupsTab();
×
1487
}
1488

1489
/*********************************************************************
1490
 * Channels groups tabs
1491
 *********************************************************************/
1492
void SceneEditor::updateChannelsGroupsTab()
×
1493
{
1494
    QScrollArea* scrollArea = NULL;
×
1495
    QList <quint32> ids = m_scene->channelGroups();
×
1496

1497
    if (m_channelGroupsTree->topLevelItemCount() == 0)
×
1498
    {
1499
        m_fixtureFirstTabIndex = 1;
×
1500
        return;
×
1501
    }
1502

1503
    /* Get a scroll area for the console */
1504
    if (m_channelGroupsTab != -1)
×
1505
    {
1506
        scrollArea = qobject_cast<QScrollArea*> (m_tab->widget(m_channelGroupsTab));
×
1507
        Q_ASSERT(scrollArea != NULL);
×
1508
        GroupsConsole *tmpGrpConsole = qobject_cast<GroupsConsole*> (scrollArea->widget());
×
1509
        Q_ASSERT(tmpGrpConsole != NULL);
×
1510
        delete tmpGrpConsole;
×
1511
        if (ids.count() == 0)
×
1512
        {
1513
            m_tab->removeTab(1);
×
1514
            m_channelGroupsTab = -1;
×
1515
            m_fixtureFirstTabIndex = 1;
×
1516
            return;
×
1517
        }
1518
    }
1519
    else
1520
    {
1521
        if (ids.count() == 0)
×
1522
            return;
×
1523
        scrollArea = new QScrollArea(m_tab);
×
1524
    }
1525

1526
    QList<uchar>levels = m_scene->channelGroupsLevels();
×
1527
    GroupsConsole* console = new GroupsConsole(scrollArea, m_doc, ids, levels);
×
1528
    scrollArea->setWidget(console);
×
1529
    scrollArea->setWidgetResizable(true);
×
1530
    if (m_channelGroupsTab == -1)
×
1531
    {
1532
        m_tab->insertTab(1, scrollArea, tr("Channels Groups"));
×
1533
        m_tab->setTabToolTip(1, tr("Channels Groups"));
×
1534
    }
1535

1536
    m_channelGroupsTab = 1;
×
1537
    m_fixtureFirstTabIndex = 2;
×
1538
    connect(console, SIGNAL(groupValueChanged(quint32,uchar)),
×
1539
            this, SLOT(slotGroupValueChanged(quint32,uchar)));
1540
}
×
1541

1542
GroupsConsole *SceneEditor::groupConsoleTab(int tab) const
×
1543
{
1544
    if (tab != m_channelGroupsTab)
×
1545
        return NULL;
×
1546

1547
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1548
    Q_ASSERT(area != NULL);
×
1549

1550
    return qobject_cast<GroupsConsole*> (area->widget());
×
1551
}
1552

1553
void SceneEditor::slotGroupValueChanged(quint32 groupID, uchar value)
×
1554
{
1555
    // Don't modify m_scene contents when doing initialization
1556
    if (m_initFinished == true)
×
1557
    {
1558
        Q_ASSERT(m_scene != NULL);
×
1559
        ChannelsGroup *group = m_doc->channelsGroup(groupID);
×
1560
        if (group == NULL)
×
1561
            return;
×
1562
        foreach (SceneValue scv, group->getChannels())
×
1563
        {
1564
            Fixture *fixture = m_doc->fixture(scv.fxi);
×
1565
            if (fixture == NULL)
×
1566
                continue;
×
1567
            FixtureConsole *fc = fixtureConsole(fixture);
×
1568
            if (fc == NULL)
×
1569
                continue;
×
1570
            fc->setValue(scv.channel, value);
×
1571
        }
×
1572
        m_scene->setChannelGroupLevel(groupID, value);
×
1573
    }
1574
}
1575

1576
/*****************************************************************************
1577
 * Fixture tabs
1578
 *****************************************************************************/
1579

1580
FixtureConsole* SceneEditor::fixtureConsole(Fixture* fixture)
×
1581
{
1582
    Q_ASSERT(fixture != NULL);
×
1583

1584
    if (m_consoleList.contains(fixture->id()))
×
1585
        return m_consoleList[fixture->id()];
×
1586

1587
    return NULL;
×
1588
}
1589

1590
void SceneEditor::addFixtureTab(Fixture* fixture, quint32 channel)
×
1591
{
1592
    Q_ASSERT(fixture != NULL);
×
1593

1594
    /* Put the console inside a scroll area */
1595
    QScrollArea* scrollArea = new QScrollArea(m_tab);
×
1596
    scrollArea->setWidgetResizable(true);
×
1597

1598
    FixtureConsole* console = new FixtureConsole(scrollArea, m_doc);
×
1599
    console->setFixture(fixture->id());
×
1600
    m_consoleList[fixture->id()] = console;
×
1601
    scrollArea->setWidget(console);
×
1602
    int tIdx = m_tab->addTab(scrollArea, fixture->name());
×
1603
    m_tab->setTabToolTip(tIdx, fixture->name());
×
1604

1605
    /* Start off with all channels disabled */
1606
    console->setChecked(false);
×
1607

1608
    connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
1609
            this, SLOT(slotValueChanged(quint32,quint32,uchar)));
1610
    connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
1611
            this, SLOT(slotChecked(quint32,quint32,bool)));
1612

1613
    if (channel != QLCChannel::invalid())
×
1614
        console->setChecked(true, channel);
×
1615
}
×
1616

1617
void SceneEditor::removeFixtureTab(quint32 fixtureID)
×
1618
{
1619
    /* Start searching from the first fixture tab */
1620
    for (int i = m_fixtureFirstTabIndex; i < m_tab->count(); i++)
×
1621
    {
1622
        FixtureConsole* fc = fixtureConsoleTab(i);
×
1623
        if (fc != NULL && fc->fixture() == fixtureID)
×
1624
        {
1625
            /* First remove the tab because otherwise Qt might
1626
               remove two tabs -- undocumented feature, which
1627
               might be intended or it might not. */
1628
            QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(i));
×
1629
            Q_ASSERT(area != NULL);
×
1630
            m_tab->removeTab(i);
×
1631
            m_consoleList.take(fixtureID);
×
1632
            delete area; // Deletes also FixtureConsole
×
1633
            break;
×
1634
        }
1635
    }
1636
}
×
1637

1638
FixtureConsole* SceneEditor::fixtureConsoleTab(int tab) const
×
1639
{
1640
    if (tab >= m_tab->count() || tab <= 0)
×
1641
        return NULL;
×
1642

1643
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1644
    Q_ASSERT(area != NULL);
×
1645

1646
    return qobject_cast<FixtureConsole*> (area->widget());
×
1647
}
1648

1649
void SceneEditor::setTabChannelState(bool status, Fixture *fixture, quint32 channel)
×
1650
{
1651
    Q_ASSERT(fixture != NULL);
×
1652

1653
    if (channel == QLCChannel::invalid())
×
1654
        return;
×
1655

1656
    if (m_consoleList.contains(fixture->id()))
×
1657
        m_consoleList[fixture->id()]->setChecked(status, channel);
×
1658
}
1659

1660
void SceneEditor::slotValueChanged(quint32 fxi, quint32 channel, uchar value)
×
1661
{
1662
    // Don't modify m_scene contents when doing initialization
1663
    if (m_initFinished == true)
×
1664
    {
1665
        Q_ASSERT(m_scene != NULL);
×
1666

1667
        if (m_doc->mode() == Doc::Operate)
×
1668
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), false);
×
1669
        else
1670
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), true);
×
1671
        emit fixtureValueChanged(SceneValue(fxi, channel, value), true);
×
1672
    }
1673

1674
    if (m_source != NULL)
×
1675
        m_source->set(fxi, channel, value);
×
1676
}
×
1677

1678
void SceneEditor::slotChecked(quint32 fxi, quint32 channel, bool state)
×
1679
{
1680
    // Don't modify m_scene contents when doing initialization
1681
    if (m_initFinished == true)
×
1682
    {
1683
        // When a channel is enabled, its current value is emitted with valueChanged().
1684
        // So, state == true case doesn't need to be handled here.
1685
        Q_ASSERT(m_scene != NULL);
×
1686
        if (state == false)
×
1687
        {
1688
            m_scene->unsetValue(fxi, channel);
×
1689
            if (m_source != NULL)
×
1690
            {
1691
                m_source->unset(fxi, channel);
×
1692
                emit fixtureValueChanged(SceneValue(fxi, channel, 0), false);
×
1693
            }
1694
        }
1695
    }
1696
}
×
1697

1698
void SceneEditor::slotGoToNextTab()
×
1699
{
1700
    m_currentTab++;
×
1701
    if (m_currentTab == m_tab->count())
×
1702
        m_currentTab = 0;
×
1703
    m_tab->setCurrentIndex(m_currentTab);
×
1704
}
×
1705

1706
void SceneEditor::slotGoToPreviousTab()
×
1707
{
1708
    if (m_currentTab == 0)
×
1709
        m_currentTab = m_tab->count() - 1;
×
1710
    else
1711
        m_currentTab--;
×
1712
    m_tab->setCurrentIndex(m_currentTab);
×
1713
}
×
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