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

mcallegari / qlcplus / 20664142517

02 Jan 2026 06:30PM UTC coverage: 34.144% (-0.04%) from 34.184%
20664142517

Pull #1914

github

web-flow
Merge 45bb2ea0c into 783861b24
Pull Request #1914: ui/sceneeditor: improve switching between view modes

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

2 existing lines in 1 file now uncovered.

17723 of 51907 relevant lines covered (34.14%)

19580.14 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
    this->layout()->setContentsMargins(8, 3, 8, 3);
×
179

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

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

213
    // Speed Dial initial state
214
    m_speedDialAction->setCheckable(true);
×
215

216
    // Blind initial state
217
    m_blindAction->setCheckable(true);
×
218

219
    m_tabViewAction->setCheckable(true);
×
NEW
220
    if (tabMode())
×
221
        m_tabViewAction->setChecked(true);
×
222

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

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

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

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

305
    /* Add & remove buttons */
306
    connect(m_addFixtureButton, SIGNAL(clicked()),
×
307
            this, SLOT(slotAddFixtureClicked()));
308
    connect(m_removeFixtureButton, SIGNAL(clicked()),
×
309
            this, SLOT(slotRemoveFixtureClicked()));
310

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

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

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

344
    // Apply any mode related change
345
    slotModeChanged(m_doc->mode());
×
346

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

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

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

375
            addFixtureItem(fixture);
×
376
        }
377
    }
×
378

379
    // Create the actual tab view
NEW
380
    slotViewModeChanged(tabMode(), applyValues);
×
381
}
×
382

383
void SceneEditor::setSceneValue(const SceneValue& scv)
×
384
{
385
    FixtureConsole* fc;
386
    Fixture* fixture;
387

388
    fixture = m_doc->fixture(scv.fxi);
×
389
    Q_ASSERT(fixture != NULL);
×
390

391
    fc = fixtureConsole(fixture);
×
392
    if (fc != NULL)
×
393
        fc->setSceneValue(scv);
×
394
}
×
395

396

397
void SceneEditor::setBlindModeEnabled(bool active)
×
398
{
399
    m_blindAction->setChecked(active);
×
400
}
×
401

402
/*****************************************************************************
403
 * Common
404
 *****************************************************************************/
405

406
void SceneEditor::slotTabChanged(int tab)
×
407
{
408
    m_currentTab = tab;
×
409
    QLCClipboard *clipboard = m_doc->clipboard();
×
410

411
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, tab);
×
412

413
    if (tab == KTabGeneral)
×
414
    {
415
        m_enableCurrentAction->setEnabled(false);
×
416
        m_disableCurrentAction->setEnabled(false);
×
417

418
        m_copyAction->setEnabled(false);
×
419
        m_pasteAction->setEnabled(false);
×
420
        m_copyToAllAction->setEnabled(false);
×
421
        m_colorToolAction->setEnabled(false);
×
422
    }
423
    else
424
    {
425
        m_enableCurrentAction->setEnabled(true);
×
426
        m_disableCurrentAction->setEnabled(true);
×
427

428
        m_copyAction->setEnabled(true);
×
429
        if (clipboard->hasSceneValues())
×
430
            m_pasteAction->setEnabled(true);
×
431
        else
432
            m_pasteAction->setEnabled(false);
×
433

434
        if (m_tabViewAction->isChecked())
×
435
            m_copyToAllAction->setEnabled(true);
×
436
        else
437
            m_copyToAllAction->setEnabled(false);
×
438
        m_colorToolAction->setEnabled(isColorToolAvailable());
×
439
        m_positionToolAction->setEnabled(isPositionToolAvailable());
×
440
    }
441
}
×
442

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

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

