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

mcallegari / qlcplus / 19144422256

06 Nov 2025 05:33PM UTC coverage: 34.256% (-0.1%) from 34.358%
19144422256

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 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()));
312

313
    m_nameEdit->setText(m_scene->name());
×
314
    m_nameEdit->setSelection(0, m_nameEdit->text().length());
×
315
    connect(m_nameEdit, SIGNAL(textEdited(const QString&)),
×
316
            this, SLOT(slotNameEdited(const QString&)));
317

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

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

346
    // Apply any mode related change
347
    slotModeChanged(m_doc->mode());
×
348

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

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

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

377
            addFixtureItem(fixture);
×
378
        }
379
    }
×
380

381
    // Create the actual tab view
382
    if (tabMode.isNull() || tabMode.toInt() == UI_STATE_TABBED_FIXTURES)
×
383
        slotViewModeChanged(true, applyValues);
×
384
    else
385
        slotViewModeChanged(false, applyValues);
×
386
}
×
387

388
void SceneEditor::setSceneValue(const SceneValue& scv)
×
389
{
390
    FixtureConsole* fc;
391
    Fixture* fixture;
392

393
    fixture = m_doc->fixture(scv.fxi);
×
394
    Q_ASSERT(fixture != NULL);
×
395

396
    fc = fixtureConsole(fixture);
×
397
    if (fc != NULL)
×
398
        fc->setSceneValue(scv);
×
399
}
×
400

401

402
void SceneEditor::setBlindModeEnabled(bool active)
×
403
{
404
    m_blindAction->setChecked(active);
×
405
}
×
406

407
/*****************************************************************************
408
 * Common
409
 *****************************************************************************/
410

411
void SceneEditor::slotTabChanged(int tab)
×
412
{
413
    m_currentTab = tab;
×
414
    QLCClipboard *clipboard = m_doc->clipboard();
×
415

416
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, tab);
×
417

418
    if (tab == KTabGeneral)
×
419
    {
420
        m_enableCurrentAction->setEnabled(false);
×
421
        m_disableCurrentAction->setEnabled(false);
×
422

423
        m_copyAction->setEnabled(false);
×
424
        m_pasteAction->setEnabled(false);
×
425
        m_copyToAllAction->setEnabled(false);
×
426
        m_colorToolAction->setEnabled(false);
×
427
    }
428
    else
429
    {
430
        m_enableCurrentAction->setEnabled(true);
×
431
        m_disableCurrentAction->setEnabled(true);
×
432

433
        m_copyAction->setEnabled(true);
×
434
        if (clipboard->hasSceneValues())
×
435
            m_pasteAction->setEnabled(true);
×
436
        else
437
            m_pasteAction->setEnabled(false);
×
438

439
        if (m_tabViewAction->isChecked())
×
440
            m_copyToAllAction->setEnabled(true);
×
441
        else
442
            m_copyToAllAction->setEnabled(false);
×
443
        m_colorToolAction->setEnabled(isColorToolAvailable());
×
444
        m_positionToolAction->setEnabled(isPositionToolAvailable());
×
445
    }
446
}
×
447

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

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

