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

mcallegari / qlcplus / 24625965106

19 Apr 2026 09:32AM UTC coverage: 34.068% (-0.001%) from 34.069%
24625965106

Pull #1993

github

web-flow
Merge 182e78ca1 into 49eff021c
Pull Request #1993: ui/virtualconsole: fix background colour issues

1 of 4 new or added lines in 1 file covered. (25.0%)

3 existing lines in 1 file now uncovered.

17760 of 52131 relevant lines covered (34.07%)

82372.06 hits per line

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

47.08
/ui/src/virtualconsole/virtualconsole.cpp
1
/*
2
  Q Light Controller Plus
3
  virtualconsole.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

8
  Licensed under the Apache License, Version 2.0 (the "License");
9
  you may not use this file except in compliance with the License.
10
  You may obtain a copy of the License at
11

12
      http://www.apache.org/licenses/LICENSE-2.0.txt
13

14
  Unless required by applicable law or agreed to in writing, software
15
  distributed under the License is distributed on an "AS IS" BASIS,
16
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
  See the License for the specific language governing permissions and
18
  limitations under the License.
19
*/
20

21
#include <QXmlStreamReader>
22
#include <QXmlStreamWriter>
23
#include <QApplication>
24
#include <QInputDialog>
25
#include <QColorDialog>
26
#include <QActionGroup>
27
#include <QHBoxLayout>
28
#include <QVBoxLayout>
29
#include <QMessageBox>
30
#include <QFileDialog>
31
#include <QFontDialog>
32
#include <QScrollArea>
33
#include <QSettings>
34
#include <QKeyEvent>
35
#include <QMenuBar>
36
#include <QToolBar>
37
#include <QString>
38
#include <QDebug>
39
#include <QMenu>
40
#include <QList>
41

42
#include "vcpropertieseditor.h"
43
#include "addvcbuttonmatrix.h"
44
#include "addvcslidermatrix.h"
45
#include "vcaudiotriggers.h"
46
#include "virtualconsole.h"
47
#include "vcproperties.h"
48
#include "vcspeeddial.h"
49
#include "vcsoloframe.h"
50
#include "vcdockarea.h"
51
#include "vccuelist.h"
52
#include "vcbutton.h"
53
#include "vcslider.h"
54
#include "vcmatrix.h"
55
#include "vcframe.h"
56
#include "vclabel.h"
57
#include "vcxypad.h"
58
#include "vcclock.h"
59
#include "functionwizard.h"
60
#include "doc.h"
61

62
#define SETTINGS_VC_SIZE "virtualconsole/size"
63

64
VirtualConsole* VirtualConsole::s_instance = NULL;
65

66
/****************************************************************************
67
 * Initialization
68
 ****************************************************************************/
69

70
VirtualConsole::VirtualConsole(QWidget* parent, Doc* doc)
152✔
71
    : QWidget(parent)
72
    , m_doc(doc)
152✔
73
    , m_latestWidgetId(0)
152✔
74

75
    , m_editAction(EditNone)
152✔
76
    , m_toolbar(NULL)
152✔
77

78
    , m_addActionGroup(NULL)
152✔
79
    , m_editActionGroup(NULL)
152✔
80
    , m_bgActionGroup(NULL)
152✔
81
    , m_fgActionGroup(NULL)
152✔
82
    , m_fontActionGroup(NULL)
152✔
83
    , m_frameActionGroup(NULL)
152✔
84
    , m_stackingActionGroup(NULL)
152✔
85

86
    , m_addButtonAction(NULL)
152✔
87
    , m_addButtonMatrixAction(NULL)
152✔
88
    , m_addSliderAction(NULL)
152✔
89
    , m_addSliderMatrixAction(NULL)
152✔
90
    , m_addKnobAction(NULL)
152✔
91
    , m_addSpeedDialAction(NULL)
152✔
92
    , m_addXYPadAction(NULL)
152✔
93
    , m_addCueListAction(NULL)
152✔
94
    , m_addFrameAction(NULL)
152✔
95
    , m_addSoloFrameAction(NULL)
152✔
96
    , m_addLabelAction(NULL)
152✔
97
    , m_addAudioTriggersAction(NULL)
152✔
98
    , m_addClockAction(NULL)
152✔
99
    , m_addAnimationAction(NULL)
152✔
100

101
    , m_toolsSettingsAction(NULL)
152✔
102
    , m_functionWizardAction(NULL)
152✔
103

104
    , m_editCutAction(NULL)
152✔
105
    , m_editCopyAction(NULL)
152✔
106
    , m_editPasteAction(NULL)
152✔
107
    , m_editDeleteAction(NULL)
152✔
108
    , m_editPropertiesAction(NULL)
152✔
109
    , m_editRenameAction(NULL)
152✔
110

111
    , m_bgColorAction(NULL)
152✔
112
    , m_bgImageAction(NULL)
152✔
113
    , m_bgDefaultAction(NULL)
152✔
114

115
    , m_fgColorAction(NULL)
152✔
116
    , m_fgDefaultAction(NULL)
152✔
117

118
    , m_fontAction(NULL)
152✔
119
    , m_resetFontAction(NULL)
152✔
120

121
    , m_frameSunkenAction(NULL)
152✔
122
    , m_frameRaisedAction(NULL)
152✔
123
    , m_frameNoneAction(NULL)
152✔
124

125
    , m_stackingRaiseAction(NULL)
152✔
126
    , m_stackingLowerAction(NULL)
152✔
127

128
    , m_customMenu(NULL)
152✔
129
    , m_editMenu(NULL)
152✔
130
    , m_addMenu(NULL)
152✔
131

132
    , m_dockArea(NULL)
152✔
133
    , m_contentsLayout(NULL)
152✔
134
    , m_scrollArea(NULL)
152✔
135
    , m_contents(NULL)
152✔
136

137
    , m_liveEdit(false)
152✔
138
{
139
    Q_ASSERT(s_instance == NULL);
152✔
140
    s_instance = this;
152✔
141

142
    Q_ASSERT(doc != NULL);
152✔
143

144
    /* Main layout */
145
    new QHBoxLayout(this);
152✔
146
    layout()->setContentsMargins(1, 1, 1, 1);
152✔
147
    layout()->setSpacing(1);
152✔
148

149
    initActions();
152✔
150
    initDockArea();
152✔
151
    m_contentsLayout = new QVBoxLayout;
152✔
152
    layout()->addItem(m_contentsLayout);
152✔
153
    initMenuBar();
152✔
154
    initContents();
152✔
155

156
    // Propagate mode changes to all widgets
157
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)),
152✔
158
            this, SLOT(slotModeChanged(Doc::Mode)));
159

160
    // Use the initial mode
161
    slotModeChanged(m_doc->mode());
152✔
162

163
    // Nothing is selected
164
    updateActions();
152✔
165
}
152✔
166

167
VirtualConsole::~VirtualConsole()
304✔
168
{
169
    s_instance = NULL;
152✔
170
}
304✔
171

172
VirtualConsole* VirtualConsole::instance()
1,948✔
173
{
174
    return s_instance;
1,948✔
175
}
176

177
Doc *VirtualConsole::getDoc()
×
178
{
179
    return m_doc;
×
180
}
181

182
quint32 VirtualConsole::newWidgetId()
2✔
183
{
184
    /* This results in an endless loop if there are UINT_MAX-1 widgets. That,
185
       however, seems a bit unlikely. */
186
    while (m_widgetsMap.contains(m_latestWidgetId) ||
4✔
187
           m_latestWidgetId == VCWidget::invalidId())
2✔
188
    {
189
        m_latestWidgetId++;
×
190
    }
191

192
    return m_latestWidgetId;
2✔
193
}
194

195
/*****************************************************************************
196
 * Properties
197
 *****************************************************************************/
198

199
VCProperties VirtualConsole::properties() const
612✔
200
{
201
    return m_properties;
612✔
202
}
203

204
/*****************************************************************************
205
 * Selected widget
206
 *****************************************************************************/
207

208
void VirtualConsole::setEditAction(VirtualConsole::EditAction action)
×
209
{
210
    m_editAction = action;
×
211
}
×
212

213
VirtualConsole::EditAction VirtualConsole::editAction() const
×
214
{
215
    return m_editAction;
×
216
}
217

218
const QList <VCWidget*> VirtualConsole::selectedWidgets() const
10✔
219
{
220
    return m_selectedWidgets;
10✔
221
}
222

223
void VirtualConsole::setWidgetSelected(VCWidget* widget, bool select)
8✔
224
{
225
    Q_ASSERT(widget != NULL);
8✔
226

227
    if (select == false)
8✔
228
    {
229
        m_selectedWidgets.removeAll(widget);
×
230
        widget->update();
×
231
    }
232
    else if (select == true && m_selectedWidgets.indexOf(widget) == -1)
8✔
233
    {
234
        m_selectedWidgets.append(widget);
8✔
235
        widget->update();
8✔
236
    }
237

238
    /* Change the custom menu to the latest-selected widget's menu */
239
    updateCustomMenu();
8✔
240

241
    /* Enable or disable actions */
242
    updateActions();
8✔
243
}
8✔
244

245
bool VirtualConsole::isWidgetSelected(VCWidget* widget) const
62✔
246
{
247
    if (widget == NULL || m_selectedWidgets.indexOf(widget) == -1)
62✔
248
        return false;
54✔
249
    else
250
        return true;
8✔
251
}
252

253
void VirtualConsole::clearWidgetSelection()
12✔
254
{
255
    /* Get a copy of selected widget list */
256
    QList <VCWidget*> widgets(m_selectedWidgets);
12✔
257

258
    /* Clear the list so isWidgetSelected() returns false for all widgets */
259
    m_selectedWidgets.clear();
12✔
260

261
    /* Update all widgets to clear the selection frame around them */
262
    QListIterator <VCWidget*> it(widgets);
12✔
263
    while (it.hasNext() == true)
14✔
264
        it.next()->update();
2✔
265

266
    /* Change the custom menu to the latest-selected widget's menu */
267
    updateCustomMenu();
12✔
268

269
    /* Enable or disable actions */
270
    updateActions();
12✔
271
}
12✔
272

273
void VirtualConsole::reselectWidgets()
×
274
{
275
    QList <VCWidget*> widgets(m_selectedWidgets);
×
276
    clearWidgetSelection();
×
277
    foreach (VCWidget* w, widgets)
×
278
        setWidgetSelected(w, true);
×
279
}
×
280

281
/*****************************************************************************
282
 * Actions, menu- and toolbar
283
 *****************************************************************************/
284

285
QMenu* VirtualConsole::customMenu() const
×
286
{
287
    return m_customMenu;
×
288
}
289

290
QMenu* VirtualConsole::editMenu() const
×
291
{
292
    return m_editMenu;
×
293
}
294