483
void SceneEditor::slotCopy()
×
484
{
485
    QList <SceneValue> copyList;
×
486
    QLCClipboard *clipboard = m_doc->clipboard();
×
487

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

524
void SceneEditor::slotPaste()
×
525
{
526
    QLCClipboard *clipboard = m_doc->clipboard();
×
527

528
    if (clipboard->hasSceneValues() == false)
×
529
        return;
×
530

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

555
void SceneEditor::slotCopyToAll()
×
556
{
557
    slotCopy();
×
558

559
    QLCClipboard *clipboard = m_doc->clipboard();
×
560

561
    if (clipboard->hasSceneValues())
×
562
    {
563
        for (int i = m_fixtureFirstTabIndex; i < m_tab->count(); i++)
×
564
        {
565
            FixtureConsole* fc = fixtureConsoleTab(i);
×
566
            if (fc != NULL)
×
567
                fc->setValues(clipboard->getSceneValues(), m_copyFromSelection);
×
568
        }
569
    }
570

571
    //m_copy.clear();
572
    m_pasteAction->setEnabled(false);
×
573
}
×
574

575
void SceneEditor::slotColorTool()
×
576
{
577
    QColor color = slotColorSelectorChanged(QColor());
×
578

579
    QColorDialog dialog(color, this);
×
580
    connect(&dialog, SIGNAL(currentColorChanged(const QColor&)),
×
581
            this, SLOT(slotColorSelectorChanged(const QColor&)));
582

583
    int result = dialog.exec();
×
584
    if (result == QDialog::Rejected)
×
585
    {
586
        slotColorSelectorChanged(color); // reset color to what it previously was
×
587
    }
588
}
×
589

590
void SceneEditor::slotPositionTool()
×
591
{
592
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
593
    if (fc != NULL)
×
594
    {
595
        QList<SceneValue> origValues = fc->values();
×
596

597
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
598
        QPointF pos;
×
599
        QRectF range;
×
600
        bool panFound = false;
×
601
        bool tiltFound = false;
×
602

603
        Q_ASSERT(fxi != NULL);
×
604

605
        for (int i = 0; i < fxi->heads(); ++i)
×
606
        {
607
             if (!range.isValid())
×
608
                 range = fxi->degreesRange(i);
×
609

610
             quint32 panMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i);
×
611
             quint32 panLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, i);
×
612
             quint32 tiltMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i);
×
613
             quint32 tiltLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, i);
×
614

615
             if (panMsbChannel != QLCChannel::invalid())
×
616
             {
617
                 if (!panFound)
×
618
                 {
619
                     qDebug() << "panFound" << i;
×
620
                     panFound = true;
×
621
                     qreal v = qreal(fc->value(panMsbChannel));
×
622
                     if (panLsbChannel != QLCChannel::invalid())
×
623
                     {
624
                        v += qreal(fc->value(panLsbChannel)) / qreal(256);
×
625
                     }
626

627
                     pos.setX(v);
×
628
                 }
629
             }
630

631
             if (tiltMsbChannel != QLCChannel::invalid())
×
632
             {
633
                 if (!tiltFound)
×
634
                 {
635
                     tiltFound = true;
×
636
                     qDebug() << "tiltFound" << i;
×
637
                     qreal v = qreal(fc->value(tiltMsbChannel));
×
638
                     if (tiltLsbChannel != QLCChannel::invalid())
×
639
                     {
640
                        v += qreal(fc->value(tiltLsbChannel)) / qreal(256);
×
641
                     }
642

643
                     pos.setY(v);
×
644
                 }
645
             }
646
        }
647

648
        PositionTool dialog(pos, range);
×
649
        connect(&dialog, SIGNAL(currentPositionChanged(const QPointF&)),
×
650
            this, SLOT(slotPositionSelectorChanged(const QPointF&)));
651

652
        int result = dialog.exec();
×
653
        if (result == QDialog::Rejected)
×
654
        {
655
            fc->setValues(origValues, false); // reset position to what it previously was
×
656
        }
657
    }
×
658
}
×
659

660
QColor SceneEditor::slotColorSelectorChanged(const QColor& color)
×
661
{
662
    QColor returnColor = QColor();
×
663

664
    /* QObject cast fails unless the widget is a FixtureConsole */
665
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
666
    if (fc != NULL)
×
667
    {
668
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
669
        Q_ASSERT(fxi != NULL);
×
670

671
        QSet <quint32> cyan    = fxi->channels(QLCChannel::Intensity, QLCChannel::Cyan);
×
672
        QSet <quint32> magenta = fxi->channels(QLCChannel::Intensity, QLCChannel::Magenta);
×
673
        QSet <quint32> yellow  = fxi->channels(QLCChannel::Intensity, QLCChannel::Yellow);
×
674
        QSet <quint32> red     = fxi->channels(QLCChannel::Intensity, QLCChannel::Red);
×
675
        QSet <quint32> green   = fxi->channels(QLCChannel::Intensity, QLCChannel::Green);
×
676
        QSet <quint32> blue    = fxi->channels(QLCChannel::Intensity, QLCChannel::Blue);
×
677

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

692
                foreach (quint32 ch, magenta)
×
693
                {
694
                    fc->setChecked(true, ch);
×
695
                    fc->setValue(ch, color.magenta());
×
696
                }
×
697

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

712
            if (color.isValid() == true)
×
713
            {
714
                foreach (quint32 ch, red)
×
715
                {
716
                    fc->setChecked(true, ch);
×
717
                    fc->setValue(ch, color.red());
×
718
                }
×
719

720
                foreach (quint32 ch, green)
×
721
                {
722
                    fc->setChecked(true, ch);
×
723
                    fc->setValue(ch, color.green());
×
724
                }
×
725

726
                foreach (quint32 ch, blue)
×
727
                {
728
                    fc->setChecked(true, ch);
×
729
                    fc->setValue(ch, color.blue());
×
730
                }
×
731
            }
732
        }
733
        return returnColor;
×
734
    }