488
void SceneEditor::slotCopy()
×
489
{
490
    QList <SceneValue> copyList;
×
491
    QLCClipboard *clipboard = m_doc->clipboard();
×
492

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

529
void SceneEditor::slotPaste()
×
530
{
531
    QLCClipboard *clipboard = m_doc->clipboard();
×
532

533
    if (clipboard->hasSceneValues() == false)
×
534
        return;
×
535

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

560
void SceneEditor::slotCopyToAll()
×
561
{
562
    slotCopy();
×
563

564
    QLCClipboard *clipboard = m_doc->clipboard();
×
565

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

576
    //m_copy.clear();
577
    m_pasteAction->setEnabled(false);
×
578
}
×
579

580
void SceneEditor::slotColorTool()
×
581
{
582
    QColor color = slotColorSelectorChanged(QColor());
×
583

584
    QColorDialog dialog(color, this);
×
585
    connect(&dialog, SIGNAL(currentColorChanged(const QColor&)),
×
586
            this, SLOT(slotColorSelectorChanged(const QColor&)));
587

588
    int result = dialog.exec();
×
589
    if (result == QDialog::Rejected)
×
590
    {
591
        slotColorSelectorChanged(color); // reset color to what it previously was
×
592
    }
593
}
×
594

595
void SceneEditor::slotPositionTool()
×
596
{
597
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
598
    if (fc != NULL)
×
599
    {
600
        QList<SceneValue> origValues = fc->values();
×
601

602
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
603
        QPointF pos;
×
604
        QRectF range;
×
605
        bool panFound = false;
×
606
        bool tiltFound = false;
×
607

608
        Q_ASSERT(fxi != NULL);
×
609

610
        for (int i = 0; i < fxi->heads(); ++i)
×
611
        {
612
             if (!range.isValid())
×
613
                 range = fxi->degreesRange(i);
×
614

615
             quint32 panMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i);
×
616
             quint32 panLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, i);
×
617
             quint32 tiltMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i);
×
618
             quint32 tiltLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, i);
×
619

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

632
                     pos.setX(v);
×
633
                 }
634
             }
635

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

648
                     pos.setY(v);
×
649
                 }
650
             }
651
        }
652

653
        PositionTool dialog(pos, range);
×
654
        connect(&dialog, SIGNAL(currentPositionChanged(const QPointF&)),
×
655
            this, SLOT(slotPositionSelectorChanged(const QPointF&)));
656

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

665
QColor SceneEditor::slotColorSelectorChanged(const QColor& color)
×
666
{
667
    QColor returnColor = QColor();
×
668

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

676
        QSet <quint32> cyan    = fxi->channels(QLCChannel::Intensity, QLCChannel::Cyan);
×
677
        QSet <quint32> magenta = fxi->channels(QLCChannel::Intensity, QLCChannel::Magenta);
×
678
        QSet <quint32> yellow  = fxi->channels(QLCChannel::Intensity, QLCChannel::Yellow);
×
679
        QSet <quint32> red     = fxi->channels(QLCChannel::Intensity, QLCChannel::Red);
×
680
        QSet <quint32> green   = fxi->channels(QLCChannel::Intensity, QLCChannel::Green);
×
681
        QSet <quint32> blue    = fxi->channels(QLCChannel::Intensity, QLCChannel::Blue);
×
682

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

697
                foreach (quint32 ch, magenta)
×
698
                {
699
                    fc->setChecked(true, ch);
×
700
                    fc->setValue(ch, color.magenta());
×
701
                }
×
702

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

717
            if (color.isValid() == true)
×
718
            {
719
                foreach (quint32 ch, red)
×
720
                {
721
                    fc->setChecked(true, ch);
×
722
                    fc->setValue(ch, color.red());
×
723
                }
×
724

725
                foreach (quint32 ch, green)
×
726
                {
727
                    fc->setChecked(true, ch);
×
728
                    fc->setValue(ch, color.green());
×
729
                }
×
730

731
                foreach (quint32 ch, blue)
×
732
                {
733
                    fc->setChecked(true, ch);
×
734
                    fc->setValue(ch, color.blue());
×
735
                }
×
736
            }
737
        }
738
        return returnColor;
×
739
    }
×
740

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

768
    return returnColor;
×
769
}
770

771
void SceneEditor::slotPositionSelectorChanged(const QPointF& position)
×
772
{
773
    qreal x = position.x();
×
774
    qreal y = position.y();
×
775

776
    uchar panMsbNew = x;
×
777
    uchar panLsbNew = (x - floor(x)) * 256;
×
778
    uchar tiltMsbNew = y;
×
779
    uchar tiltLsbNew = (y - floor(y)) * 256;
×
780

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

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

795
             if (panMsbChannel != QLCChannel::invalid())
×
796
             {
797
                 fc->setChecked(true, panMsbChannel);
×
798
                 fc->setValue(panMsbChannel, panMsbNew);
×
799

800
                 if (panLsbChannel != QLCChannel::invalid())
×
801
                 {
802
                     fc->setChecked(true, panLsbChannel);
×
803
                     fc->setValue(panLsbChannel, panLsbNew);
×
804
                 }
805
             }
806

807
             if (tiltMsbChannel != QLCChannel::invalid())
×
808
             {
809
                 fc->setChecked(true, tiltMsbChannel);
×
810
                 fc->setValue(tiltMsbChannel, tiltMsbNew);
×
811

812
                 if (tiltLsbChannel != QLCChannel::invalid())
×
813
                 {
814
                     fc->setChecked(true, tiltLsbChannel);
×
815
                     fc->setValue(tiltLsbChannel, tiltLsbNew);
×
816
                 }
817
             }
818
        }