295
QMenu* VirtualConsole::addMenu() const
16✔
296
{
297
    return m_addMenu;
16✔
298
}
299

300
void VirtualConsole::initActions()
152✔
301
{
302
    /* Add menu actions */
303
    m_addButtonAction = new QAction(QIcon(":/button.png"), tr("New Button"), this);
152✔
304
    connect(m_addButtonAction, SIGNAL(triggered(bool)), this, SLOT(slotAddButton()), Qt::QueuedConnection);
152✔
305

306
    m_addButtonMatrixAction = new QAction(QIcon(":/buttonmatrix.png"), tr("New Button Matrix"), this);
152✔
307
    connect(m_addButtonMatrixAction, SIGNAL(triggered(bool)), this, SLOT(slotAddButtonMatrix()), Qt::QueuedConnection);
152✔
308

309
    m_addSliderAction = new QAction(QIcon(":/slider.png"), tr("New Slider"), this);
152✔
310
    connect(m_addSliderAction, SIGNAL(triggered(bool)), this, SLOT(slotAddSlider()), Qt::QueuedConnection);
152✔
311

312
    m_addSliderMatrixAction = new QAction(QIcon(":/slidermatrix.png"), tr("New Slider Matrix"), this);
152✔
313
    connect(m_addSliderMatrixAction, SIGNAL(triggered(bool)), this, SLOT(slotAddSliderMatrix()), Qt::QueuedConnection);
152✔
314

315
    m_addKnobAction = new QAction(QIcon(":/knob.png"), tr("New Knob"), this);
152✔
316
    connect(m_addKnobAction, SIGNAL(triggered(bool)), this, SLOT(slotAddKnob()), Qt::QueuedConnection);
152✔
317

318
    m_addSpeedDialAction = new QAction(QIcon(":/speed.png"), tr("New Speed Dial"), this);
152✔
319
    connect(m_addSpeedDialAction, SIGNAL(triggered(bool)), this, SLOT(slotAddSpeedDial()), Qt::QueuedConnection);
152✔
320

321
    m_addXYPadAction = new QAction(QIcon(":/xypad.png"), tr("New XY pad"), this);
152✔
322
    connect(m_addXYPadAction, SIGNAL(triggered(bool)), this, SLOT(slotAddXYPad()), Qt::QueuedConnection);
152✔
323

324
    m_addCueListAction = new QAction(QIcon(":/cuelist.png"), tr("New Cue list"), this);
152✔
325
    connect(m_addCueListAction, SIGNAL(triggered(bool)), this, SLOT(slotAddCueList()), Qt::QueuedConnection);
152✔
326

327
    m_addFrameAction = new QAction(QIcon(":/frame.png"), tr("New Frame"), this);
152✔
328
    connect(m_addFrameAction, SIGNAL(triggered(bool)), this, SLOT(slotAddFrame()), Qt::QueuedConnection);
152✔
329

330
    m_addSoloFrameAction = new QAction(QIcon(":/soloframe.png"), tr("New Solo frame"), this);
152✔
331
    connect(m_addSoloFrameAction, SIGNAL(triggered(bool)), this, SLOT(slotAddSoloFrame()), Qt::QueuedConnection);
152✔
332

333
    m_addLabelAction = new QAction(QIcon(":/label.png"), tr("New Label"), this);
152✔
334
    connect(m_addLabelAction, SIGNAL(triggered(bool)), this, SLOT(slotAddLabel()), Qt::QueuedConnection);
152✔
335

336
    m_addAudioTriggersAction = new QAction(QIcon(":/audioinput.png"), tr("New Audio Triggers"), this);
152✔
337
    connect(m_addAudioTriggersAction, SIGNAL(triggered(bool)), this, SLOT(slotAddAudioTriggers()), Qt::QueuedConnection);
152✔
338

339
    m_addClockAction = new QAction(QIcon(":/clock.png"), tr("New Clock"), this);
152✔
340
    connect(m_addClockAction, SIGNAL(triggered(bool)), this, SLOT(slotAddClock()), Qt::QueuedConnection);
152✔
341

342
    m_addAnimationAction = new QAction(QIcon(":/animation.png"), tr("New Animation"), this);
152✔
343
    connect(m_addAnimationAction, SIGNAL(triggered(bool)), this, SLOT(slotAddAnimation()), Qt::QueuedConnection);
152✔
344

345
    /* Put add actions under the same group */
346
    m_addActionGroup = new QActionGroup(this);
152✔
347
    m_addActionGroup->setExclusive(false);
152✔
348
    m_addActionGroup->addAction(m_addButtonAction);
152✔
349
    m_addActionGroup->addAction(m_addButtonMatrixAction);
152✔
350
    m_addActionGroup->addAction(m_addSliderAction);
152✔
351
    m_addActionGroup->addAction(m_addSliderMatrixAction);
152✔
352
    m_addActionGroup->addAction(m_addKnobAction);
152✔
353
    m_addActionGroup->addAction(m_addSpeedDialAction);
152✔
354
    m_addActionGroup->addAction(m_addXYPadAction);
152✔
355
    m_addActionGroup->addAction(m_addCueListAction);
152✔
356
    m_addActionGroup->addAction(m_addFrameAction);
152✔
357
    m_addActionGroup->addAction(m_addSoloFrameAction);
152✔
358
    m_addActionGroup->addAction(m_addLabelAction);
152✔
359
    m_addActionGroup->addAction(m_addAudioTriggersAction);
152✔
360
    m_addActionGroup->addAction(m_addClockAction);
152✔
361
    m_addActionGroup->addAction(m_addAnimationAction);
152✔
362

363
    /* Tools menu actions */
364
    m_toolsSettingsAction = new QAction(QIcon(":/configure.png"), tr("Virtual Console Settings"), this);
152✔
365
    connect(m_toolsSettingsAction, SIGNAL(triggered(bool)), this, SLOT(slotToolsSettings()));
152✔
366
    // Prevent this action from ending up to the application menu on OSX
367
    // and crashing the app after VC window is closed.
368
    m_toolsSettingsAction->setMenuRole(QAction::NoRole);
152✔
369

370
    m_functionWizardAction = new QAction(QIcon(":/wizard.png"), tr("VC Fixture Widget Wizard"), this);
152✔
371
    connect(m_functionWizardAction, SIGNAL(triggered(bool)), this, SLOT(slotWizard()));
152✔
372

373
    /* Edit menu actions */
374
    m_editCutAction = new QAction(QIcon(":/editcut.png"), tr("Cut"), this);
152✔
375
    connect(m_editCutAction, SIGNAL(triggered(bool)), this, SLOT(slotEditCut()));
152✔
376

377
    m_editCopyAction = new QAction(QIcon(":/editcopy.png"), tr("Copy"), this);
152✔
378
    connect(m_editCopyAction, SIGNAL(triggered(bool)), this, SLOT(slotEditCopy()));
152✔
379

380
    m_editPasteAction = new QAction(QIcon(":/editpaste.png"), tr("Paste"), this);
152✔
381
    m_editPasteAction->setEnabled(false);
152✔
382
    connect(m_editPasteAction, SIGNAL(triggered(bool)), this, SLOT(slotEditPaste()));
152✔
383

384
    m_editDeleteAction = new QAction(QIcon(":/editdelete.png"), tr("Delete"), this);
152✔
385
    connect(m_editDeleteAction, SIGNAL(triggered(bool)), this, SLOT(slotEditDelete()));
152✔
386

387
    m_editPropertiesAction = new QAction(QIcon(":/edit.png"), tr("Widget Properties"), this);
152✔
388
    connect(m_editPropertiesAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProperties()));
152✔
389

390
    m_editRenameAction = new QAction(QIcon(":/editclear.png"), tr("Rename Widget"), this);
152✔
391
    connect(m_editRenameAction, SIGNAL(triggered(bool)), this, SLOT(slotEditRename()));
152✔
392

393
    /* Put edit actions under the same group */
394
    m_editActionGroup = new QActionGroup(this);
152✔
395
    m_editActionGroup->setExclusive(false);
152✔
396
    m_editActionGroup->addAction(m_editCutAction);
152✔
397
    m_editActionGroup->addAction(m_editCopyAction);
152✔
398
    m_editActionGroup->addAction(m_editPasteAction);
152✔
399
    m_editActionGroup->addAction(m_editDeleteAction);
152✔
400
    m_editActionGroup->addAction(m_editPropertiesAction);
152✔
401
    m_editActionGroup->addAction(m_editRenameAction);
152✔
402

403
    /* Background menu actions */
404
    m_bgColorAction = new QAction(QIcon(":/color.png"), tr("Background Color"), this);
152✔
405
    connect(m_bgColorAction, SIGNAL(triggered(bool)), this, SLOT(slotBackgroundColor()));
152✔
406

407
    m_bgImageAction = new QAction(QIcon(":/image.png"), tr("Background Image"), this);
152✔
408
    connect(m_bgImageAction, SIGNAL(triggered(bool)), this, SLOT(slotBackgroundImage()));
152✔
409

410
    m_bgDefaultAction = new QAction(QIcon(":/undo.png"), tr("Default"), this);
152✔
411
    connect(m_bgDefaultAction, SIGNAL(triggered(bool)), this, SLOT(slotBackgroundNone()));
152✔
412

413
    /* Put BG actions under the same group */
414
    m_bgActionGroup = new QActionGroup(this);
152✔
415
    m_bgActionGroup->setExclusive(false);
152✔
416
    m_bgActionGroup->addAction(m_bgColorAction);
152✔
417
    m_bgActionGroup->addAction(m_bgImageAction);
152✔
418
    m_bgActionGroup->addAction(m_bgDefaultAction);
152✔
419

420
    /* Foreground menu actions */
421
    m_fgColorAction = new QAction(QIcon(":/fontcolor.png"), tr("Font Colour"), this);
152✔
422
    connect(m_fgColorAction, SIGNAL(triggered(bool)), this, SLOT(slotForegroundColor()));
152✔
423

424
    m_fgDefaultAction = new QAction(QIcon(":/undo.png"), tr("Default"), this);
152✔
425
    connect(m_fgDefaultAction, SIGNAL(triggered(bool)), this, SLOT(slotForegroundNone()));
152✔
426

427
    /* Put FG actions under the same group */
428
    m_fgActionGroup = new QActionGroup(this);
152✔
429
    m_fgActionGroup->setExclusive(false);
152✔
430
    m_fgActionGroup->addAction(m_fgColorAction);
152✔
431
    m_fgActionGroup->addAction(m_fgDefaultAction);
152✔
432

433
    /* Font menu actions */
434
    m_fontAction = new QAction(QIcon(":/fonts.png"), tr("Font"), this);
152✔
435
    connect(m_fontAction, SIGNAL(triggered(bool)), this, SLOT(slotFont()));
152✔
436

437
    m_resetFontAction = new QAction(QIcon(":/undo.png"), tr("Default"), this);