×
735

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

763
    return returnColor;
×
764
}
765

766
void SceneEditor::slotPositionSelectorChanged(const QPointF& position)
×
767
{
768
    qreal x = position.x();
×
769
    qreal y = position.y();
×
770

771
    uchar panMsbNew = x;
×
772
    uchar panLsbNew = (x - floor(x)) * 256;
×
773
    uchar tiltMsbNew = y;
×
774
    uchar tiltLsbNew = (y - floor(y)) * 256;
×
775

776
    /* QObject cast fails unless the widget is a FixtureConsole */
777
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
778
    if (fc != NULL)
×
779
    {
780
        Fixture* fxi = m_doc->fixture(fc->fixture());
×
781
        Q_ASSERT(fxi != NULL);
×
782

783
        for (int i = 0; i < fxi->heads(); ++i)
×
784
        {
785
             quint32 panMsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i);
×
786
             quint32 panLsbChannel = fxi->channelNumber(QLCChannel::Pan, QLCChannel::LSB, i);
×
787
             quint32 tiltMsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i);
×
788
             quint32 tiltLsbChannel = fxi->channelNumber(QLCChannel::Tilt, QLCChannel::LSB, i);
×
789

790
             if (panMsbChannel != QLCChannel::invalid())
×
791
             {
792
                 fc->setChecked(true, panMsbChannel);
×
793
                 fc->setValue(panMsbChannel, panMsbNew);
×
794

795
                 if (panLsbChannel != QLCChannel::invalid())
×
796
                 {
797
                     fc->setChecked(true, panLsbChannel);
×
798
                     fc->setValue(panLsbChannel, panLsbNew);
×
799
                 }
800
             }
801

802
             if (tiltMsbChannel != QLCChannel::invalid())
×
803
             {
804
                 fc->setChecked(true, tiltMsbChannel);
×
805
                 fc->setValue(tiltMsbChannel, tiltMsbNew);
×
806

807
                 if (tiltLsbChannel != QLCChannel::invalid())
×
808
                 {
809
                     fc->setChecked(true, tiltLsbChannel);
×
810
                     fc->setValue(tiltLsbChannel, tiltLsbNew);
×
811
                 }
812
             }
813
        }
814
    }
815

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

843
void SceneEditor::slotSpeedDialToggle(bool state)
×
844
{
845
    if (state == true)
×
846
    {
847
        createSpeedDials();
×
848
    }
849
    else
850
    {
851
        if (m_speedDials != NULL)
×
852
            m_speedDials->deleteLater();
×
853
        m_speedDials = NULL;
×
854
    }
855

856
    m_scene->setUiStateValue(UI_STATE_SHOW_DIAL, state);
×
857
}
×
858

859
void SceneEditor::slotBlindToggled(bool state)
×
860
{
861
    if (m_doc->mode() == Doc::Operate)
×
862
    {
863
        delete m_source;
×
864
        m_source = NULL;
×
865

866
        if (m_scene != NULL && !m_scene->isRunning())
×
867
        {
868
            m_source = new GenericDMXSource(m_doc);
×
869
            foreach (SceneValue scv, m_scene->values())
×
870
                m_source->set(scv.fxi, scv.channel, scv.value);
×
871
        }
872
    }
873
    else
874
    {
875
        if (m_source == NULL)
×
876
            m_source = new GenericDMXSource(m_doc);
×
877
    }
878

879
    if (m_source != NULL)
×
880
        m_source->setOutputEnabled(!state);
×
881
}
×
882

883
void SceneEditor::slotModeChanged(Doc::Mode mode)
×
884
{
885
    if (mode == Doc::Operate)
×
886
    {
887
        m_blindAction->setChecked(true);
×
888
        slotBlindToggled(true);
×
889
    }
890
    else
891
    {
892
        m_blindAction->setChecked(false);
×
893
        slotBlindToggled(false);
×
894
    }
895

896
}
×
897

898
void SceneEditor::slotViewModeChanged(bool tabbed, bool applyValues)
×
899
{
NEW
900
    setTabMode(tabbed);
×
901

902
    m_tab->blockSignals(true);
×
903
    for (int i = m_tab->count() - 1; i >= m_fixtureFirstTabIndex; i--)
×
904
    {
905
        QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(i));
×
906
        Q_ASSERT(area != NULL);
×
907
        m_tab->removeTab(i);
×
908
        delete area; // Deletes also FixtureConsole
×
909
    }
910
    m_consoleList.clear();