819
    }
820

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

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

861
    m_scene->setUiStateValue(UI_STATE_SHOW_DIAL, state);
×
862
}
×
863

864
void SceneEditor::slotBlindToggled(bool state)
×
865
{
866
    if (m_doc->mode() == Doc::Operate)
×
867
    {
868
        delete m_source;
×
869
        m_source = NULL;
×
870

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

884
    if (m_source != NULL)
×
885
        m_source->setOutputEnabled(!state);
×
886
}
×
887

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

901
}
×
902

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

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

924
            scrollArea->setWidgetResizable(true);
×
925
            int tIdx = m_tab->addTab(scrollArea, tr("All fixtures"));
×
926
            m_tab->setTabToolTip(tIdx, tr("All fixtures"));
×
927

928
            QGroupBox* grpBox = new QGroupBox(scrollArea);
×
929
            grpBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
×
930
            QHBoxLayout* fixturesLayout = new QHBoxLayout(grpBox);
×
931
            grpBox->setLayout(fixturesLayout);
×
932
            fixturesLayout->setSpacing(2);
×
933
            fixturesLayout->setContentsMargins(0, 2, 2, 2);
×
934

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

949
                connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
950
                        this, SLOT(slotValueChanged(quint32,quint32,uchar)));
951
                connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
952
                        this, SLOT(slotChecked(quint32,quint32,bool)));
953

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

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

980
            addFixtureTab(fixture);
×
981

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

994
    m_scene->setUiStateValue(UI_STATE_TAB_MODE, tabbed ? UI_STATE_TABBED_FIXTURES : UI_STATE_ALL_FIXTURES);
×
995

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

1010
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, m_tab->currentIndex());
×
1011
}
×
1012

1013
void SceneEditor::slotRecord()
×
1014
{
1015
    Chaser* chaser = selectedChaser();
×
1016
    if (chaser == NULL)
×
1017
        return;
×
1018

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

1026
    // Switch to the cloned scene
1027
    FunctionManager::instance()->selectFunction(clone->id());
×
1028
}
×
1029

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

1039
bool SceneEditor::isColorToolAvailable()
×
1040
{
1041
    Fixture* fxi = NULL;
×
1042
    quint32 cyan = QLCChannel::invalid(), magenta = QLCChannel::invalid(), yellow = QLCChannel::invalid();
×
1043
    quint32 red = QLCChannel::invalid(), green = QLCChannel::invalid(), blue = QLCChannel::invalid();
×
1044

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

1052
        cyan = fxi->channel(QLCChannel::Intensity, QLCChannel::Cyan);
×
1053
        magenta = fxi->channel(QLCChannel::Intensity, QLCChannel::Magenta);
×
1054
        yellow = fxi->channel(QLCChannel::Intensity, QLCChannel::Yellow);
×
1055
        red = fxi->channel(QLCChannel::Intensity, QLCChannel::Red);
×
1056
        green = fxi->channel(QLCChannel::Intensity, QLCChannel::Green);
×
1057
        blue = fxi->channel(QLCChannel::Intensity, QLCChannel::Blue);
×
1058
    }
1059

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

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

1103
bool SceneEditor::isPositionToolAvailable()
×
1104
{
1105
    Fixture* fxi = NULL;
×
1106

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

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

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

1136
    return false;
×
1137
}
1138