152✔
438
    connect(m_resetFontAction, SIGNAL(triggered(bool)), this, SLOT(slotResetFont()));
152✔
439

440
    /* Put font actions under the same group */
441
    m_fontActionGroup = new QActionGroup(this);
152✔
442
    m_fontActionGroup->setExclusive(false);
152✔
443
    m_fontActionGroup->addAction(m_fontAction);
152✔
444
    m_fontActionGroup->addAction(m_resetFontAction);
152✔
445

446
    /* Frame menu actions */
447
    m_frameSunkenAction = new QAction(QIcon(":/framesunken.png"), tr("Sunken"), this);
152✔
448
    connect(m_frameSunkenAction, SIGNAL(triggered(bool)), this, SLOT(slotFrameSunken()));
152✔
449

450
    m_frameRaisedAction = new QAction(QIcon(":/frameraised.png"), tr("Raised"), this);
152✔
451
    connect(m_frameRaisedAction, SIGNAL(triggered(bool)), this, SLOT(slotFrameRaised()));
152✔
452

453
    m_frameNoneAction = new QAction(QIcon(":/framenone.png"), tr("None"), this);
152✔
454
    connect(m_frameNoneAction, SIGNAL(triggered(bool)), this, SLOT(slotFrameNone()));
152✔
455

456
    /* Put frame actions under the same group */
457
    m_frameActionGroup = new QActionGroup(this);
152✔
458
    m_frameActionGroup->setExclusive(false);
152✔
459
    m_frameActionGroup->addAction(m_frameRaisedAction);
152✔
460
    m_frameActionGroup->addAction(m_frameSunkenAction);
152✔
461
    m_frameActionGroup->addAction(m_frameNoneAction);
152✔
462

463
    /* Stacking menu actions */
464
    m_stackingRaiseAction = new QAction(QIcon(":/up.png"), tr("Bring to front"), this);
152✔
465
    connect(m_stackingRaiseAction, SIGNAL(triggered(bool)), this, SLOT(slotStackingRaise()));
152✔
466

467
    m_stackingLowerAction = new QAction(QIcon(":/down.png"), tr("Send to back"), this);
152✔
468
    connect(m_stackingLowerAction, SIGNAL(triggered(bool)), this, SLOT(slotStackingLower()));
152✔
469

470
    /* Put stacking actions under the same group */
471
    m_stackingActionGroup = new QActionGroup(this);
152✔
472
    m_stackingActionGroup->setExclusive(false);
152✔
473
    m_stackingActionGroup->addAction(m_stackingRaiseAction);
152✔
474
    m_stackingActionGroup->addAction(m_stackingLowerAction);
152✔
475
}
152✔
476

477
void VirtualConsole::initMenuBar()
152✔
478
{
479
    /* Add menu */
480
    m_addMenu = new QMenu(this);
152✔
481
    m_addMenu->setTitle(tr("&Add"));
152✔
482
    m_addMenu->addAction(m_addButtonAction);
152✔
483
    m_addMenu->addAction(m_addButtonMatrixAction);
152✔
484
    m_addMenu->addSeparator();
152✔
485
    m_addMenu->addAction(m_addSliderAction);
152✔
486
    m_addMenu->addAction(m_addSliderMatrixAction);
152✔
487
    m_addMenu->addAction(m_addKnobAction);
152✔
488
    m_addMenu->addAction(m_addSpeedDialAction);
152✔
489
    m_addMenu->addSeparator();
152✔
490
    m_addMenu->addAction(m_addXYPadAction);
152✔
491
    m_addMenu->addAction(m_addCueListAction);
152✔
492
    m_addMenu->addAction(m_addAnimationAction);
152✔
493
    m_addMenu->addAction(m_addAudioTriggersAction);
152✔
494
    m_addMenu->addSeparator();
152✔
495
    m_addMenu->addAction(m_addFrameAction);
152✔
496
    m_addMenu->addAction(m_addSoloFrameAction);
152✔
497
    m_addMenu->addAction(m_addLabelAction);
152✔
498
    m_addMenu->addAction(m_addClockAction);
152✔
499

500
    /* Edit menu */
501
    m_editMenu = new QMenu(this);
152✔
502
    m_editMenu->setTitle(tr("&Edit"));
152✔
503
    m_editMenu->addAction(m_editCutAction);
152✔
504
    m_editMenu->addAction(m_editCopyAction);
152✔
505
    m_editMenu->addAction(m_editPasteAction);
152✔
506
    m_editMenu->addAction(m_editDeleteAction);
152✔
507
    m_editMenu->addSeparator();
152✔
508
    m_editMenu->addAction(m_editPropertiesAction);
152✔
509
    m_editMenu->addAction(m_editRenameAction);
152✔
510
    m_editMenu->addSeparator();
152✔
511

512
    /* Background Menu */
513
    QMenu* bgMenu = new QMenu(m_editMenu);
152✔
514
    bgMenu->setTitle(tr("&Background"));
152✔
515
    m_editMenu->addMenu(bgMenu);
152✔
516
    bgMenu->addAction(m_bgColorAction);
152✔
517
    bgMenu->addAction(m_bgImageAction);
152✔
518
    bgMenu->addAction(m_bgDefaultAction);
152✔
519

520
    /* Foreground menu */
521
    QMenu* fgMenu = new QMenu(m_editMenu);
152✔
522
    fgMenu->setTitle(tr("&Foreground"));
152✔
523
    m_editMenu->addMenu(fgMenu);
152✔
524
    fgMenu->addAction(m_fgColorAction);
152✔
525
    fgMenu->addAction(m_fgDefaultAction);
152✔
526

527
    /* Font menu */
528
    QMenu* fontMenu = new QMenu(m_editMenu);
152✔
529
    fontMenu->setTitle(tr("F&ont"));
152✔
530
    m_editMenu->addMenu(fontMenu);
152✔
531
    fontMenu->addAction(m_fontAction);
152✔
532
    fontMenu->addAction(m_resetFontAction);
152✔
533

534
    /* Frame menu */
535
    QMenu* frameMenu = new QMenu(m_editMenu);
152✔
536
    frameMenu->setTitle(tr("F&rame"));
152✔
537
    m_editMenu->addMenu(frameMenu);
152✔
538
    frameMenu->addAction(m_frameSunkenAction);
152✔
539
    frameMenu->addAction(m_frameRaisedAction);
152✔
540
    frameMenu->addAction(m_frameNoneAction);
152✔
541

542
    /* Stacking order menu */
543
    QMenu* stackMenu = new QMenu(m_editMenu);
152✔
544
    stackMenu->setTitle(tr("Stacking &order"));
152✔
545
    m_editMenu->addMenu(stackMenu);
152✔
546
    stackMenu->addAction(m_stackingRaiseAction);
152✔
547
    stackMenu->addAction(m_stackingLowerAction);
152✔
548

549
    /* Add a separator that separates the common edit items from a custom
550
       widget menu that gets appended to the edit menu when a selected
551
       widget provides one. */
552
    m_editMenu->addSeparator();
152✔
553

554
    /* Toolbar */
555
    m_toolbar = new QToolBar(this);
152✔
556
    m_toolbar->setIconSize(QSize(26,26));
152✔
557
    m_contentsLayout->addWidget(m_toolbar);
152✔
558

559
    m_toolbar->addAction(m_addButtonAction);
152✔
560
    m_toolbar->addAction(m_addButtonMatrixAction);
152✔
561
    m_toolbar->addAction(m_addSliderAction);
152✔
562
    m_toolbar->addAction(m_addSliderMatrixAction);
152✔
563
    m_toolbar->addAction(m_addKnobAction);
152✔
564
    m_toolbar->addAction(m_addSpeedDialAction);
152✔
565
    m_toolbar->addAction(m_addXYPadAction);
152✔
566
    m_toolbar->addAction(m_addCueListAction);
152✔
567
    m_toolbar->addAction(m_addAnimationAction);
152✔
568
    m_toolbar->addAction(m_addFrameAction);
152✔
569
    m_toolbar->addAction(m_addSoloFrameAction);
152✔
570
    m_toolbar->addAction(m_addLabelAction);
152✔
571
    m_toolbar->addAction(m_addAudioTriggersAction);
152✔
572
    m_toolbar->addAction(m_addClockAction);
152✔
573
    m_toolbar->addSeparator();
152✔
574
    m_toolbar->addAction(m_editCutAction);
152✔
575
    m_toolbar->addAction(m_editCopyAction);
152✔
576
    m_toolbar->addAction(m_editPasteAction);
152✔
577
    m_toolbar->addSeparator();
152✔
578
    m_toolbar->addAction(m_editDeleteAction);
152✔
579
    m_toolbar->addSeparator();
152✔
580
    m_toolbar->addAction(m_editPropertiesAction);
152✔
581
    m_toolbar->addAction(m_editRenameAction);
152✔
582
    m_toolbar->addSeparator();
152✔
583
    m_toolbar->addAction(m_stackingRaiseAction);
152✔
584
    m_toolbar->addAction(m_stackingLowerAction);
152✔
585
    m_toolbar->addSeparator();
152✔
586
    m_toolbar->addAction(m_bgColorAction);
152✔
587
    m_toolbar->addAction(m_bgImageAction);
152✔
588
    m_toolbar->addAction(m_fgColorAction);
152✔
589
    m_toolbar->addAction(m_fontAction);
152✔
590
    m_toolbar->addSeparator();
152✔
591
    m_toolbar->addAction(m_functionWizardAction);
152✔
592
    m_toolbar->addAction(m_toolsSettingsAction);
152✔
593
}
152✔
594

595
void VirtualConsole::updateCustomMenu()
20✔
596
{
597
    /* Get rid of the custom menu, but delete it later because this might
598
       be called from the very menu that is being deleted. */
599
    if (m_customMenu != NULL)
20✔
600
    {
601
        delete m_customMenu;
12✔
602
        m_customMenu = NULL;
12✔
603
    }
604

605
    if (m_selectedWidgets.size() > 0)
20✔
606
    {
607
        /* Change the custom menu to the last selected widget's menu */
608
        VCWidget* latestWidget = m_selectedWidgets.last();
8✔
609
        m_customMenu = latestWidget->customMenu(m_editMenu);
8✔
610
        if (m_customMenu != NULL)
8✔
611
            m_editMenu->addMenu(m_customMenu);
4✔
612
    }
613
    else
614
    {
615
        /* Change the custom menu to the bottom frame's menu */
616
        Q_ASSERT(contents() != NULL);
12✔
617
        m_customMenu = contents()->customMenu(m_editMenu);
12✔
618
        if (m_customMenu != NULL)
12✔
619
            m_editMenu->addMenu(m_customMenu);
12✔
620
    }
621
}
20✔
622