×
911
    m_tab->blockSignals(false);
×
912

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

921
            scrollArea->setWidgetResizable(true);
×
922
            int tIdx = m_tab->addTab(scrollArea, tr("All fixtures"));
×
923
            m_tab->setTabToolTip(tIdx, tr("All fixtures"));
×
924

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

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

946
                connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
947
                        this, SLOT(slotValueChanged(quint32,quint32,uchar)));
948
                connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
949
                        this, SLOT(slotChecked(quint32,quint32,bool)));
950

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

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

977
            addFixtureTab(fixture);
×
978

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

991
    if (m_tab->count() == 0)
×
992
    {
993
        slotTabChanged(KTabGeneral);
×
994
    }
995
    else
996
    {
997
        QVariant tabIndex = m_scene->uiStateValue(UI_STATE_TAB_INDEX);
×
998
        int prevTabIdx = tabIndex.isValid() ? tabIndex.toInt() : 0;
×
999
        if (prevTabIdx > m_tab->count())
×
1000
            m_tab->setCurrentIndex(m_fixtureFirstTabIndex);
×
1001
        else
1002
            m_tab->setCurrentIndex(prevTabIdx);
×
1003
    }
×
1004

1005
    m_scene->setUiStateValue(UI_STATE_TAB_INDEX, m_tab->currentIndex());
×
1006
}
×
1007

1008
void SceneEditor::slotRecord()
×
1009
{
1010
    Chaser* chaser = selectedChaser();
×
1011
    if (chaser == NULL)
×
1012
        return;
×
1013

1014
    QString name = chaser->name() + QString(" - %1").arg(chaser->steps().size() + 1);
×
1015
    Scene* clone = new Scene(m_doc);
×
1016
    clone->copyFrom(m_scene);
×
1017
    clone->setName(name);
×
1018
    m_doc->addFunction(clone);
×
1019
    chaser->addStep(ChaserStep(clone->id()));
×
1020

1021
    // Switch to the cloned scene
1022
    FunctionManager::instance()->selectFunction(clone->id());
×
1023
}
×
1024

1025
void SceneEditor::slotChaserComboActivated(int index)
×
1026
{
1027
    quint32 id = m_chaserCombo->itemData(index).toUInt();
×
1028
    if (id == Function::invalidId())
×
1029
        m_recordAction->setEnabled(false);
×
1030
    else
1031
        m_recordAction->setEnabled(true);
×
1032
}
×
1033

1034
bool SceneEditor::isColorToolAvailable()
×
1035
{
1036
    Fixture* fxi = NULL;
×
1037
    quint32 cyan = QLCChannel::invalid(), magenta = QLCChannel::invalid(), yellow = QLCChannel::invalid();
×
1038
    quint32 red = QLCChannel::invalid(), green = QLCChannel::invalid(), blue = QLCChannel::invalid();
×
1039

1040
    /* QObject cast fails unless the widget is a FixtureConsole */
1041
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
1042
    if (fc != NULL)
×
1043
    {
1044
        fxi = m_doc->fixture(fc->fixture());
×
1045
        Q_ASSERT(fxi != NULL);
×
1046

1047
        cyan = fxi->channel(QLCChannel::Intensity, QLCChannel::Cyan);
×
1048
        magenta = fxi->channel(QLCChannel::Intensity, QLCChannel::Magenta);
×
1049
        yellow = fxi->channel(QLCChannel::Intensity, QLCChannel::Yellow);
×
1050
        red = fxi->channel(QLCChannel::Intensity, QLCChannel::Red);
×
1051
        green = fxi->channel(QLCChannel::Intensity, QLCChannel::Green);
×
1052
        blue = fxi->channel(QLCChannel::Intensity, QLCChannel::Blue);
×
1053
    }
1054

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

1082
    if (cyan != QLCChannel::invalid() && magenta != QLCChannel::invalid() &&
×
1083
        yellow != QLCChannel::invalid())
×
1084
    {
1085
        return true;
×
1086
    }
1087
    else if (red != QLCChannel::invalid() && green != QLCChannel::invalid() &&
×
1088
             blue != QLCChannel::invalid())
×
1089
    {
1090
        return true;
×
1091
    }
1092
    else
1093
    {
1094
        return false;
×
1095
    }
1096
}
1097