1139
void SceneEditor::createSpeedDials()
×
1140
{
1141
    if (m_speedDials != NULL)
×
1142
        return;
×
1143

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

1157
void SceneEditor::slotDialDestroyed(QObject *)
×
1158
{
1159
    m_speedDialAction->setChecked(false);
×
1160
}
×
1161

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

1171
/*****************************************************************************
1172
 * General page
1173
 *****************************************************************************/
1174

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

1186
    return NULL;
×
1187
}
×
1188

1189
QList <Fixture*> SceneEditor::selectedFixtures() const
×
1190
{
1191
    QListIterator <QTreeWidgetItem*> it(m_tree->selectedItems());
×
1192
    QList <Fixture*> list;
×
1193

1194
    while (it.hasNext() == true)
×
1195
    {
1196
        QTreeWidgetItem* item;
1197
        quint32 fxi_id;
1198
        Fixture* fixture;
1199

1200
        item = it.next();
×
1201
        fxi_id = item->text(KColumnID).toInt();
×
1202
        fixture = m_doc->fixture(fxi_id);
×
1203
        Q_ASSERT(fixture != NULL);
×
1204

1205
        list.append(fixture);
×
1206
    }
1207

1208
    return list;
×
1209
}
×
1210

1211
bool SceneEditor::addFixtureItem(Fixture* fixture)
×
1212
{
1213
    Q_ASSERT(fixture != NULL);
×
1214

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

1227
    QTreeWidgetItem* item;
1228

1229
    item = new QTreeWidgetItem(m_tree);
×
1230
    item->setText(KColumnName, fixture->name());
×
1231
    item->setText(KColumnID, QString("%1").arg(fixture->id()));
×
1232

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

1245
    /* Select newly-added fixtures so that their channels can be
1246
       quickly disabled/enabled */
1247
    item->setSelected(true);
×
1248

1249
    return true;
×
1250
}
1251

1252
void SceneEditor::removeFixtureItem(quint32 fixtureID)
×
1253
{
1254
    QTreeWidgetItem *item;
1255

1256
    item = fixtureItem(fixtureID);
×
1257
    delete item;
×
1258
}
×
1259

1260
void SceneEditor::slotNameEdited(const QString& name)
×
1261
{
1262
    m_scene->setName(name);
×
1263
    if (m_speedDials != NULL)
×
1264
        m_speedDials->setWindowTitle(m_scene->name());
×
1265
}
×
1266

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

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

1291
            if (!m_scene->fixtures().contains(fixture->id()))
×
1292
            {
1293
                addFixtureItem(fixture);
×
1294
                addFixtureTab(fixture);
×
1295

1296
                // Add fixture in scene
1297
                m_scene->addFixture(fixture->id());
×
1298
            }
1299
        }
1300
    }
×
1301
}
×
1302

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

1310
    if (r == QMessageBox::Yes)
×
1311
    {
1312
        QListIterator <Fixture*> it(selectedFixtures());
×
1313
        while (it.hasNext() == true)
×
1314
        {
1315
            Fixture* fixture = it.next();
×
1316
            Q_ASSERT(fixture != NULL);
×
1317

1318
            removeFixtureTab(fixture->id());
×
1319
            removeFixtureItem(fixture->id());
×
1320

1321
            /* Remove all values associated to the fixture */
1322
            for (quint32 i = 0; i < fixture->channels(); i++)
×
1323
                m_scene->unsetValue(fixture->id(), i);
×
1324

1325
            // Remove fixture from scene
1326
            m_scene->removeFixture(fixture->id());
×
1327
        }
1328
    }
×
1329
}
×
1330

1331
void SceneEditor::slotEnableAll()
×
1332
{
1333
    foreach (FixtureConsole* fc, m_consoleList)
×
1334
    {
1335
        if (fc != NULL)
×
1336
            fc->setChecked(true);
×
1337
    }
×
1338
}
×
1339

1340
void SceneEditor::slotDisableAll()
×
1341
{
1342
    foreach (FixtureConsole* fc, m_consoleList)
×
1343
    {
1344
        if (fc != NULL)
×
1345
            fc->setChecked(false);
×
1346
    }
×
1347
}
×
1348