623
void VirtualConsole::updateActions()
324✔
624
{
625
    /* When selected widgets is empty, all actions go to main draw area. */
626
    if (m_selectedWidgets.isEmpty() == true)
324✔
627
    {
628
        /* Enable widget additions to draw area */
629
        m_addActionGroup->setEnabled(true);
316✔
630

631
        /* Disable edit actions that can't be allowed for draw area */
632
        m_editCutAction->setEnabled(false);
316✔
633
        m_editCopyAction->setEnabled(false);
316✔
634
        m_editDeleteAction->setEnabled(false);
316✔
635
        m_editRenameAction->setEnabled(false);
316✔
636
        m_editPropertiesAction->setEnabled(false);
316✔
637

638
        /* All the rest are disabled for draw area, except BG & font */
639
        m_frameActionGroup->setEnabled(false);
316✔
640
        m_stackingActionGroup->setEnabled(false);
316✔
641

642
        /* Enable paste to draw area if there's something to paste */
643
        if (m_clipboard.isEmpty() == true)
316✔
644
            m_editPasteAction->setEnabled(false);
316✔
645
        else
646
            m_editPasteAction->setEnabled(true);
×
647
    }
648
    else
649
    {
650
        /* Enable edit actions for other widgets */
651
        m_editCutAction->setEnabled(true);
8✔
652
        m_editCopyAction->setEnabled(true);
8✔
653
        m_editDeleteAction->setEnabled(true);
8✔
654
        m_editRenameAction->setEnabled(true);
8✔
655
        m_editPropertiesAction->setEnabled(true);
8✔
656

657
        /* Enable all common properties */
658
        m_bgActionGroup->setEnabled(true);
8✔
659
        m_fgActionGroup->setEnabled(true);
8✔
660
        m_fontActionGroup->setEnabled(true);
8✔
661
        m_frameActionGroup->setEnabled(true);
8✔
662
        m_stackingActionGroup->setEnabled(true);
8✔
663

664
        /* Check, whether the last selected widget can hold children */
665
        if (m_selectedWidgets.last()->allowChildren() == true)
8✔
666
        {
667
            /* Enable paste for widgets that can hold children */
668
            if (m_clipboard.isEmpty() == true)
2✔
669
                m_editPasteAction->setEnabled(false);
2✔
670
            else
671
                m_editPasteAction->setEnabled(true);
×
672

673
            /* Enable also new additions */
674
            m_addActionGroup->setEnabled(true);
2✔
675
        }
676
        else
677
        {
678
            /* No pasted children possible */
679
            m_editPasteAction->setEnabled(false);
6✔
680
        }
681
    }
682

683
    if (contents()->children().count() == 0)
324✔
684
        m_latestWidgetId = 0;
312✔
685
}
324✔
686

687
/*****************************************************************************
688
 * Add menu callbacks
689
 *****************************************************************************/
690

691
VCWidget* VirtualConsole::closestParent() const
×
692
{
693
    /* If nothing is selected, return the bottom-most contents frame */
694
    if (m_selectedWidgets.isEmpty() == true)
×
695
        return contents();
×
696

697
    /* Find the next VCWidget in the hierarchy that accepts children */
698
    VCWidget* widget = m_selectedWidgets.last();
×
699
    while (widget != NULL)
×
700
    {
701
        if (widget->allowChildren() == true)
×
702
            return widget;
×
703
        else
704
            widget = qobject_cast<VCWidget*> (widget->parentWidget());
×
705
    }
706

707
    return NULL;
×
708
}
709

710
void VirtualConsole::connectWidgetToParent(VCWidget *widget, VCWidget *parent)
×
711
{
712
    if (parent->type() == VCWidget::FrameWidget
×
713
            || parent->type() == VCWidget::SoloFrameWidget)
×
714
    {
715
        VCFrame *frame = qobject_cast<VCFrame *>(parent);
×
716
        if (frame != NULL)
×
717
        {
718
            widget->setPage(frame->currentPage());
×
719
            frame->addWidgetToPageMap(widget);
×
720
        }
721
    }
722
    else
723
        widget->setPage(0);
×
724

725
    if (widget->type() == VCWidget::SliderWidget)
×
726
    {
727
        VCSlider *slider = qobject_cast<VCSlider *>(widget);
×
728
        if (slider != NULL)
×
729
        {
730
            connect(slider, SIGNAL(submasterValueChanged(qreal)),
×
731
                    parent, SLOT(slotSubmasterValueChanged(qreal)));
732
        }
733
    }
734
}
×
735

736
void VirtualConsole::disconnectWidgetFromParent(VCWidget *widget, VCWidget *parent)
×
737
{
738
    if (parent->type() == VCWidget::FrameWidget
×
739
            || parent->type() == VCWidget::SoloFrameWidget)
×
740
    {
741
        VCFrame *frame = qobject_cast<VCFrame *>(parent);
×
742
        if (frame != NULL)
×
743
            frame->removeWidgetFromPageMap(widget);
×
744
    }
745

746
    if (widget->type() == VCWidget::SliderWidget)
×
747
    {
748
        VCSlider *slider = qobject_cast<VCSlider *>(widget);
×
749
        if (slider != NULL)
×
750
        {
751
            disconnect(slider, SIGNAL(submasterValueChanged(qreal)),
×
752
                       parent, SLOT(slotSubmasterValueChanged(qreal)));
753
        }
754
    }
755
}
×
756

757
void VirtualConsole::slotAddButton()
×
758
{
759
    VCWidget* parent(closestParent());
×
760
    if (parent == NULL)
×
761
        return;
×
762

763
    VCButton* button = new VCButton(parent, m_doc);
×
764
    setupWidget(button, parent);
×
765
    m_doc->setModified();
×
766
}
767

768
void VirtualConsole::slotAddButtonMatrix()
×
769
{
770
    VCWidget* parent(closestParent());
×
771
    if (parent == NULL)
×
772
        return;
×
773

774
    AddVCButtonMatrix abm(this, m_doc);
×
775
    if (abm.exec() == QDialog::Rejected)
×
776
        return;
×
777

778
    int h = abm.horizontalCount();
×
779
    int v = abm.verticalCount();
×
780
    int sz = abm.buttonSize();
×
781

782
    VCFrame* frame = NULL;
×
783
    if (abm.frameStyle() == AddVCButtonMatrix::NormalFrame)
×
784
        frame = new VCFrame(parent, m_doc);
×
785
    else
786
        frame = new VCSoloFrame(parent, m_doc);
×
787
    Q_ASSERT(frame != NULL);
×
788
    addWidgetInMap(frame);
×
789
    frame->setHeaderVisible(false);
×
790
    connectWidgetToParent(frame, parent);
×
791

792
    // Resize the parent frame to fit the buttons nicely and toggle resizing off
793
    frame->resize(QSize((h * sz) + 20, (v * sz) + 20));
×
794
    frame->setAllowResize(false);
×
795

796
    for (int y = 0; y < v; y++)
×
797
    {
798
        for (int x = 0; x < h; x++)
×
799
        {
800
            VCButton* button = new VCButton(frame, m_doc);
×
801
            Q_ASSERT(button != NULL);
×
802
            addWidgetInMap(button);
×
803
            connectWidgetToParent(button, frame);
×
804
            button->move(QPoint(10 + (x * sz), 10 + (y * sz)));
×
805
            button->resize(QSize(sz, sz));
×
806
            button->show();
×
807

808
            int index = (y * h) + x;
×
809
            if (index < abm.functions().size())
×
810
            {
811
                quint32 fid = abm.functions().at(index);
×
812
                Function* function = m_doc->function(fid);
×
813
                if (function != NULL)
×
814
                {
815
                    button->setFunction(fid);
×
816
                    button->setCaption(function->name());
×
817
                }
818
            }
819
        }
820
    }
821

822
    // Show the frame after adding buttons to prevent flickering
823
    frame->show();
×
824
    frame->move(parent->lastClickPoint());
×
825
    frame->setAllowChildren(false); // Don't allow more children
×
826
    clearWidgetSelection();
×
827
    setWidgetSelected(frame, true);
×
828
    m_doc->setModified();
×
829
}
×
830

831
void VirtualConsole::slotAddSlider()
×
832
{
833
    VCWidget* parent(closestParent());
×
834
    if (parent == NULL)
×
835
        return;
×
836

837
    VCSlider* slider = new VCSlider(parent, m_doc);
×
838
    setupWidget(slider, parent);
×
839
    m_doc->setModified();
×
840
}
841

842
void VirtualConsole::slotAddSliderMatrix()
×
843
{
844
    VCWidget* parent(closestParent());
×
845
    if (parent == NULL)
×
846
        return;
×
847

848
    AddVCSliderMatrix avsm(this);
×
849
    if (avsm.exec() == QDialog::Rejected)
×
850
        return;
×
851

852
    int width = avsm.width();
×
853
    int height = avsm.height();
×
854
    int count = avsm.amount();
×
855

856
    VCFrame* frame = new VCFrame(parent, m_doc);
×
857
    Q_ASSERT(frame != NULL);
×
858
    addWidgetInMap(frame);
×
859
    frame->setHeaderVisible(false);
×
860
    connectWidgetToParent(frame, parent);
×
861

862
    // Resize the parent frame to fit the sliders nicely
863
    frame->resize(QSize((count * width) + 20, height + 20));
×
864
    frame->setAllowResize(false);
×
865

866
    for (int i = 0; i < count; i++)
×
867
    {
868
        VCSlider* slider = new VCSlider(frame, m_doc);
×
869
        Q_ASSERT(slider != NULL);
×
870
        addWidgetInMap(slider);
×
871
        connectWidgetToParent(slider, frame);
×
872
        slider->move(QPoint(10 + (width * i), 10));
×
873
        slider->resize(QSize(width, height));
×
874
        slider->show();
×
875
    }
876

877
    // Show the frame after adding buttons to prevent flickering
878
    frame->show();
×
879
    frame->move(parent->lastClickPoint());
×
880
    frame->setAllowChildren(false); // Don't allow more children
×
881
    clearWidgetSelection();
×
882
    setWidgetSelected(frame, true);
×
883
    m_doc->setModified();
×
884
}
×
885

886
void VirtualConsole::slotAddKnob()
×
887
{
888
    VCWidget* parent(closestParent());
×
889
    if (parent == NULL)
×
890
        return;
×
891

892
    VCSlider* knob = new VCSlider(parent, m_doc);
×
893
    setupWidget(knob, parent);
×
894
    knob->resize(QSize(60, 90));
×
895
    knob->setWidgetStyle(VCSlider::WKnob);
×
896
    knob->setCaption(tr("Knob %1").arg(knob->id()));
×
897
    m_doc->setModified();
×
898
}
899