1098
bool SceneEditor::isPositionToolAvailable()
×
1099
{
1100
    Fixture* fxi = NULL;
×
1101

1102
    /* QObject cast fails unless the widget is a FixtureConsole */
1103
    FixtureConsole* fc = fixtureConsoleTab(m_currentTab);
×
1104
    if (fc != NULL)
×
1105
    {
1106
        fxi = m_doc->fixture(fc->fixture());
×
1107
        Q_ASSERT(fxi != NULL);
×
1108

1109
        for (int i = 0; i < fxi->heads(); ++i)
×
1110
        {
1111
            if (fxi->channelNumber(QLCChannel::Pan, QLCChannel::MSB, i) != QLCChannel::invalid())
×
1112
                return true;
×
1113
            if (fxi->channelNumber(QLCChannel::Tilt, QLCChannel::MSB, i) != QLCChannel::invalid())
×
1114
                return true;
×
1115
        }
1116
    }
1117

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

1131
    return false;
×
1132
}
1133

1134
void SceneEditor::createSpeedDials()
×
1135
{
1136
    if (m_speedDials != NULL)
×
1137
        return;
×
1138

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

1152
void SceneEditor::slotDialDestroyed(QObject *)
×
1153
{
1154
    m_speedDialAction->setChecked(false);
×
1155
}
×
1156

1157
Chaser* SceneEditor::selectedChaser() const
×
1158
{
1159
    QVariant var = m_chaserCombo->itemData(m_chaserCombo->currentIndex());
×
1160
    if (var.isValid() == false)
×
1161
        return NULL;
×
1162
    else
1163
        return qobject_cast<Chaser*> (m_doc->function(var.toUInt()));
×
1164
}
×
1165

1166
/*****************************************************************************
1167
 * General page
1168
 *****************************************************************************/
1169

1170
QTreeWidgetItem* SceneEditor::fixtureItem(quint32 fxi_id)
×
1171
{
1172
    QTreeWidgetItemIterator it(m_tree);
×
1173
    while (*it != NULL)
×
1174
    {
1175
        QTreeWidgetItem* item = *it;
×
1176
        if (item->text(KColumnID).toUInt() == fxi_id)
×
1177
            return item;
×
1178
        ++it;
×
1179
    }
1180

1181
    return NULL;
×
1182
}
×
1183

NEW
1184
QList <Fixture*> SceneEditor::selectedFixtures(bool showAll) const
×
1185
{
NEW
1186
    QListIterator <QTreeWidgetItem*> it(showAll ? m_tree->findItems(QStringLiteral("*"), Qt::MatchWrap | Qt::MatchWildcard | Qt::MatchRecursive) : m_tree->selectedItems());
×
1187

UNCOV
1188
    QList <Fixture*> list;
×
1189

1190
    while (it.hasNext() == true)
×
1191
    {
1192
        QTreeWidgetItem* item;
1193
        quint32 fxi_id;
1194
        Fixture* fixture;
1195

1196
        item = it.next();
×
1197
        fxi_id = item->text(KColumnID).toInt();
×
1198
        fixture = m_doc->fixture(fxi_id);
×
1199
        Q_ASSERT(fixture != NULL);
×
1200

1201
        list.append(fixture);
×
1202
    }
1203

1204
    return list;
×
1205
}
×
1206

1207
bool SceneEditor::addFixtureItem(Fixture* fixture)
×
1208
{
1209
    Q_ASSERT(fixture != NULL);
×
1210

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

1223
    QTreeWidgetItem* item;
1224

1225
    item = new QTreeWidgetItem(m_tree);
×
1226
    item->setText(KColumnName, fixture->name());
×
1227
    item->setText(KColumnID, QString("%1").arg(fixture->id()));
×
1228

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

1241
    /* Select newly-added fixtures so that their channels can be
1242
       quickly disabled/enabled */
1243
    item->setSelected(true);
×
1244

1245
    return true;
×
1246
}
1247

1248
void SceneEditor::removeFixtureItem(quint32 fixtureID)
×
1249
{
1250
    QTreeWidgetItem *item;
1251

1252
    item = fixtureItem(fixtureID);
×
1253
    delete item;
×
1254
}
×
1255

1256
void SceneEditor::slotNameEdited(const QString& name)
×
1257
{
1258
    m_scene->setName(name);
×
1259
    if (m_speedDials != NULL)
×
1260
        m_speedDials->setWindowTitle(m_scene->name());
×
1261
}
×
1262

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

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

1287
            if (!m_scene->fixtures().contains(fixture->id()))
×
1288
            {
1289
                addFixtureItem(fixture);
×
1290
                addFixtureTab(fixture);
×
1291

1292
                // Add fixture in scene
1293
                m_scene->addFixture(fixture->id());
×
1294
            }
1295
        }
1296
    }
×
1297
}
×
1298

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

1306
    if (r == QMessageBox::Yes)