1349
void SceneEditor::slotFadeInChanged(int ms)
×
1350
{
1351
    m_scene->setFadeInSpeed(ms);
×
1352
}
×
1353

1354
void SceneEditor::slotFadeOutChanged(int ms)
×
1355
{
1356
    m_scene->setFadeOutSpeed(ms);
×
1357
}
×
1358

1359
void SceneEditor::slotEnableAllChannelGroups()
×
1360
{
1361
    for (int i = 0; i < m_channelGroupsTree->topLevelItemCount(); i++)
×
1362
    {
1363
        QTreeWidgetItem *item = m_channelGroupsTree->topLevelItem(i);
×
1364
        item->setCheckState(KColumnName, Qt::Checked);
×
1365
    }
1366
}
×
1367

1368
void SceneEditor::slotDisableAllChannelGroups()
×
1369
{
1370
    for (int i = 0; i < m_channelGroupsTree->topLevelItemCount(); i++)
×
1371
    {
1372
        QTreeWidgetItem *item = m_channelGroupsTree->topLevelItem(i);
×
1373
        item->setCheckState(KColumnName, Qt::Unchecked);
×
1374
    }
1375
}
×
1376

1377
void SceneEditor::slotChannelGroupsChanged(QTreeWidgetItem *item, int column)
×
1378
{
1379
    if (item == NULL)
×
1380
        return;
×
1381

1382
    quint32 grpID = item->data(column, Qt::UserRole).toUInt();
×
1383
    ChannelsGroup *grp = m_doc->channelsGroup(grpID);
×
1384
    if (grp == NULL)
×
1385
        return;
×
1386

1387
    if (item->checkState(column) == Qt::Checked)
×
1388
    {
1389
        m_scene->addChannelGroup(grpID);
×
1390
        foreach (SceneValue val, grp->getChannels())
×
1391
        {
1392
            Fixture *fixture = m_doc->fixture(val.fxi);
×
1393
            if (fixture != NULL)
×
1394
            {
1395
                if (addFixtureItem(fixture) == true)
×
1396
                    addFixtureTab(fixture, val.channel);
×
1397
                else
1398
                    setTabChannelState(true, fixture, val.channel);
×
1399
            }
1400
        }
×
1401
    }
1402
    else
1403
    {
1404
        m_scene->removeChannelGroup(grpID);
×
1405
        foreach (SceneValue val, grp->getChannels())
×
1406
        {
1407
            Fixture *fixture = m_doc->fixture(val.fxi);
×
1408
            if (fixture != NULL)
×
1409
                setTabChannelState(false, fixture, val.channel);
×
1410
        }
×
1411
    }
1412

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

1415
    updateChannelsGroupsTab();
×
1416
}
1417

1418
/*********************************************************************
1419
 * Channels groups tabs
1420
 *********************************************************************/