900
void VirtualConsole::slotAddSpeedDial()
×
901
{
902
    VCWidget* parent(closestParent());
×
903
    if (parent == NULL)
×
904
        return;
×
905

906
    VCSpeedDial* dial = new VCSpeedDial(parent, m_doc);
×
907
    setupWidget(dial, parent);
×
908
    m_doc->setModified();
×
909
}
910

911
void VirtualConsole::slotAddXYPad()
×
912
{
913
    VCWidget* parent(closestParent());
×
914
    if (parent == NULL)
×
915
        return;
×
916

917
    VCXYPad* xypad = new VCXYPad(parent, m_doc);
×
918
    setupWidget(xypad, parent);
×
919
    m_doc->setModified();
×
920
}
921

922
void VirtualConsole::slotAddCueList()
×
923
{
924
    VCWidget* parent(closestParent());
×
925
    if (parent == NULL)
×
926
        return;
×
927

928
    VCCueList* cuelist = new VCCueList(parent, m_doc);
×
929
    setupWidget(cuelist, parent);
×
930
    m_doc->setModified();
×
931
}
932

933
void VirtualConsole::slotAddFrame()
×
934
{
935
    VCWidget* parent(closestParent());
×
936
    if (parent == NULL)
×
937
        return;
×
938

939
    VCFrame* frame = new VCFrame(parent, m_doc, true);
×
940
    setupWidget(frame, parent);
×
941
    m_doc->setModified();
×
942
}
943

944
void VirtualConsole::slotAddSoloFrame()
×
945
{
946
    VCWidget* parent(closestParent());
×
947
    if (parent == NULL)
×
948
        return;
×
949

950
    VCSoloFrame* soloframe = new VCSoloFrame(parent, m_doc, true);
×
951
    setupWidget(soloframe, parent);
×
952
    m_doc->setModified();
×
953
}
954

955
void VirtualConsole::slotAddLabel()
×
956
{
957
    VCWidget* parent(closestParent());
×
958
    if (parent == NULL)
×
959
        return;
×
960

961
    VCLabel* label = new VCLabel(parent, m_doc);
×
962
    setupWidget(label, parent);
×
963
    m_doc->setModified();
×
964
}
965

966
void VirtualConsole::slotAddAudioTriggers()
×
967
{
968
    VCWidget* parent(closestParent());
×
969
    if (parent == NULL)
×
970
        return;
×
971

972
    VCAudioTriggers* triggers = new VCAudioTriggers(parent, m_doc);
×
973
    setupWidget(triggers, parent);
×
974
    m_doc->setModified();
×
975
}
976

977
void VirtualConsole::slotAddClock()
×
978
{
979
    VCWidget* parent(closestParent());
×
980
    if (parent == NULL)
×
981
        return;
×
982

983
    VCClock* clock = new VCClock(parent, m_doc);
×
984
    setupWidget(clock, parent);
×
985
    m_doc->setModified();
×
986
}
987

988
void VirtualConsole::slotAddAnimation()
×
989
{
990
    VCWidget* parent(closestParent());
×
991
    if (parent == NULL)
×
992
        return;
×
993

994
    VCMatrix* matrix = new VCMatrix(parent, m_doc);
×
995
    setupWidget(matrix, parent);
×
996
    m_doc->setModified();
×
997
}
998

999
/*****************************************************************************
1000
 * Tools menu callbacks
1001
 *****************************************************************************/
1002

1003
void VirtualConsole::slotToolsSettings()
×
1004
{
1005
    VCPropertiesEditor vcpe(this, m_properties, m_doc->inputOutputMap());
×
1006
    if (vcpe.exec() == QDialog::Accepted)
×
1007
    {
1008
        m_properties = vcpe.properties();
×
1009
        contents()->resize(m_properties.size());
×
1010
        m_doc->inputOutputMap()->setGrandMasterChannelMode(m_properties.grandMasterChannelMode());
×
1011
        m_doc->inputOutputMap()->setGrandMasterValueMode(m_properties.grandMasterValueMode());
×
1012
        if (m_dockArea != NULL)
×
1013
        {
1014
            m_dockArea->setGrandMasterVisible(m_properties.grandMasterVisible());
×
1015
            m_dockArea->setGrandMasterInvertedAppearance(m_properties.grandMasterSliderMode());
×
1016
        }
1017

1018
        QSettings settings;
×
1019
        settings.setValue(SETTINGS_BUTTON_SIZE, vcpe.buttonSize());
×
1020
        settings.setValue(SETTINGS_BUTTON_STATUSLED, vcpe.buttonStatusLED());
×
1021
        settings.setValue(SETTINGS_SLIDER_SIZE, vcpe.sliderSize());
×
1022
        settings.setValue(SETTINGS_SPEEDDIAL_SIZE, vcpe.speedDialSize());
×
1023
        settings.setValue(SETTINGS_SPEEDDIAL_VALUE, vcpe.speedDialValue());
×
1024
        settings.setValue(SETTINGS_XYPAD_SIZE, vcpe.xypadSize());
×
1025
        settings.setValue(SETTINGS_CUELIST_SIZE, vcpe.cuelistSize());
×
1026
        settings.setValue(SETTINGS_FRAME_SIZE, vcpe.frameSize());
×
1027
        settings.setValue(SETTINGS_SOLOFRAME_SIZE, vcpe.soloFrameSize());
×
1028
        settings.setValue(SETTINGS_AUDIOTRIGGERS_SIZE, vcpe.audioTriggersSize());
×
1029
        settings.setValue(SETTINGS_RGBMATRIX_SIZE, vcpe.rgbMatrixSize());
×
1030

1031
        m_doc->setModified();
×
1032
    }
×
1033
}
×
1034

1035
void VirtualConsole::slotWizard()
×
1036
{
1037
    FunctionWizard fw(this, m_doc);
×
1038
    if (fw.exec() == QDialog::Accepted){
×
1039
        m_doc->setModified();
×
1040
    }
1041
}
×
1042

1043
/*****************************************************************************
1044
 * Edit menu callbacks
1045
 *****************************************************************************/
1046

1047
void VirtualConsole::slotEditCut()
×
1048
{
1049
    /* No need to delete widgets in clipboard because they are actually just
1050
       MOVED to another parent during Paste when m_editAction == EditCut.
1051
       Cutting the widgets does nothing to them unless Paste is invoked. */
1052

1053
    /* Make the edit action valid only if there's something to cut */
1054
    if (m_selectedWidgets.size() == 0)
×
1055
    {
1056
        m_editAction = EditNone;
×
1057
        m_clipboard.clear();
×
1058
        m_editPasteAction->setEnabled(false);
×
1059
    }
1060
    else
1061
    {
1062
        m_editAction = EditCut;
×
1063
        m_clipboard = m_selectedWidgets;
×
1064
        m_editPasteAction->setEnabled(true);
×
1065
    }
1066

1067
    updateActions();
×
1068
}
×
1069

1070
void VirtualConsole::slotEditCopy()
×
1071
{
1072
    /* Make the edit action valid only if there's something to copy */
1073
    if (m_selectedWidgets.size() == 0)
×
1074
    {
1075
        m_editAction = EditNone;
×
1076
        m_clipboard.clear();
×
1077
        m_editPasteAction->setEnabled(false);
×
1078
    }
1079
    else
1080
    {
1081
        m_editAction = EditCopy;
×
1082
        m_clipboard = m_selectedWidgets;
×
1083
        m_editPasteAction->setEnabled(true);
×
1084
    }
1085
}
×
1086

1087
void VirtualConsole::slotEditPaste()
×
1088
{
1089
    if (m_clipboard.size() == 0)
×
1090
    {
1091
        /* Invalidate the edit action if there's nothing to paste */
1092
        m_editAction = EditNone;
×
1093
        m_editPasteAction->setEnabled(false);
×
1094
        return;
×
1095
    }
1096

1097
    VCWidget* parent;
1098
    VCWidget* widget;
1099
    QRect bounds;
×
1100

1101
    Q_ASSERT(contents() != NULL);
×
1102

1103
    /* Select the parent that gets the cut clipboard contents */
1104
    parent = closestParent();
×
1105

1106
    /* Get the bounding rect for all selected widgets */
1107
    QListIterator <VCWidget*> it(m_clipboard);
×
1108
    while (it.hasNext() == true)
×
1109
    {
1110
        widget = it.next();
×
1111
        Q_ASSERT(widget != NULL);
×
1112
        bounds = bounds.united(widget->geometry());
×
1113
    }
1114

1115
    /* Get the upcoming parent's last mouse click point */
1116
    QPoint cp(parent->lastClickPoint());
×
1117

1118
    if (m_editAction == EditCut)
×
1119
    {
1120
        it.toFront();
×
1121
        while (it.hasNext() == true)
×
1122
        {
1123
            widget = it.next();
×
1124
            Q_ASSERT(widget != NULL);
×
1125
            if (widget == parent)
×
1126
                continue;
×
1127

1128
            VCWidget* prevParent = qobject_cast<VCWidget*> (widget->parentWidget());
×
1129
            if (prevParent != NULL)
×
1130
                disconnectWidgetFromParent(widget, prevParent);
×
1131

1132
            /* Get widget's relative pos to the bounding rect */
1133
            QPoint p(widget->x() - bounds.x() + cp.x(),
×
1134
                     widget->y() - bounds.y() + cp.y());
×
1135

1136
            /* Reparent and move to the correct place */
1137
            widget->setParent(parent);
×
1138
            connectWidgetToParent(widget, parent);
×
1139
            widget->move(p);
×
1140
            widget->show();
×
1141
        }
1142

1143
        /* Clear clipboard after pasting stuff that was CUT */
1144
        m_clipboard.clear();
×
1145
        m_editPasteAction->setEnabled(false);
×
1146
    }
1147
    else if (m_editAction == EditCopy)
×
1148
    {
1149
        it.toFront();
×
1150
        while (it.hasNext() == true)
×
1151
        {
1152
            widget = it.next();
×
1153
            Q_ASSERT(widget != NULL);
×
1154
            if (widget == parent)
×
1155
                continue;
×
1156

1157
            /* Get widget's relative pos to the bounding rect */
1158
            QPoint p(widget->x() - bounds.x() + cp.x(),
×
1159
                     widget->y() - bounds.y() + cp.y());
×
1160

1161
            /* Create a copy and move to correct place */
1162
            VCWidget* copy = widget->createCopy(parent);
×
1163
            Q_ASSERT(copy != NULL);
×
1164
            addWidgetInMap(copy);
×
1165
            connectWidgetToParent(copy, parent);
×
1166
            copy->move(p);
×
1167
            copy->show();
×
1168
        }
1169
    }
1170

1171
    updateActions();
×
1172
}
×
1173