×
1307
    {
1308
        QListIterator <Fixture*> it(selectedFixtures());
×
1309
        while (it.hasNext() == true)
×
1310
        {
1311
            Fixture* fixture = it.next();
×
1312
            Q_ASSERT(fixture != NULL);
×
1313

1314
            removeFixtureTab(fixture->id());
×
1315
            removeFixtureItem(fixture->id());
×
1316

1317
            /* Remove all values associated to the fixture */
1318
            for (quint32 i = 0; i < fixture->channels(); i++)
×
1319
                m_scene->unsetValue(fixture->id(), i);
×
1320

1321
            // Remove fixture from scene
1322
            m_scene->removeFixture(fixture->id());
×
1323
        }
1324
    }
×
1325
}
×
1326

1327
void SceneEditor::slotEnableAll()
×
1328
{
1329
    foreach (FixtureConsole* fc, m_consoleList)
×
1330
    {
1331
        if (fc != NULL)
×
1332
            fc->setChecked(true);
×
1333
    }
×
1334
}
×
1335

1336
void SceneEditor::slotDisableAll()
×
1337
{
1338
    foreach (FixtureConsole* fc, m_consoleList)
×
1339
    {
1340
        if (fc != NULL)
×
1341
            fc->setChecked(false);
×
1342
    }
×
1343
}
×
1344

1345
void SceneEditor::slotFadeInChanged(int ms)
×
1346
{
1347
    m_scene->setFadeInSpeed(ms);
×
1348
}
×
1349

1350
void SceneEditor::slotFadeOutChanged(int ms)
×
1351
{
1352
    m_scene->setFadeOutSpeed(ms);
×
1353
}
×
1354

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

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

1373
void SceneEditor::slotChannelGroupsChanged(QTreeWidgetItem *item, int column)
×
1374
{
1375
    if (item == NULL)
×
1376
        return;
×
1377

1378
    quint32 grpID = item->data(column, Qt::UserRole).toUInt();
×
1379
    ChannelsGroup *grp = m_doc->channelsGroup(grpID);
×
1380
    if (grp == NULL)
×
1381
        return;
×
1382

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

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

1411
    updateChannelsGroupsTab();
×
1412
}
1413

1414
/*********************************************************************
1415
 * Channels groups tabs
1416
 *********************************************************************/
1417
void SceneEditor::updateChannelsGroupsTab()
×
1418
{
1419
    QScrollArea* scrollArea = NULL;
×
1420
    QList <quint32> ids = m_scene->channelGroups();
×
1421

1422
    if (m_channelGroupsTree->topLevelItemCount() == 0)
×
1423
    {
1424
        m_fixtureFirstTabIndex = 1;
×
1425
        return;
×
1426
    }
1427

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

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

1461
    m_channelGroupsTab = 1;
×
1462
    m_fixtureFirstTabIndex = 2;
×
1463
    connect(console, SIGNAL(groupValueChanged(quint32,uchar)),
×
1464
            this, SLOT(slotGroupValueChanged(quint32,uchar)));
1465
}
×
1466

1467
GroupsConsole *SceneEditor::groupConsoleTab(int tab)
×
1468
{
1469
    if (tab != m_channelGroupsTab)
×
1470
        return NULL;
×
1471

1472
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1473
    Q_ASSERT(area != NULL);
×
1474

1475
    return qobject_cast<GroupsConsole*> (area->widget());
×
1476
}
1477

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

1501
/*****************************************************************************
1502
 * Fixture tabs
1503
 *****************************************************************************/
1504

1505
FixtureConsole* SceneEditor::fixtureConsole(Fixture* fixture)
×
1506
{
1507
    Q_ASSERT(fixture != NULL);
×
1508

1509
    if (m_consoleList.contains(fixture->id()))
×
1510
        return m_consoleList[fixture->id()];
×
1511

1512
    return NULL;
×
1513
}
1514