1421
void SceneEditor::updateChannelsGroupsTab()
×
1422
{
1423
    QScrollArea* scrollArea = NULL;
×
1424
    QList <quint32> ids = m_scene->channelGroups();
×
1425

1426
    if (m_channelGroupsTree->topLevelItemCount() == 0)
×
1427
    {
1428
        m_fixtureFirstTabIndex = 1;
×
1429
        return;
×
1430
    }
1431

1432
    /* Get a scroll area for the console */
1433
    if (m_channelGroupsTab != -1)
×
1434
    {
1435
        scrollArea = qobject_cast<QScrollArea*> (m_tab->widget(m_channelGroupsTab));
×
1436
        Q_ASSERT(scrollArea != NULL);
×
1437
        GroupsConsole *tmpGrpConsole = qobject_cast<GroupsConsole*> (scrollArea->widget());
×
1438
        Q_ASSERT(tmpGrpConsole != NULL);
×
1439
        delete tmpGrpConsole;
×
1440
        if (ids.count() == 0)
×
1441
        {
1442
            m_tab->removeTab(1);
×
1443
            m_channelGroupsTab = -1;
×
1444
            m_fixtureFirstTabIndex = 1;
×
1445
            return;
×
1446
        }
1447
    }
1448
    else
1449
    {
1450
        if (ids.count() == 0)
×
1451
            return;
×
1452
        scrollArea = new QScrollArea(m_tab);
×
1453
    }
1454

1455
    QList<uchar>levels = m_scene->channelGroupsLevels();
×
1456
    GroupsConsole* console = new GroupsConsole(scrollArea, m_doc, ids, levels);
×
1457
    scrollArea->setWidget(console);
×
1458
    scrollArea->setWidgetResizable(true);
×
1459
    if (m_channelGroupsTab == -1)
×
1460
    {
1461
        m_tab->insertTab(1, scrollArea, tr("Channels Groups"));
×
1462
        m_tab->setTabToolTip(1, tr("Channels Groups"));
×
1463
    }
1464

1465
    m_channelGroupsTab = 1;
×
1466
    m_fixtureFirstTabIndex = 2;
×
1467
    connect(console, SIGNAL(groupValueChanged(quint32,uchar)),
×
1468
            this, SLOT(slotGroupValueChanged(quint32,uchar)));
1469
}
×
1470

1471
GroupsConsole *SceneEditor::groupConsoleTab(int tab)
×
1472
{
1473
    if (tab != m_channelGroupsTab)
×
1474
        return NULL;
×
1475

1476
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1477
    Q_ASSERT(area != NULL);
×
1478

1479
    return qobject_cast<GroupsConsole*> (area->widget());
×
1480
}
1481

1482
void SceneEditor::slotGroupValueChanged(quint32 groupID, uchar value)
×
1483
{
1484
    // Don't modify m_scene contents when doing initialization
1485
    if (m_initFinished == true)
×
1486
    {
1487
        Q_ASSERT(m_scene != NULL);
×
1488
        ChannelsGroup *group = m_doc->channelsGroup(groupID);
×
1489
        if (group == NULL)
×
1490
            return;
×
1491
        foreach (SceneValue scv, group->getChannels())
×
1492
        {
1493
            Fixture *fixture = m_doc->fixture(scv.fxi);
×
1494
            if (fixture == NULL)
×
1495
                continue;
×
1496
            FixtureConsole *fc = fixtureConsole(fixture);
×
1497
            if (fc == NULL)
×
1498
                continue;
×
1499
            fc->setValue(scv.channel, value);
×
1500
        }
×
1501
        m_scene->setChannelGroupLevel(groupID, value);
×
1502
    }
1503
}
1504

1505
/*****************************************************************************
1506
 * Fixture tabs
1507
 *****************************************************************************/
1508

1509
FixtureConsole* SceneEditor::fixtureConsole(Fixture* fixture)
×
1510
{
1511
    Q_ASSERT(fixture != NULL);
×
1512

1513
    if (m_consoleList.contains(fixture->id()))
×
1514
        return m_consoleList[fixture->id()];
×
1515

1516
    return NULL;
×
1517
}
1518

1519
void SceneEditor::addFixtureTab(Fixture* fixture, quint32 channel)
×
1520
{
1521
    Q_ASSERT(fixture != NULL);
×
1522

1523
    /* Put the console inside a scroll area */
1524
    QScrollArea* scrollArea = new QScrollArea(m_tab);
×
1525
    scrollArea->setWidgetResizable(true);
×
1526

1527
    FixtureConsole* console = new FixtureConsole(scrollArea, m_doc);
×
1528
    console->setFixture(fixture->id());
×
1529
    m_consoleList[fixture->id()] = console;
×
1530
    scrollArea->setWidget(console);
×
1531
    int tIdx = m_tab->addTab(scrollArea, fixture->name());
×
1532
    m_tab->setTabToolTip(tIdx, fixture->name());
×
1533

1534
    /* Start off with all channels disabled */
1535
    console->setChecked(false);
×
1536

1537
    connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
1538
            this, SLOT(slotValueChanged(quint32,quint32,uchar)));
1539
    connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