1174
void VirtualConsole::slotEditDelete()
×
1175
{
1176
    QString msg(tr("Do you wish to delete the selected widgets?"));
×
1177
    QString title(tr("Delete widgets"));
×
1178
    int result = QMessageBox::question(this, title, msg,
×
1179
                                       QMessageBox::Yes,
1180
                                       QMessageBox::No);
1181
    if (result == QMessageBox::Yes)
×
1182
    {
1183
        while (m_selectedWidgets.isEmpty() == false)
×
1184
        {
1185
            /* Consume the selected list until it is empty and
1186
               delete each widget. */
1187
            VCWidget* widget = m_selectedWidgets.takeFirst();
×
1188
            m_widgetsMap.remove(widget->id());
×
1189
            foreach (VCWidget* child, getChildren(widget))
×
1190
                m_widgetsMap.remove(child->id());
×
1191
            VCWidget* parent = qobject_cast<VCWidget*> (widget->parentWidget());
×
1192
            widget->deleteLater();
×
1193

1194
            if (parent != NULL)
×
1195
                disconnectWidgetFromParent(widget, parent);
×
1196

1197
            /* Remove the widget from clipboard as well so that
1198
               deleted widgets won't be pasted anymore anywhere */
1199
            m_clipboard.removeAll(widget);
×
1200
            m_editPasteAction->setEnabled(false);
×
1201
        }
1202

1203
        updateActions();
×
1204
    }
1205
    m_doc->setModified();
×
1206
}
×
1207

1208
void VirtualConsole::slotEditProperties()
×
1209
{
1210
    VCWidget* widget;
1211

1212
    Q_ASSERT(contents() != NULL);
×
1213

1214
    if (m_selectedWidgets.isEmpty() == true)
×
1215
        widget = contents();
×
1216
    else
1217
        widget = m_selectedWidgets.last();
×
1218

1219
    if (widget != NULL)
×
1220
        widget->editProperties();
×
1221
}
×
1222

1223
void VirtualConsole::slotEditRename()
×
1224
{
1225
    if (m_selectedWidgets.isEmpty() == true)
×
1226
        return;
×
1227

1228
    bool ok = false;
×
1229
    QString text(m_selectedWidgets.last()->caption());
×
1230
    text = QInputDialog::getText(this, tr("Rename widgets"), tr("Caption:"),
×
1231
                                 QLineEdit::Normal, text, &ok);
×
1232
    if (ok == true)
×
1233
    {
1234
        VCWidget* widget;
1235
        foreach (widget, m_selectedWidgets)
×
1236
            widget->setCaption(text);
×
1237
    }
1238
}
×
1239

1240
/*****************************************************************************
1241
 * Background menu callbacks
1242
 *****************************************************************************/
1243

1244
void VirtualConsole::slotBackgroundColor()
×
1245
{
1246
    QColor color;
×
1247

1248
    Q_ASSERT(contents() != NULL);
×
1249

1250
    if (m_selectedWidgets.isEmpty() == true)
×
1251
        color = contents()->backgroundColor();
×
1252
    else
1253
        color = m_selectedWidgets.last()->backgroundColor();
×
1254

1255
    color = QColorDialog::getColor(color);
×
1256
    if (color.isValid() == true)
×
1257
    {
1258
        if (m_selectedWidgets.isEmpty() == true)
×
1259
        {
NEW
1260
            contents()->setAutoFillBackground(true);
×
UNCOV
1261
            contents()->setBackgroundColor(color);
×
1262
        }
1263
        else
1264
        {
1265
            VCWidget* widget;
1266
            foreach (widget, m_selectedWidgets)
×
1267
                widget->setBackgroundColor(color);
×
1268
        }
1269
    }
1270
}
×
1271

1272
void VirtualConsole::slotBackgroundImage()
×
1273
{
1274
    QString path;
×
1275

1276
    Q_ASSERT(contents() != NULL);
×
1277

1278
    if (m_selectedWidgets.isEmpty() == true)
×
1279
        path = contents()->backgroundImage();
×
1280
    else
1281
        path = m_selectedWidgets.last()->backgroundImage();
×
1282

1283
    path = QFileDialog::getOpenFileName(this,
×
1284
                                        tr("Select background image"),
×
1285
                                        path,
1286
                                        QString("%1 (*.png *.bmp *.jpg *.jpeg *.gif)").arg(tr("Images")));
×
1287
    if (path.isEmpty() == false)
×
1288
    {
1289
        if (m_selectedWidgets.isEmpty() == true)
×
1290
        {
NEW
1291
            contents()->setAutoFillBackground(true);
×
UNCOV
1292
            contents()->setBackgroundImage(path);
×
1293
        }
1294
        else
1295
        {
1296
            VCWidget* widget;
1297
            foreach (widget, m_selectedWidgets)
×
1298
                widget->setBackgroundImage(path);
×
1299
        }
1300
    }
1301
}
×
1302

1303
void VirtualConsole::slotBackgroundNone()
×
1304
{
1305
    Q_ASSERT(contents() != NULL);
×
1306

1307
    if (m_selectedWidgets.isEmpty() == true)
×
1308
    {
NEW
1309
        contents()->setAutoFillBackground(true);
×
UNCOV
1310
        contents()->resetBackgroundColor();
×
1311
    }
1312
    else
1313
    {
1314
        VCWidget* widget;
1315
        foreach (widget, m_selectedWidgets)
×
1316
            widget->resetBackgroundColor();
×
1317
    }
1318
}
×
1319

1320
/*****************************************************************************
1321
 * Foreground menu callbacks
1322
 *****************************************************************************/
1323

1324
void VirtualConsole::slotForegroundColor()
×
1325
{
1326
    Q_ASSERT(contents() != NULL);
×
1327

1328
    if (m_selectedWidgets.isEmpty() == true)
×
1329
        return;
×
1330

1331
    QColor color(m_selectedWidgets.last()->foregroundColor());
×
1332
    color = QColorDialog::getColor(color);
×
1333
    if (color.isValid() == true)
×
1334
    {
1335
        VCWidget* widget;
1336
        foreach (widget, m_selectedWidgets)
×
1337
            widget->setForegroundColor(color);
×
1338
    }
1339
}
1340

1341
void VirtualConsole::slotForegroundNone()
×
1342
{
1343
    Q_ASSERT(contents() != NULL);
×
1344

1345
    if (m_selectedWidgets.isEmpty() == true)
×
1346
        return;
×
1347

1348
    VCWidget* widget;
1349
    foreach (widget, m_selectedWidgets)
×
1350
        widget->resetForegroundColor();
×
1351
}
1352

1353
/*****************************************************************************
1354
 * Font menu callbacks
1355
 *****************************************************************************/
1356

1357
void VirtualConsole::slotFont()
×
1358
{
1359
    bool ok = false;
×
1360
    QFont font;
×
1361

1362
    Q_ASSERT(contents() != NULL);
×
1363

1364
    if (m_selectedWidgets.isEmpty() == true)
×
1365
        font = contents()->font();
×
1366
    else
1367
        font = m_selectedWidgets.last()->font();
×
1368

1369
    /* This crashes with Qt 4.6.x on OSX. Upgrade to 4.7.x. */
1370
    font = QFontDialog::getFont(&ok, font);
×
1371
    if (ok == true)
×
1372
    {
1373
        if (m_selectedWidgets.isEmpty() == true)
×
1374
        {
1375
            contents()->setFont(font);
×
1376
        }
1377
        else
1378
        {
1379
            VCWidget* widget;
1380
            foreach (widget, m_selectedWidgets)
×
1381
                widget->setFont(font);
×
1382
        }
1383
    }
1384
}
×
1385

1386
void VirtualConsole::slotResetFont()
×
1387
{
1388
    Q_ASSERT(contents() != NULL);
×
1389

1390
    if (m_selectedWidgets.isEmpty() == true)
×
1391
    {
1392
        contents()->resetFont();
×
1393
    }
1394
    else
1395
    {
1396
        VCWidget* widget;
1397
        foreach (widget, m_selectedWidgets)
×
1398
            widget->resetFont();
×
1399
    }
1400
}
×
1401

1402
/*****************************************************************************
1403
 * Stacking menu callbacks
1404
 *****************************************************************************/
1405

1406
void VirtualConsole::slotStackingRaise()
×
1407
{
1408
    Q_ASSERT(contents() != NULL);
×
1409

1410
    if (m_selectedWidgets.isEmpty() == true)
×
1411
        return;
×
1412

1413
    VCWidget* widget;
1414
    foreach (widget, m_selectedWidgets)
×
1415
        widget->raise();
×
1416

1417
    m_doc->setModified();
×
1418
}
1419

1420
void VirtualConsole::slotStackingLower()
×
1421
{
1422
    Q_ASSERT(contents() != NULL);
×
1423

1424
    if (m_selectedWidgets.isEmpty() == true)
×
1425
        return;
×
1426

1427
    VCWidget* widget;
1428
    foreach (widget, m_selectedWidgets)
×
1429
        widget->lower();
×
1430

1431
    m_doc->setModified();
×
1432
}
1433

1434
/*****************************************************************************
1435
 * Frame menu callbacks
1436
 *****************************************************************************/
1437

1438
void VirtualConsole::slotFrameSunken()
×
1439
{
1440
    Q_ASSERT(contents() != NULL);
×
1441

1442
    if (m_selectedWidgets.isEmpty() == true)
×
1443
        return;
×
1444

1445
    VCWidget* widget;
1446
    foreach (widget, m_selectedWidgets)
×
1447
        widget->setFrameStyle(KVCFrameStyleSunken);
×
1448
}
1449

1450
void VirtualConsole::slotFrameRaised()
×
1451
{
1452
    Q_ASSERT(contents() != NULL);
×
1453

1454
    if (m_selectedWidgets.isEmpty() == true)
×
1455
        return;
×
1456

1457
    VCWidget* widget;
1458
    foreach (widget, m_selectedWidgets)
×
1459
        widget->setFrameStyle(KVCFrameStyleRaised);
×
1460
}
1461

1462
void VirtualConsole::slotFrameNone()
×
1463
{
1464
    Q_ASSERT(contents() != NULL);
×
1465

1466
    if (m_selectedWidgets.isEmpty() == true)
×
1467
        return;
×
1468

1469
    VCWidget* widget;
1470
    foreach (widget, m_selectedWidgets)
×
1471
        widget->setFrameStyle(KVCFrameStyleNone);
×
1472
}
1473

1474
/*****************************************************************************
1475
 * Dock area
1476
 *****************************************************************************/
1477

1478
VCDockArea* VirtualConsole::dockArea() const
×
1479
{
1480
    return m_dockArea;
×
1481
}
1482

1483
void VirtualConsole::initDockArea()
152✔
1484
{
1485
    if (m_dockArea != NULL)
152✔
1486
        delete m_dockArea;
×
1487

1488
    m_dockArea = new VCDockArea(this, m_doc->inputOutputMap());
152✔
1489
    m_dockArea->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
152✔
1490

1491
    // Add the dock area into the master horizontal layout
1492
    layout()->addWidget(m_dockArea);
152✔
1493

1494
    /* Show the dock area by default */
1495
    m_dockArea->show();
152✔
1496
}
152✔
1497