1515
void SceneEditor::addFixtureTab(Fixture* fixture, quint32 channel)
×
1516
{
1517
    Q_ASSERT(fixture != NULL);
×
NEW
1518
    Q_ASSERT(m_tab != NULL);
×
1519

NEW
1520
    if (tabMode())
×
1521
    {
1522
        /* Put the console inside a scroll area */
NEW
1523
        QScrollArea* scrollArea = new QScrollArea(m_tab);
×
NEW
1524
        scrollArea->setWidgetResizable(true);
×
1525

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

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

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

NEW
1541
        if (channel != QLCChannel::invalid())
×
NEW
1542
            console->setChecked(true, channel);
×
1543
    }
1544
    else
1545
    {
NEW
1546
        QScrollArea* scrollArea = qobject_cast<QScrollArea*>(m_tab->widget(m_fixtureFirstTabIndex));
×
NEW
1547
        if (scrollArea == NULL)
×
1548
        {
NEW
1549
            scrollArea = new QScrollArea(m_tab);
×
NEW
1550
            scrollArea->setWidgetResizable(true);
×
NEW
1551
            int tIdx = m_tab->addTab(scrollArea, tr("All fixtures"));
×
NEW
1552
            m_tab->setTabToolTip(tIdx, tr("All fixtures"));
×
1553
        }
1554

NEW
1555
        QGroupBox* grpBox = qobject_cast<QGroupBox*>(scrollArea->widget());
×
NEW
1556
        if (grpBox == NULL)
×
1557
        {
NEW
1558
            grpBox = new QGroupBox(scrollArea);
×
NEW
1559
            grpBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
×
NEW
1560
            scrollArea->setWidget(grpBox);
×
1561
        }
1562

NEW
1563
        QHBoxLayout* fixturesLayout = qobject_cast<QHBoxLayout*>(grpBox->layout());
×
NEW
1564
        if (fixturesLayout == NULL)
×
1565
        {
NEW
1566
            fixturesLayout = new QHBoxLayout(grpBox);
×
NEW
1567
            grpBox->setLayout(fixturesLayout);
×
NEW
1568
            fixturesLayout->setSpacing(2);
×
NEW
1569
            fixturesLayout->setContentsMargins(0, 2, 2, 2);
×
NEW
1570
            fixturesLayout->addStretch(1);
×
1571
        }
1572

NEW
1573
        const FixtureConsole::GroupType type = ((selectedFixtures(true).count() % 2) == 0) ? FixtureConsole::GroupOdd : FixtureConsole::GroupEven;
×
NEW
1574
        FixtureConsole* console = new FixtureConsole(scrollArea, m_doc, type);
×
NEW
1575
        console->setFixture(fixture->id());
×
NEW
1576
        m_consoleList[fixture->id()] = console;
×
1577

1578
        /* Start off with all channels disabled */
NEW
1579
        console->setChecked(false);
×
1580

NEW
1581
        connect(console, SIGNAL(valueChanged(quint32,quint32,uchar)),
×
1582
                this, SLOT(slotValueChanged(quint32,quint32,uchar)));
NEW
1583
        connect(console, SIGNAL(checked(quint32,quint32,bool)),
×
1584
                this, SLOT(slotChecked(quint32,quint32,bool)));
1585

NEW
1586
        if (channel != QLCChannel::invalid())
×
NEW
1587
            console->setChecked(true, channel);
×
1588

NEW
1589
        fixturesLayout->insertWidget(fixturesLayout->count()-1, console);
×
1590
    }
UNCOV
1591
}
×
1592

1593
void SceneEditor::removeFixtureTab(quint32 fixtureID)
×
1594
{
NEW
1595
    Q_ASSERT(m_tab != NULL);
×
1596

NEW
1597
    if (tabMode())
×
1598
    {
1599
        /* Start searching from the first fixture tab */
NEW
1600
        for (int i = m_fixtureFirstTabIndex; i < m_tab->count(); i++)
×
1601
        {
NEW
1602
            FixtureConsole* fc = fixtureConsoleTab(i);
×
NEW
1603
            if (fc != NULL && fc->fixture() == fixtureID)
×
1604
            {
1605
                /* First remove the tab because otherwise Qt might
1606
                   remove two tabs -- undocumented feature, which
1607
                   might be intended or it might not. */
NEW
1608
                QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(i));
×
NEW
1609
                Q_ASSERT(area != NULL);
×
NEW
1610
                m_tab->removeTab(i);
×
NEW
1611
                m_consoleList.take(fixtureID);
×
NEW
1612
                delete area; // Deletes also FixtureConsole
×
1613

NEW
1614
                break;
×
1615
            }
1616
        }
1617
    }
1618
    else
1619
    {
NEW
1620
        QScrollArea* area = qobject_cast<QScrollArea*>(m_tab->widget(m_fixtureFirstTabIndex));
×
NEW
1621
        if (area == NULL)
×
NEW
1622
            return;
×
1623

NEW
1624
        QGroupBox* grpBox = qobject_cast<QGroupBox*>(area->widget());
×
NEW
1625
        if (grpBox == NULL)
×
NEW
1626
            return;
×
1627

NEW
1628
        QHBoxLayout* fixturesLayout = qobject_cast<QHBoxLayout*>(grpBox->layout());
×
NEW
1629
        if (fixturesLayout == NULL)
×
NEW
1630
            return;
×
1631

NEW
1632
        for (int i = 0; i < fixturesLayout->count(); i++)
×
1633
        {
NEW
1634
            QLayoutItem* layoutItem = fixturesLayout->itemAt(i);
×
NEW
1635
            if (layoutItem == NULL)
×
NEW
1636
                continue;
×
1637

NEW
1638
            FixtureConsole* console = qobject_cast<FixtureConsole*>(layoutItem->widget());
×
1639

NEW
1640
            if (console != NULL && console->fixture() == fixtureID)
×
1641
            {
NEW
1642
                console->hide();
×
NEW
1643
                QLayoutItem* deleteLayoutItem = fixturesLayout->takeAt(i);
×
1644
                // Q_ASSERT(deleteLayoutItem == layoutItem);
1645

NEW
1646
                m_consoleList.take(console->fixture());
×
1647

NEW
1648
                delete console;
×
NEW
1649
                delete deleteLayoutItem;
×
1650

NEW
1651
                break;
×
1652
            }
1653
        }
1654
    }