1540
            this, SLOT(slotChecked(quint32,quint32,bool)));
1541

1542
    if (channel != QLCChannel::invalid())
×
1543
        console->setChecked(true, channel);
×
1544
}
×
1545

1546
void SceneEditor::removeFixtureTab(quint32 fixtureID)
×
1547
{
1548
    /* Start searching from the first fixture tab */
1549
    for (int i = m_fixtureFirstTabIndex; i < m_tab->count(); i++)
×
1550
    {
1551
        FixtureConsole* fc = fixtureConsoleTab(i);
×
1552
        if (fc != NULL && fc->fixture() == fixtureID)
×
1553
        {
1554
            /* First remove the tab because otherwise Qt might
1555
               remove two tabs -- undocumented feature, which
1556
               might be intended or it might not. */
1557
            QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(i));
×
1558
            Q_ASSERT(area != NULL);
×
1559
            m_tab->removeTab(i);
×
1560
            m_consoleList.take(fixtureID);
×
1561
            delete area; // Deletes also FixtureConsole
×
1562
            break;
×
1563
        }
1564
    }
1565
}
×
1566

1567
FixtureConsole* SceneEditor::fixtureConsoleTab(int tab)
×
1568
{
1569
    if (tab >= m_tab->count() || tab <= 0)
×
1570
        return NULL;
×
1571

1572
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1573
    Q_ASSERT(area != NULL);
×
1574

1575
    return qobject_cast<FixtureConsole*> (area->widget());
×
1576
}
1577

1578
void SceneEditor::setTabChannelState(bool status, Fixture *fixture, quint32 channel)
×
1579
{
1580
    Q_ASSERT(fixture != NULL);
×
1581

1582
    if (channel == QLCChannel::invalid())
×
1583
        return;
×
1584

1585
    if (m_consoleList.contains(fixture->id()))
×
1586
        m_consoleList[fixture->id()]->setChecked(status, channel);
×
1587
}
1588

1589
void SceneEditor::slotValueChanged(quint32 fxi, quint32 channel, uchar value)
×
1590
{
1591
    // Don't modify m_scene contents when doing initialization
1592
    if (m_initFinished == true)
×
1593
    {
1594
        Q_ASSERT(m_scene != NULL);
×
1595

1596
        if (m_doc->mode() == Doc::Operate)
×
1597
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), false);
×
1598
        else
1599
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), true);
×
1600
        emit fixtureValueChanged(SceneValue(fxi, channel, value), true);
×
1601
    }
1602

1603
    if (m_source != NULL)
×
1604
        m_source->set(fxi, channel, value);
×
1605
}
×
1606

1607
void SceneEditor::slotChecked(quint32 fxi, quint32 channel, bool state)
×
1608
{
1609
    // Don't modify m_scene contents when doing initialization
1610
    if (m_initFinished == true)
×
1611
    {
1612
        // When a channel is enabled, its current value is emitted with valueChanged().
1613
        // So, state == true case doesn't need to be handled here.
1614
        Q_ASSERT(m_scene != NULL);
×
1615
        if (state == false)
×
1616
        {
1617
            m_scene->unsetValue(fxi, channel);
×
1618
            if (m_source != NULL)
×
1619
            {
1620
                m_source->unset(fxi, channel);
×
1621
                emit fixtureValueChanged(SceneValue(fxi, channel, 0), false);
×
1622
            }
1623
        }
1624
    }
1625
}
×
1626

1627
void SceneEditor::slotGoToNextTab()
×
1628
{
1629
    m_currentTab++;
×
1630
    if (m_currentTab == m_tab->count())
×
1631
        m_currentTab = 0;
×
1632
    m_tab->setCurrentIndex(m_currentTab);
×
1633
}
×
1634

1635
void SceneEditor::slotGoToPreviousTab()
×
1636
{
1637
    if (m_currentTab == 0)
×
1638
        m_currentTab = m_tab->count() - 1;
×
1639
    else
1640
        m_currentTab--;
×
1641
    m_tab->setCurrentIndex(m_currentTab);
×
1642
}
×
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