1498
/*****************************************************************************
1499
 * Contents
1500
 *****************************************************************************/
1501

1502
VCFrame* VirtualConsole::contents() const
1,574✔
1503
{
1504
    return m_contents;
1,574✔
1505
}
1506

1507
void VirtualConsole::resetContents()
152✔
1508
{
1509
    if (m_contents != NULL)
152✔
1510
        delete m_contents;
×
1511

1512
    Q_ASSERT(m_scrollArea != NULL);
152✔
1513
    m_contents = new VCFrame(m_scrollArea, m_doc);
152✔
1514
    m_contents->setFrameStyle(0);
152✔
1515

1516
    // Get virtual console size from properties
1517
    QSize size(m_properties.size());
152✔
1518
    contents()->resize(size);
152✔
1519
    contents()->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
152✔
1520
    m_scrollArea->setWidget(contents());
152✔
1521

1522
    /* Disconnect old key handlers to prevent duplicates */
1523
    disconnect(this, SIGNAL(keyPressed(const QKeySequence&)),
304✔
1524
               contents(), SLOT(slotKeyPressed(const QKeySequence&)));
152✔
1525
    disconnect(this, SIGNAL(keyReleased(const QKeySequence&)),
304✔
1526
               contents(), SLOT(slotKeyReleased(const QKeySequence&)));
152✔
1527

1528
    /* Connect new key handlers */
1529
    connect(this, SIGNAL(keyPressed(const QKeySequence&)),
304✔
1530
            contents(), SLOT(slotKeyPressed(const QKeySequence&)));
152✔
1531
    connect(this, SIGNAL(keyReleased(const QKeySequence&)),
304✔
1532
            contents(), SLOT(slotKeyReleased(const QKeySequence&)));
152✔
1533

1534
    /* Make the contents area take up all available space */
1535
    contents()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
152✔
1536

1537
    m_clipboard.clear();
152✔
1538
    m_selectedWidgets.clear();
152✔
1539
    m_latestWidgetId = 0;
152✔
1540
    m_widgetsMap.clear();
152✔
1541

1542
    /* Update actions' enabled status */
1543
    updateActions();
152✔
1544

1545
    /* Reset all properties but size */
1546
    m_properties.setGrandMasterVisible(true);
152✔
1547
    m_properties.setGrandMasterSliderMode(GrandMaster::Normal);
152✔
1548
    m_properties.setGrandMasterChannelMode(GrandMaster::Intensity);
152✔
1549
    m_properties.setGrandMasterValueMode(GrandMaster::Reduce);
152✔
1550
    m_properties.setGrandMasterInputSource(InputOutputMap::invalidUniverse(), QLCChannel::invalid());
152✔
1551

1552
    m_dockArea->setGrandMasterVisible(m_properties.grandMasterVisible());
152✔
1553
    m_dockArea->setGrandMasterInvertedAppearance(m_properties.grandMasterSliderMode());
152✔
1554
}
152✔
1555

1556
void VirtualConsole::addWidgetInMap(VCWidget* widget)
2✔
1557
{
1558
    // Valid ID ?
1559
    if (widget->id() != VCWidget::invalidId())
2✔
1560
    {
1561
        // Maybe we don't know this widget yet
1562
        if (!m_widgetsMap.contains(widget->id()))
×
1563
        {
1564
            m_widgetsMap.insert(widget->id(), widget);
×
1565
            return;
×
1566
        }
1567

1568
        // Maybe we already know this widget
1569
        if (m_widgetsMap[widget->id()] == widget)
×
1570
        {
1571
            qDebug() << Q_FUNC_INFO << "widget" << widget->id() << "already in map";
×
1572
            return;
×
1573
        }
1574

1575
        // This widget id conflicts with another one we have to change it.
1576
        qDebug() << Q_FUNC_INFO << "widget id" << widget->id() << "conflicts, creating a new ID";
×
1577
    }
1578

1579
    quint32 wid = newWidgetId();
2✔
1580
    Q_ASSERT(!m_widgetsMap.contains(wid));
2✔
1581
    qDebug() << Q_FUNC_INFO << "id=" << wid;
2✔
1582
    widget->setID(wid);
2✔
1583
    m_widgetsMap.insert(wid, widget);
2✔
1584
}
1585

1586
void VirtualConsole::setupWidget(VCWidget *widget, VCWidget *parent)
×
1587
{
1588
    Q_ASSERT(widget != NULL);
×
1589
    Q_ASSERT(parent != NULL);
×
1590

1591
    addWidgetInMap(widget);
×
1592
    connectWidgetToParent(widget, parent);
×
1593
    widget->show();
×
1594
    widget->move(parent->lastClickPoint());
×
1595
    clearWidgetSelection();
×
1596
    setWidgetSelected(widget, true);
×
1597
}
×
1598

1599
VCWidget *VirtualConsole::widget(quint32 id)
×
1600
{
1601
    if (id == VCWidget::invalidId())
×
1602
        return NULL;
×
1603

1604
    return m_widgetsMap.value(id, NULL);
×
1605
}
1606

1607
void VirtualConsole::initContents()
152✔
1608
{
1609
    Q_ASSERT(layout() != NULL);
152✔
1610

1611
    m_scrollArea = new QScrollArea(this);
152✔
1612
    m_contentsLayout->addWidget(m_scrollArea);
152✔
1613
    m_scrollArea->setAlignment(Qt::AlignCenter);
152✔
1614
    m_scrollArea->setWidgetResizable(false);
152✔
1615
    m_scrollArea->setAutoFillBackground(true);
152✔
1616

1617
    resetContents();
152✔
1618
}
152✔
1619

1620
/*****************************************************************************
1621
 * Key press handler
1622
 *****************************************************************************/
1623

1624
void VirtualConsole::keyPressEvent(QKeyEvent* event)
×
1625
{
1626
    if (event->isAutoRepeat() == true || event->key() == 0)
×
1627
    {
1628
        event->ignore();
×
1629
        return;
×
1630
    }
1631

1632
    QKeySequence seq(event->key() | (event->modifiers() & ~Qt::ControlModifier));
×
1633
    emit keyPressed(seq);
×
1634

1635
    event->accept();
×
1636
}
×
1637

1638
void VirtualConsole::keyReleaseEvent(QKeyEvent* event)
×
1639
{
1640
    if (event->isAutoRepeat() == true || event->key() == 0)
×
1641
    {
1642
        event->ignore();
×
1643
        return;
×
1644
    }
1645

1646
    QKeySequence seq(event->key() | event->modifiers());
×
1647
    emit keyReleased(seq);
×
1648

1649
    event->accept();
×
1650
}
×
1651

1652
/*****************************************************************************
1653
 * Main application mode
1654
 *****************************************************************************/
1655

1656
void VirtualConsole::toggleLiveEdit()
×
1657
{
1658
    // No live edit in Design Mode
1659
    Q_ASSERT(m_doc->mode() == Doc::Operate);
×
1660

1661
    if (m_liveEdit)
×
1662
    { // live edit was on, disable live edit
1663
        m_liveEdit = false;
×
1664
        disableEdit();
×
1665
    }
1666
    else
1667
    { // live edit was off, enable live edit
1668
        m_liveEdit = true;
×
1669
        enableEdit();
×
1670
    }
1671

1672
    // inform the widgets of the live edit status
1673
    QHash<quint32, VCWidget*>::iterator widgetIt = m_widgetsMap.begin();
×
1674
    while (widgetIt != m_widgetsMap.end())
×
1675
    {
1676
        VCWidget* widget = widgetIt.value();
×
1677
        widget->setLiveEdit(m_liveEdit);
×
1678
        ++widgetIt;
×
1679
    }
1680
    m_contents->setLiveEdit(m_liveEdit);
×
1681
}
×
1682

1683
bool VirtualConsole::liveEdit() const
354✔
1684
{
1685
    return m_liveEdit;
354✔
1686
}
1687

1688
void VirtualConsole::enableEdit()
160✔
1689
{
1690
    // Allow editing and adding in design mode
1691
    m_toolsSettingsAction->setEnabled(true);
160✔
1692
    m_editActionGroup->setEnabled(true);
160✔
1693
    m_addActionGroup->setEnabled(true);
160✔
1694
    m_bgActionGroup->setEnabled(true);
160✔
1695
    m_fgActionGroup->setEnabled(true);
160✔
1696
    m_fontActionGroup->setEnabled(true);
160✔
1697
    m_frameActionGroup->setEnabled(true);
160✔
1698
    m_stackingActionGroup->setEnabled(true);
160✔
1699
    m_functionWizardAction->setEnabled(true);
160✔
1700

1701
    // Set action shortcuts for design mode
1702
    m_addButtonAction->setShortcut(QKeySequence("CTRL+SHIFT+B"));
160✔
1703
    m_addButtonMatrixAction->setShortcut(QKeySequence("CTRL+SHIFT+M"));
160✔
1704
    m_addSliderAction->setShortcut(QKeySequence("CTRL+SHIFT+S"));
160✔
1705
    m_addSliderMatrixAction->setShortcut(QKeySequence("CTRL+SHIFT+I"));
160✔
1706
    m_addKnobAction->setShortcut(QKeySequence("CTRL+SHIFT+K"));
160✔
1707
    m_addSpeedDialAction->setShortcut(QKeySequence("CTRL+SHIFT+D"));
160✔
1708
    m_addXYPadAction->setShortcut(QKeySequence("CTRL+SHIFT+X"));
160✔
1709
    m_addCueListAction->setShortcut(QKeySequence("CTRL+SHIFT+C"));
160✔
1710
    m_addFrameAction->setShortcut(QKeySequence("CTRL+SHIFT+F"));
160✔
1711
    m_addSoloFrameAction->setShortcut(QKeySequence("CTRL+SHIFT+O"));
160✔
1712
    m_addLabelAction->setShortcut(QKeySequence("CTRL+SHIFT+L"));
160✔
1713
    m_addAudioTriggersAction->setShortcut(QKeySequence("CTRL+SHIFT+A"));
160✔
1714
    m_addClockAction->setShortcut(QKeySequence("CTRL+SHIFT+T"));
160✔
1715
    m_addAnimationAction->setShortcut(QKeySequence("CTRL+SHIFT+R"));
160✔
1716

1717
    m_editCutAction->setShortcut(QKeySequence("CTRL+X"));
160✔
1718
    m_editCopyAction->setShortcut(QKeySequence("CTRL+C"));
160✔
1719
    m_editPasteAction->setShortcut(QKeySequence("CTRL+V"));
160✔
1720
    m_editDeleteAction->setShortcut(QKeySequence("Delete"));
160✔
1721
    m_editPropertiesAction->setShortcut(QKeySequence("CTRL+E"));
160✔
1722

1723
    m_bgColorAction->setShortcut(QKeySequence("SHIFT+B"));
160✔
1724
    m_bgImageAction->setShortcut(QKeySequence("SHIFT+I"));
160✔
1725
    m_bgDefaultAction->setShortcut(QKeySequence("SHIFT+ALT+B"));
160✔
1726
    m_fgColorAction->setShortcut(QKeySequence("SHIFT+F"));
160✔
1727
    m_fgDefaultAction->setShortcut(QKeySequence("SHIFT+ALT+F"));
160✔
1728
    m_fontAction->setShortcut(QKeySequence("SHIFT+O"));
160✔
1729
    m_resetFontAction->setShortcut(QKeySequence("SHIFT+ALT+O"));
160✔
1730
    m_frameSunkenAction->setShortcut(QKeySequence("SHIFT+S"));
160✔
1731
    m_frameRaisedAction->setShortcut(QKeySequence("SHIFT+R"));
160✔
1732
    m_frameNoneAction->setShortcut(QKeySequence("SHIFT+ALT+S"));
160✔
1733

1734
    m_stackingRaiseAction->setShortcut(QKeySequence("SHIFT+UP"));
160✔
1735
    m_stackingLowerAction->setShortcut(QKeySequence("SHIFT+DOWN"));
160✔
1736

1737
    // Show toolbar
1738
    m_toolbar->show();
160✔
1739
}
160✔
1740