1655
}
1656

1657
FixtureConsole* SceneEditor::fixtureConsoleTab(int tab)
×
1658
{
1659
    if (tab >= m_tab->count() || tab <= 0)
×
1660
        return NULL;
×
1661

1662
    QScrollArea* area = qobject_cast<QScrollArea*> (m_tab->widget(tab));
×
1663
    Q_ASSERT(area != NULL);
×
1664

1665
    return qobject_cast<FixtureConsole*> (area->widget());
×
1666
}
1667

1668
void SceneEditor::setTabChannelState(bool status, Fixture *fixture, quint32 channel)
×
1669
{
1670
    Q_ASSERT(fixture != NULL);
×
1671

1672
    if (channel == QLCChannel::invalid())
×
1673
        return;
×
1674

1675
    if (m_consoleList.contains(fixture->id()))
×
1676
        m_consoleList[fixture->id()]->setChecked(status, channel);
×
1677
}
1678

1679
void SceneEditor::slotValueChanged(quint32 fxi, quint32 channel, uchar value)
×
1680
{
1681
    // Don't modify m_scene contents when doing initialization
1682
    if (m_initFinished == true)
×
1683
    {
1684
        Q_ASSERT(m_scene != NULL);
×
1685

1686
        if (m_doc->mode() == Doc::Operate)
×
1687
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), false);
×
1688
        else
1689
            m_scene->setValue(SceneValue(fxi, channel, value), m_blindAction->isChecked(), true);
×
1690
        emit fixtureValueChanged(SceneValue(fxi, channel, value), true);
×
1691
    }
1692

1693
    if (m_source != NULL)
×
1694
        m_source->set(fxi, channel, value);
×
1695
}
×
1696

1697
void SceneEditor::slotChecked(quint32 fxi, quint32 channel, bool state)
×
1698
{
1699
    // Don't modify m_scene contents when doing initialization
1700
    if (m_initFinished == true)
×
1701
    {
1702
        // When a channel is enabled, its current value is emitted with valueChanged().
1703
        // So, state == true case doesn't need to be handled here.
1704
        Q_ASSERT(m_scene != NULL);
×
1705
        if (state == false)
×
1706
        {
1707
            m_scene->unsetValue(fxi, channel);
×
1708
            if (m_source != NULL)
×
1709
            {
1710
                m_source->unset(fxi, channel);
×
1711
                emit fixtureValueChanged(SceneValue(fxi, channel, 0), false);
×
1712
            }
1713
        }
1714
    }
1715
}
×
1716

1717
void SceneEditor::slotGoToNextTab()
×
1718
{
1719
    m_currentTab++;
×
1720
    if (m_currentTab == m_tab->count())
×
1721
        m_currentTab = 0;
×
1722
    m_tab->setCurrentIndex(m_currentTab);
×
1723
}
×
1724

1725
void SceneEditor::slotGoToPreviousTab()
×
1726
{
1727
    if (m_currentTab == 0)
×
1728
        m_currentTab = m_tab->count() - 1;
×
1729
    else
1730
        m_currentTab--;
×
1731
    m_tab->setCurrentIndex(m_currentTab);
×
1732
}
×
1733

NEW
1734
bool SceneEditor::tabMode() const
×
1735
{
NEW
1736
    if (m_scene == NULL)
×
NEW
1737
        return true;
×
1738

NEW
1739
    QVariant tabMode = m_scene->uiStateValue(UI_STATE_TAB_MODE);
×
NEW
1740
    if (tabMode.isNull() || tabMode.toInt() == UI_STATE_TABBED_FIXTURES)
×
NEW
1741
        return true;
×
1742
    else
NEW
1743
        return false;
×
NEW
1744
}
×
1745

NEW
1746
void SceneEditor::setTabMode(bool tabbed)
×
1747
{
NEW
1748
    if (m_scene == NULL)
×
NEW
1749
        return;
×
1750

NEW
1751
    m_scene->setUiStateValue(UI_STATE_TAB_MODE, tabbed ? UI_STATE_TABBED_FIXTURES : UI_STATE_ALL_FIXTURES);
×
1752
}
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