1741
void VirtualConsole::disableEdit()
30✔
1742
{
1743
    // Don't allow editing or adding in operate mode
1744
    m_toolsSettingsAction->setEnabled(false);
30✔
1745
    m_editActionGroup->setEnabled(false);
30✔
1746
    m_addActionGroup->setEnabled(false);
30✔
1747
    m_bgActionGroup->setEnabled(false);
30✔
1748
    m_fgActionGroup->setEnabled(false);
30✔
1749
    m_fontActionGroup->setEnabled(false);
30✔
1750
    m_frameActionGroup->setEnabled(false);
30✔
1751
    m_stackingActionGroup->setEnabled(false);
30✔
1752
    m_functionWizardAction->setEnabled(false);
30✔
1753

1754
    // Disable action shortcuts in operate mode
1755
    m_addButtonAction->setShortcut(QKeySequence());
30✔
1756
    m_addButtonMatrixAction->setShortcut(QKeySequence());
30✔
1757
    m_addSliderAction->setShortcut(QKeySequence());
30✔
1758
    m_addSliderMatrixAction->setShortcut(QKeySequence());
30✔
1759
    m_addKnobAction->setShortcut(QKeySequence());
30✔
1760
    m_addSpeedDialAction->setShortcut(QKeySequence());
30✔
1761
    m_addXYPadAction->setShortcut(QKeySequence());
30✔
1762
    m_addCueListAction->setShortcut(QKeySequence());
30✔
1763
    m_addFrameAction->setShortcut(QKeySequence());
30✔
1764
    m_addSoloFrameAction->setShortcut(QKeySequence());
30✔
1765
    m_addLabelAction->setShortcut(QKeySequence());
30✔
1766
    m_addAudioTriggersAction->setShortcut(QKeySequence());
30✔
1767
    m_addClockAction->setShortcut(QKeySequence());
30✔
1768
    m_addAnimationAction->setShortcut(QKeySequence());
30✔
1769

1770
    m_editCutAction->setShortcut(QKeySequence());
30✔
1771
    m_editCopyAction->setShortcut(QKeySequence());
30✔
1772
    m_editPasteAction->setShortcut(QKeySequence());
30✔
1773
    m_editDeleteAction->setShortcut(QKeySequence());
30✔
1774
    m_editPropertiesAction->setShortcut(QKeySequence());
30✔
1775

1776
    m_bgColorAction->setShortcut(QKeySequence());
30✔
1777
    m_bgImageAction->setShortcut(QKeySequence());
30✔
1778
    m_bgDefaultAction->setShortcut(QKeySequence());
30✔
1779
    m_fgColorAction->setShortcut(QKeySequence());
30✔
1780
    m_fgDefaultAction->setShortcut(QKeySequence());
30✔
1781
    m_fontAction->setShortcut(QKeySequence());
30✔
1782
    m_resetFontAction->setShortcut(QKeySequence());
30✔
1783
    m_frameSunkenAction->setShortcut(QKeySequence());
30✔
1784
    m_frameRaisedAction->setShortcut(QKeySequence());
30✔
1785
    m_frameNoneAction->setShortcut(QKeySequence());
30✔
1786

1787
    m_stackingRaiseAction->setShortcut(QKeySequence());
30✔
1788
    m_stackingLowerAction->setShortcut(QKeySequence());
30✔
1789

1790
    // Hide toolbar; there's nothing usable there in operate mode
1791
    m_toolbar->hide();
30✔
1792

1793
    // Make sure the virtual console contents has the focus.
1794
    // Without this, key combinations don't work unless
1795
    // the user clicks on some VC area
1796
    m_contents->setFocus();
30✔
1797
}
30✔
1798

1799
void VirtualConsole::slotModeChanged(Doc::Mode mode)
190✔
1800
{
1801
    if (mode == Doc::Operate)
190✔
1802
    { // Switch from Design mode to Operate mode
1803
        // Hide edit tools
1804
        disableEdit();
30✔
1805
    }
1806
    else
1807
    { // Switch from Operate mode to Design mode
1808
        if (m_liveEdit)
160✔
1809
        {
1810
            // Edit tools already shown,
1811
            // inform the widgets that we are out of live edit mode
1812
            m_liveEdit = false;
×
1813
            QHash<quint32, VCWidget*>::iterator widgetIt = m_widgetsMap.begin();
×
1814
            while (widgetIt != m_widgetsMap.end())
×
1815
            {
1816
                VCWidget* widget = widgetIt.value();
×
1817
                widget->cancelLiveEdit();
×
1818
                ++widgetIt;
×
1819
            }
1820
            m_contents->cancelLiveEdit();
×
1821
        }
1822
        else
1823
        {
1824
            // Show edit tools
1825
            enableEdit();
160✔
1826
        }
1827
    }
1828
}
190✔
1829

1830
/*****************************************************************************
1831
 * Load & Save
1832
 *****************************************************************************/
1833

1834
bool VirtualConsole::loadXML(QXmlStreamReader &root)
×
1835
{
1836
    if (root.name() != KXMLQLCVirtualConsole)
×
1837
    {
1838
        qWarning() << Q_FUNC_INFO << "Virtual Console node not found";
×
1839
        return false;
×
1840
    }
1841

1842
    while (root.readNextStartElement())
×
1843
    {
1844
        //qDebug() << "VC tag:" << root.name();
1845
        if (root.name() == KXMLQLCVCProperties)
×
1846
        {
1847
            /* Properties */
1848
            m_properties.loadXML(root);
×
1849
            QSize size(m_properties.size());
×
1850
            contents()->resize(size);
×
1851
            contents()->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
×
1852
        }
1853
        else if (root.name() == KXMLQLCVCFrame)
×
1854
        {
1855
            /* Contents */
1856
            Q_ASSERT(m_contents != NULL);
×
1857
            m_contents->loadXML(root);
×
1858
        }
1859
        else
1860
        {
1861
            qWarning() << Q_FUNC_INFO << "Unknown Virtual Console tag"
×
1862
                       << root.name().toString();
×
1863
            root.skipCurrentElement();
×
1864
        }
1865
    }
1866

1867
    return true;
×
1868
}
1869

1870
bool VirtualConsole::saveXML(QXmlStreamWriter *doc)
×
1871
{
1872
    Q_ASSERT(doc != NULL);
×
1873

1874
    /* Virtual Console entry */
1875
    doc->writeStartElement(KXMLQLCVirtualConsole);
×
1876

1877
    /* Contents */
1878
    Q_ASSERT(m_contents != NULL);
×
1879
    m_contents->saveXML(doc);
×
1880

1881
    /* Properties */
1882
    m_properties.saveXML(doc);
×
1883

1884
    /* End the <VirtualConsole> tag */
1885
    doc->writeEndElement();
×
1886

1887
    return true;
×
1888
}
1889

1890
QList<VCWidget *> VirtualConsole::getChildren(VCWidget *obj)
×
1891
{
1892
    QList<VCWidget *> list;
×
1893
    if (obj == NULL)
×
1894
        return list;
×
1895
    QListIterator <VCWidget*> it(obj->findChildren<VCWidget*>());
×
1896
    while (it.hasNext() == true)
×
1897
    {
1898
        VCWidget* child = it.next();
×
1899
        list.append(child);
×
1900
        list.append(getChildren(child));
×
1901
    }
1902
    return list;
×
1903
}
×
1904

1905
void VirtualConsole::postLoad()
×
1906
{
1907
    m_contents->postLoad();
×
1908

1909
    /* apply GM values
1910
      this should probably be placed in another place, but at the moment m_properties
1911
      is just loaded in VirtualConsole */
1912
    m_doc->inputOutputMap()->setGrandMasterValue(255);
×
1913
    m_doc->inputOutputMap()->setGrandMasterValueMode(m_properties.grandMasterValueMode());
×
1914
    m_doc->inputOutputMap()->setGrandMasterChannelMode(m_properties.grandMasterChannelMode());
×
1915

1916
    /* Go through widgets, check IDs and register */
1917
    /* widgets to the map */
1918
    /* This code is the same as the one in addWidgetInMap() */
1919
    /* We have to repeat it to limit conflicts if */
1920
    /* one widget was not saved with a valid ID, */
1921
    /* as addWidgetInMap ensures the widget WILL be added */
1922
    QList<VCWidget *> widgetsList = getChildren(m_contents);
×
1923
    QList<VCWidget *> invalidWidgetsList;
×
1924
    foreach (VCWidget *widget, widgetsList)
×
1925
    {
1926
        quint32 wid = widget->id();
×
1927
        if (wid != VCWidget::invalidId())
×
1928
        {
1929
            if (!m_widgetsMap.contains(wid))
×
1930
                m_widgetsMap.insert(wid, widget);
×
1931
            else if (m_widgetsMap[wid] != widget)
×
1932
                invalidWidgetsList.append(widget);
×
1933
        }
1934
        else
1935
            invalidWidgetsList.append(widget);
×
1936
    }
×
1937
    foreach (VCWidget *widget, invalidWidgetsList)
×
1938
        addWidgetInMap(widget);
×
1939

1940
    m_dockArea->setGrandMasterVisible(m_properties.grandMasterVisible());
×
1941
    m_dockArea->setGrandMasterInvertedAppearance(m_properties.grandMasterSliderMode());
×
1942

1943
    m_contents->setFocus();
×
1944

1945
    emit loaded();
×
1946
}
×
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