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

mcallegari / qlcplus / 22258491215

21 Feb 2026 02:28PM UTC coverage: 33.978% (-0.001%) from 33.979%
22258491215

push

github

web-flow
Merge pull request #1962 from jpue/nestedSubmaster

qmlui,ui: improve nested submasters

1 of 5 new or added lines in 1 file covered. (20.0%)

1 existing line in 1 file now uncovered.

17651 of 51948 relevant lines covered (33.98%)

19782.85 hits per line

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

45.11
/ui/src/virtualconsole/vcframe.cpp
1
/*
2
  Q Light Controller Plus
3
  vcframe.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 <QMapIterator>
24
#include <QMetaObject>
25
#include <QComboBox>
26
#include <QMessageBox>
27
#include <QSettings>
28
#include <QPainter>
29
#include <QAction>
30
#include <QStyle>
31
#include <QDebug>
32
#include <QPoint>
33
#include <QSize>
34
#include <QMenu>
35
#include <QFont>
36
#include <QList>
37

38
#include "vcframepageshortcut.h"
39
#include "vcpropertieseditor.h"
40
#include "vcframeproperties.h"
41
#include "vcaudiotriggers.h"
42
#include "virtualconsole.h"
43
#include "vcsoloframe.h"
44
#include "vcspeeddial.h"
45
#include "vccuelist.h"
46
#include "vcbutton.h"
47
#include "vcslider.h"
48
#include "vcmatrix.h"
49
#include "qlcfile.h"
50
#include "vcframe.h"
51
#include "vclabel.h"
52
#include "vcxypad.h"
53
#include "vcclock.h"
54
#include "apputil.h"
55
#include "doc.h"
56

57
const QSize VCFrame::defaultSize(QSize(200, 200));
58

59
const quint8 VCFrame::nextPageInputSourceId = 0;
60
const quint8 VCFrame::previousPageInputSourceId = 1;
61
const quint8 VCFrame::enableInputSourceId = 2;
62
const quint8 VCFrame::shortcutsBaseInputSourceId = 20;
63

64
VCFrame::VCFrame(QWidget* parent, Doc* doc, bool canCollapse)
95✔
65
    : VCWidget(parent, doc)
66
    , m_hbox(NULL)
95✔
67
    , m_collapseButton(NULL)
95✔
68
    , m_enableButton(NULL)
95✔
69
    , m_label(NULL)
95✔
70
    , m_collapsed(false)
95✔
71
    , m_showHeader(true)
95✔
72
    , m_showEnableButton(true)
95✔
73
    , m_multiPageMode(false)
95✔
74
    , m_currentPage(0)
95✔
75
    , m_totalPagesNumber(1)
95✔
76
    , m_nextPageBtn(NULL)
95✔
77
    , m_prevPageBtn(NULL)
95✔
78
    , m_pageCombo(NULL)
95✔
79
    , m_pagesLoop(false)
95✔
80
{
81
    /* Set the class name "VCFrame" as the object name as well */
82
    setObjectName(VCFrame::staticMetaObject.className());
95✔
83
    setFrameStyle(KVCFrameStyleSunken);
95✔
84
    setAllowChildren(true);
95✔
85
    setType(VCWidget::FrameWidget);
95✔
86

87
    if (canCollapse == true)
95✔
88
        createHeader();
3✔
89

90
    QSettings settings;
95✔
91
    QVariant var = settings.value(SETTINGS_FRAME_SIZE);
95✔
92
    if (var.isValid() == true)
95✔
93
        resize(var.toSize());
×
94
    else
95
        resize(defaultSize);
95✔
96
    m_width = this->width();
95✔
97
    m_height = this->height();
95✔
98
}
95✔
99

100
VCFrame::~VCFrame()
175✔
101
{
102
}
175✔
103

104
bool VCFrame::isBottomFrame() const
13✔
105
{
106
    return (parentWidget() != NULL && qobject_cast<VCFrame*>(parentWidget()) == NULL);
13✔
107
}
108

109
void VCFrame::setDisableState(bool disable)
×
110
{
111
    if (m_enableButton)
×
112
    {
113
        m_enableButton->blockSignals(true);
×
114
        m_enableButton->setChecked(!disable);
×
115
        m_enableButton->blockSignals(false);
×
116
    }
117

118
    foreach (VCWidget* widget, this->findChildren<VCWidget*>())
×
119
    {
120
        widget->setDisableState(disable);
×
121
        if (!disable)
×
122
            widget->adjustIntensity(intensity());
×
123
    }
×
124

125
    m_disableState = disable;
×
126

127
    emit disableStateChanged(disable);
×
128
    updateFeedback();
×
129
}
×
130

131
void VCFrame::setLiveEdit(bool liveEdit)
×
132
{
133
    if (m_doc->mode() == Doc::Design)
×
134
        return;
×
135

136
    m_liveEdit = liveEdit;
×
137

138
    if (!m_disableState)
×
139
        enableWidgetUI(!m_liveEdit);
×
140

141
    updateSubmasterValue();
×
142

143
    unsetCursor();
×
144
    update();
×
145
}
146

147
void VCFrame::setCaption(const QString& text)
5✔
148
{
149
    if (m_label != NULL)
5✔
150
    {
151
        if (!shortcuts().isEmpty() && m_currentPage < shortcuts().length())
1✔
152
        {
153
            // Show caption, if there is no page name
154
            if (m_pageShortcuts.at(m_currentPage)->name() == "")
×
155
                m_label->setText(text);
×
156
            else
157
            {
158
                // Show only page name, if there is no caption
159
                if (text == "")
×
160
                    m_label->setText(m_pageShortcuts.at(m_currentPage)->name());
×
161
                else
162
                    m_label->setText(text + " - " + m_pageShortcuts.at(m_currentPage)->name());
×
163
            }
164
        }
165
        else
166
            m_label->setText(text);
1✔
167
    }
168

169
    VCWidget::setCaption(text);
5✔
170
}
5✔
171

172
void VCFrame::setFont(const QFont &font)
×
173
{
174
    if (m_label != NULL)
×
175
    {
176
        m_label->setFont(font);
×
177
        m_hasCustomFont = true;
×
178
        m_doc->setModified();
×
179
    }
180
}
×
181

182
QFont VCFrame::font() const
×
183
{
184
    if (m_label != NULL)
×
185
        return m_label->font();
×
186
    else
187
        return VCWidget::font();
×
188
}
189

190
void VCFrame::setForegroundColor(const QColor &color)
×
191
{
192
    if (m_label != NULL)
×
193
    {
194
        m_label->setStyleSheet("QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #666666, stop: 1 #000000); "
×
195
                               "color: " + color.name() + "; border-radius: 3px; padding: 3px; margin-left: 2px; }");
×
196
        m_hasCustomForegroundColor = true;
×
197
        m_doc->setModified();
×
198
    }
199
}
×
200

201
QColor VCFrame::foregroundColor() const
×
202
{
203
    if (m_label != NULL)
×
204
        return m_label->palette().color(m_label->foregroundRole());
×
205
    else
206
        return VCWidget::foregroundColor();
×
207
}
208

209
void VCFrame::setHeaderVisible(bool enable)
2✔
210
{
211
    m_showHeader = enable;
2✔
212

213
    if (m_hbox == NULL)
2✔
214
        createHeader();
1✔
215

216
    if (enable == false)
2✔
217
    {
218
        m_collapseButton->hide();
×
219
        m_label->hide();
×
220
        m_enableButton->hide();
×
221
    }
222
    else
223
    {
224
        m_collapseButton->show();
2✔
225
        m_label->show();
2✔
226
        if (m_showEnableButton)
2✔
227
            m_enableButton->show();
2✔
228
    }
229
}
2✔
230

231
bool VCFrame::isHeaderVisible() const
4✔
232
{
233
    return m_showHeader;
4✔
234
}
235

236
void VCFrame::setEnableButtonVisible(bool show)
2✔
237
{
238
    if (show && m_showHeader) m_enableButton->show();
2✔
239
    else m_enableButton->hide();
×
240

241
    m_showEnableButton = show;
2✔
242
}
2✔
243

244
bool VCFrame::isEnableButtonVisible() const
3✔
245
{
246
    return m_showEnableButton;
3✔
247
}
248

249
bool VCFrame::isCollapsed() const
6✔
250
{
251
    return m_collapsed;
6✔
252
}
253

254
QSize VCFrame::originalSize() const
×
255
{
256
    return QSize(m_width, m_height);
×
257
}
258

259
void VCFrame::slotCollapseButtonToggled(bool toggle)
×
260
{
261
    if (toggle == true)
×
262
    {
263
        m_width = this->width();
×
264
        m_height = this->height();
×
265
        if (m_multiPageMode == true)
×
266
        {
267
            if (m_prevPageBtn) m_prevPageBtn->hide();
×
268
            if (m_nextPageBtn) m_nextPageBtn->hide();
×
269
        }
270
        resize(QSize(200, 40));
×
271
        m_collapsed = true;
×
272
    }
273
    else
274
    {
275
        resize(QSize(m_width, m_height));
×
276
        if (m_multiPageMode == true)
×
277
        {
278
            if (m_prevPageBtn) m_prevPageBtn->show();
×
279
            if (m_nextPageBtn) m_nextPageBtn->show();
×
280
        }
281
        m_collapsed = false;
×
282
    }
283
    m_doc->setModified();
×
284
}
×
285

286
void VCFrame::slotEnableButtonClicked(bool checked)
×
287
{
288
    setDisableState(!checked);
×
289
}
×
290

291
void VCFrame::createHeader()
4✔
292
{
293
    if (m_hbox != NULL)
4✔
294
        return;
×
295

296
    QVBoxLayout *vbox = new QVBoxLayout(this);
4✔
297
    /* Main HBox */
298
    m_hbox = new QHBoxLayout();
4✔
299
    m_hbox->setGeometry(QRect(0, 0, 200, 40));
4✔
300

301
    layout()->setSpacing(2);
4✔
302
    layout()->setContentsMargins(4, 4, 4, 4);
4✔
303
    layout()->addItem(m_hbox);
4✔
304
    vbox->addStretch();
4✔
305

306
    m_collapseButton = new QToolButton(this);
4✔
307
    m_collapseButton->setStyle(AppUtil::saneStyle());
4✔
308
    m_collapseButton->setIconSize(QSize(32, 32));
4✔
309
    m_collapseButton->setMinimumSize(QSize(32, 32));
4✔
310
    m_collapseButton->setMaximumSize(QSize(32, 32));
4✔
311
    m_collapseButton->setIcon(QIcon(":/expand.png"));
4✔
312
    m_collapseButton->setCheckable(true);
4✔
313
    QString cBtnSS = "QToolButton { background-color: #E0DFDF; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
4✔
314
    cBtnSS += "QToolButton:pressed { background-color: #919090; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
4✔
315
    m_collapseButton->setStyleSheet(cBtnSS);
4✔
316

317
    m_hbox->addWidget(m_collapseButton);
4✔
318
    connect(m_collapseButton, SIGNAL(toggled(bool)), this, SLOT(slotCollapseButtonToggled(bool)));
4✔
319

320
    m_label = new QLabel(this);
4✔
321
    m_label->setText(this->caption());
4✔
322
    QString txtColor = "white";
4✔
323
    if (m_hasCustomForegroundColor)
4✔
324
        txtColor = this->foregroundColor().name();
×
325
    m_label->setStyleSheet("QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #666666, stop: 1 #000000); "
4✔
326
                           "color: " + txtColor + "; border-radius: 3px; padding: 3px; margin-left: 2px; margin-right: 2px; }");
8✔
327

328
    if (m_hasCustomFont)
4✔
329
        m_label->setFont(font());
×
330
    else
331
    {
332
        QFont m_font = QApplication::font();
4✔
333
        m_font.setBold(true);
4✔
334
        m_font.setPixelSize(12);
4✔
335
        m_label->setFont(m_font);
4✔
336
    }
4✔
337
    m_hbox->addWidget(m_label);
4✔
338

339
    m_enableButton = new QToolButton(this);
4✔
340
    m_enableButton->setStyle(AppUtil::saneStyle());
4✔
341
    m_enableButton->setIconSize(QSize(32, 32));
4✔
342
    m_enableButton->setMinimumSize(QSize(32, 32));
4✔
343
    m_enableButton->setMaximumSize(QSize(32, 32));
4✔
344
    m_enableButton->setIcon(QIcon(":/check.png"));
4✔
345
    m_enableButton->setCheckable(true);
4✔
346
    QString eBtnSS = "QToolButton { background-color: #E0DFDF; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
4✔
347
    eBtnSS += "QToolButton:checked { background-color: #D7DE75; border: 1px solid gray; border-radius: 3px; padding: 3px; } ";
4✔
348
    m_enableButton->setStyleSheet(eBtnSS);
4✔
349
    m_enableButton->setEnabled(true);
4✔
350
    m_enableButton->setChecked(true);
4✔
351
    if (!m_showEnableButton)
4✔
352
        m_enableButton->hide();
×
353

354
    m_hbox->addWidget(m_enableButton);
4✔
355
    connect(m_enableButton, SIGNAL(clicked(bool)), this, SLOT(slotEnableButtonClicked(bool)));
4✔
356
}
4✔
357

358
/*********************************************************************
359
 * Pages
360
 *********************************************************************/
361

362
void VCFrame::setMultipageMode(bool enable)
2✔
363
{
364
    if (m_multiPageMode == enable)
2✔
365
        return;
2✔
366

367
    if (enable == true)
×
368
    {
369
        if (m_prevPageBtn != NULL && m_nextPageBtn != NULL && m_pageCombo != NULL)
×
370
            return;
×
371

372
        QString btnSS = "QToolButton { background-color: #E0DFDF; border: 1px solid gray; border-radius: 3px; padding: 3px; margin-left: 2px; }";
×
373
        btnSS += "QToolButton:pressed { background-color: #919090; border: 1px solid gray; border-radius: 3px; padding: 3px; margin-left: 2px; }";
×
374

375
        m_prevPageBtn = new QToolButton(this);
×
376
        m_prevPageBtn->setStyle(AppUtil::saneStyle());
×
377
        m_prevPageBtn->setIconSize(QSize(32, 32));
×
378
        m_prevPageBtn->setMinimumSize(QSize(32, 32));
×
379
        m_prevPageBtn->setMaximumSize(QSize(32, 32));
×
380
        m_prevPageBtn->setIcon(QIcon(":/back.png"));
×
381
        m_prevPageBtn->setStyleSheet(btnSS);
×
382
        m_hbox->addWidget(m_prevPageBtn);
×
383

384
        m_pageCombo = new QComboBox(this);
×
385
        m_pageCombo->setMaximumWidth(100);
×
386
        m_pageCombo->setFixedHeight(32);
×
387
        m_pageCombo->setFocusPolicy(Qt::NoFocus);
×
388

389
        /** Add a single shortcut until setTotalPagesNumber kicks in */
390
        addShortcut();
×
391

392
        m_pageCombo->setStyleSheet("QComboBox { background-color: black; color: red; margin-left: 2px; padding: 3px; }");
×
393
        if (m_hasCustomFont)
×
394
        {
395
            m_pageCombo->setFont(font());
×
396
        }
397
        else
398
        {
399
            QFont m_font = QApplication::font();
×
400
            m_font.setBold(true);
×
401
            m_font.setPixelSize(12);
×
402
            m_pageCombo->setFont(m_font);
×
403
        }
×
404
        m_hbox->addWidget(m_pageCombo);
×
405

406
        m_nextPageBtn = new QToolButton(this);
×
407
        m_nextPageBtn->setStyle(AppUtil::saneStyle());
×
408
        m_nextPageBtn->setIconSize(QSize(32, 32));
×
409
        m_nextPageBtn->setMinimumSize(QSize(32, 32));
×
410
        m_nextPageBtn->setMaximumSize(QSize(32, 32));
×
411
        m_nextPageBtn->setIcon(QIcon(":/forward.png"));
×
412
        m_nextPageBtn->setStyleSheet(btnSS);
×
413
        m_hbox->addWidget(m_nextPageBtn);
×
414

415
        connect (m_prevPageBtn, SIGNAL(clicked()), this, SLOT(slotPreviousPage()));
×
416
        connect (m_pageCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetPage(int)));
×
417
        connect (m_nextPageBtn, SIGNAL(clicked()), this, SLOT(slotNextPage()));
×
418

419
        if (this->isCollapsed() == false)
×
420
        {
421
            m_prevPageBtn->show();
×
422
            m_nextPageBtn->show();
×
423
        }
424
        else
425
        {
426
            m_prevPageBtn->hide();
×
427
            m_nextPageBtn->hide();
×
428
        }
429
        m_pageCombo->show();
×
430

431
        if (m_pagesMap.isEmpty())
×
432
        {
433
            QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
434
            while (it.hasNext() == true)
×
435
            {
436
                VCWidget* child = it.next();
×
437
                addWidgetToPageMap(child);
×
438
            }
439
        }
×
440
    }
×
441
    else
442
    {
443
        if (m_prevPageBtn == NULL && m_nextPageBtn == NULL && m_pageCombo == NULL)
×
444
            return;
×
445

446
        resetShortcuts();
×
447
        m_hbox->removeWidget(m_prevPageBtn);
×
448
        m_hbox->removeWidget(m_pageCombo);
×
449
        m_hbox->removeWidget(m_nextPageBtn);
×
450
        delete m_prevPageBtn;
×
451
        delete m_pageCombo;
×
452
        delete m_nextPageBtn;
×
453
        m_prevPageBtn = NULL;
×
454
        m_pageCombo = NULL;
×
455
        m_nextPageBtn = NULL;
×
456
        setCaption(caption());
×
457
    }
458

459
    m_multiPageMode = enable;
×
460
}
461

462
bool VCFrame::multipageMode() const
7✔
463
{
464
    return m_multiPageMode;
7✔
465
}
466

467
void VCFrame::setTotalPagesNumber(int num)
2✔
468
{
469
    if (num == m_totalPagesNumber)
2✔
470
        return;
2✔
471

472
    if (num < m_totalPagesNumber)
×
473
    {
474
        for (int i = 0; i < (m_totalPagesNumber - num); i++)
×
475
        {
476
            m_pageShortcuts.removeLast();
×
477
            if (m_pageCombo)
×
478
                m_pageCombo->removeItem(m_pageCombo->count() - 1);
×
479
        }
480
    }
481
    else
482
    {
483
        for (int i = 0; i < (num - m_totalPagesNumber); i++)
×
484
            addShortcut();
×
485
    }
486
    m_totalPagesNumber = num;
×
487
}
488

489
int VCFrame::totalPagesNumber() const
2✔
490
{
491
    return m_totalPagesNumber;
2✔
492
}
493

494
int VCFrame::currentPage() const
17✔
495
{
496
    if (m_multiPageMode == false)
17✔
497
        return 0;
17✔
498
    return m_currentPage;
×
499
}
500

501
void VCFrame::updatePageCombo()
2✔
502
{
503
    if (m_pageCombo == NULL || shortcuts().isEmpty())
2✔
504
        return;
2✔
505

506
    // Save current page to restore it afterwards
507
    int page = currentPage();
×
508
    m_pageCombo->blockSignals(true);
×
509
    m_pageCombo->clear();
×
510
    for (int i = 0; i < m_pageShortcuts.count(); i++)
×
511
        m_pageCombo->addItem(m_pageShortcuts.at(i)->name());
×
512
    m_pageCombo->setCurrentIndex(page);
×
513
    m_pageCombo->blockSignals(false);
×
514
}
515

516
/*********************************************************************
517
 * Shortcuts
518
 *********************************************************************/
519

520
void VCFrame::addShortcut()
×
521
{
522
    int index = m_pageShortcuts.count();
×
523
    m_pageShortcuts.append(new VCFramePageShortcut(index, VCFrame::shortcutsBaseInputSourceId + index));
×
524
    m_pageCombo->addItem(m_pageShortcuts.last()->name());
×
525
}
×
526

527
void VCFrame::setShortcuts(QList<VCFramePageShortcut *> shortcuts)
2✔
528
{
529
    resetShortcuts();
2✔
530
    foreach (VCFramePageShortcut const* shortcut, shortcuts)
2✔
531
    {
532
        m_pageShortcuts.append(new VCFramePageShortcut(*shortcut));
×
533
        if (shortcut->m_inputSource != NULL)
×
534
            setInputSource(shortcut->m_inputSource, shortcut->m_id);
×
535
    }
2✔
536
    updatePageCombo();
2✔
537
}
2✔
538

539
void VCFrame::resetShortcuts()
2✔
540
{
541
    int count = m_pageShortcuts.count();
2✔
542
    for (int i = 0; i < count; i++)
2✔
543
    {
544
        VCFramePageShortcut* shortcut = m_pageShortcuts.takeLast();
×
545
        delete shortcut;
×
546
    }
547
    m_pageShortcuts.clear();
2✔
548
}
2✔
549

550
QList<VCFramePageShortcut*> VCFrame::shortcuts() const
3✔
551
{
552
    return m_pageShortcuts;
3✔
553
}
554

555
void VCFrame::setPagesLoop(bool pagesLoop)
2✔
556
{
557
    m_pagesLoop = pagesLoop;
2✔
558
}
2✔
559

560
bool VCFrame::pagesLoop() const
1✔
561
{
562
    return m_pagesLoop;
1✔
563
}
564

565
void VCFrame::addWidgetToPageMap(VCWidget *widget)
8✔
566
{
567
    m_pagesMap.insert(widget, widget->page());
8✔
568
}
8✔
569

570
void VCFrame::removeWidgetFromPageMap(VCWidget *widget)
×
571
{
572
    m_pagesMap.remove(widget);
×
573
}
×
574

575
void VCFrame::slotPreviousPage()
×
576
{
577
    if (!m_pagesLoop && m_currentPage == 0)
×
578
        return;
×
579

580
    if (m_pagesLoop && m_currentPage == 0)
×
581
        slotSetPage(m_totalPagesNumber - 1);
×
582
    else
583
        slotSetPage(m_currentPage - 1);
×
584

585
    sendFeedback(m_currentPage, previousPageInputSourceId);
×
586
}
587

588
void VCFrame::slotNextPage()
×
589
{
590
    if (!m_pagesLoop && m_currentPage == m_totalPagesNumber - 1)
×
591
        return;
×
592

593
    if (m_pagesLoop && m_currentPage == m_totalPagesNumber - 1)
×
594
        slotSetPage(0);
×
595
    else
596
        slotSetPage(m_currentPage + 1);
×
597

598
    sendFeedback(m_currentPage, nextPageInputSourceId);
×
599
}
600

601
void VCFrame::slotSetPage(int pageNum)
17✔
602
{
603
    if (m_pageCombo)
17✔
604
    {
605
        if (pageNum >= 0 && pageNum < m_totalPagesNumber)
×
606
            m_currentPage = pageNum;
×
607

608
        m_pageCombo->blockSignals(true);
×
609
        m_pageCombo->setCurrentIndex(m_currentPage);
×
610
        m_pageCombo->blockSignals(false);
×
611
        setCaption(caption());
×
612

613
        QMapIterator <VCWidget*, int> it(m_pagesMap);
×
614
        while (it.hasNext() == true)
×
615
        {
616
            it.next();
×
617
            int page = it.value();
×
618
            VCWidget *widget = it.key();
×
619
            if (page == m_currentPage)
×
620
            {
621
                widget->setEnabled(true);
×
622
                widget->show();
×
623
                widget->updateFeedback();
×
624
            }
625
            else
626
            {
627
                widget->setEnabled(false);
×
628
                widget->hide();
×
629
            }
630
        }
631
        m_doc->setModified();
×
632
        emit pageChanged(m_currentPage);
×
633
    }
×
634
    updateFeedback();
17✔
635
}
17✔
636

637
void VCFrame::slotModeChanged(Doc::Mode mode)
21✔
638
{
639
    if (mode == Doc::Operate)
21✔
640
    {
641
        if (isDisabled())
16✔
642
            slotEnableButtonClicked(false);
×
643
        slotSetPage(currentPage());
16✔
644
        updateSubmasterValue();
16✔
645
        updateFeedback();
16✔
646
    }
647

648
    VCWidget::slotModeChanged(mode);
21✔
649
}
21✔
650

651
/*********************************************************************
652
 * Submasters
653
 *********************************************************************/
654

655
void VCFrame::slotSubmasterValueChanged(qreal value)
×
656
{
657
    qDebug() << Q_FUNC_INFO << "val:" << value;
×
658
    VCSlider *submaster = qobject_cast<VCSlider *>(sender());
×
659
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
660
    while (it.hasNext() == true)
×
661
    {
662
        VCWidget *child = it.next();
×
NEW
663
        if (child != NULL && child->parent() == this && child != submaster)
×
664
            child->adjustIntensity(value);
×
665
    }
666
}
×
667

668
void VCFrame::updateSubmasterValue()
16✔
669
{
670
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
16✔
671
    while (it.hasNext() == true)
18✔
672
    {
673
        VCWidget* child = it.next();
2✔
674
        if (child != NULL && child->parent() == this && child->type() == SliderWidget)
2✔
675
        {
676
            VCSlider* slider = reinterpret_cast<VCSlider*>(child);
×
NEW
677
            if (slider != NULL && slider->sliderMode() == VCSlider::Submaster)
×
678
                slider->emitSubmasterValue();
×
679
        }
680
    }
681
}
16✔
682

683
void VCFrame::adjustIntensity(qreal val)
×
684
{
685
    VCWidget::adjustIntensity(val);
×
686

687
    if (isDisabled())
×
688
        return;
×
689

690
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
691
    while (it.hasNext() == true)
×
692
    {
693
        VCWidget *child = it.next();
×
NEW
694
        if (child != NULL && child->parent() == this)
×
695
            child->adjustIntensity(val);
×
696
    }
697

NEW
698
    updateSubmasterValue();
×
UNCOV
699
}
×
700

701
/*****************************************************************************
702
 * Key Sequences
703
 *****************************************************************************/
704

705
void VCFrame::setEnableKeySequence(const QKeySequence &keySequence)
2✔
706
{
707
    m_enableKeySequence = QKeySequence(keySequence);
2✔
708
}
2✔
709

710
QKeySequence VCFrame::enableKeySequence() const
1✔
711
{
712
    return m_enableKeySequence;
1✔
713
}
714

715
void VCFrame::setNextPageKeySequence(const QKeySequence& keySequence)
2✔
716
{
717
    m_nextPageKeySequence = QKeySequence(keySequence);
2✔
718
}
2✔
719

720
QKeySequence VCFrame::nextPageKeySequence() const
1✔
721
{
722
    return m_nextPageKeySequence;
1✔
723
}
724

725
void VCFrame::setPreviousPageKeySequence(const QKeySequence& keySequence)
2✔
726
{
727
    m_previousPageKeySequence = QKeySequence(keySequence);
2✔
728
}
2✔
729

730
QKeySequence VCFrame::previousPageKeySequence() const
1✔
731
{
732
    return m_previousPageKeySequence;
1✔
733
}
734

735
void VCFrame::slotKeyPressed(const QKeySequence& keySequence)
×
736
{
737
    if (isEnabled() == false)
×
738
        return;
×
739

740
    if (m_enableKeySequence == keySequence)
×
741
        setDisableState(!isDisabled());
×
742
    else if (m_previousPageKeySequence == keySequence)
×
743
        slotPreviousPage();
×
744
    else if (m_nextPageKeySequence == keySequence)
×
745
        slotNextPage();
×
746
    else
747
    {
748
        foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
×
749
        {
750
            if (shortcut->m_keySequence == keySequence)
×
751
                slotSetPage(shortcut->m_page);
×
752
        }
×
753
    }
754
}
755

756
void VCFrame::updateFeedback()
33✔
757
{
758
    QSharedPointer<QLCInputSource> src = inputSource(enableInputSourceId);
33✔
759
    if (!src.isNull() && src->isValid() == true)
33✔
760
    {
761
        if (m_disableState == false)
×
762
        {
763
            sendFeedback(src->feedbackValue(QLCInputFeedback::UpperValue), enableInputSourceId);
×
764
        }
765
        else
766
        {
767
            // temporarily revert the disabled state otherwise this
768
            // feedback will never go through (cause of acceptsInput)
769
            m_disableState = false;
×
770
            sendFeedback(src->feedbackValue(QLCInputFeedback::LowerValue), enableInputSourceId);
×
771
            m_disableState = true;
×
772
        }
773
    }
774

775
    foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
33✔
776
    {
777
        QSharedPointer<QLCInputSource> src = shortcut->m_inputSource;
×
778
        if (!src.isNull() && src->isValid() == true)
×
779
        {
780
            if (m_currentPage == shortcut->m_page)
×
781
                sendFeedback(src->feedbackValue(QLCInputFeedback::UpperValue), src);
×
782
            else
783
                sendFeedback(src->feedbackValue(QLCInputFeedback::LowerValue), src);
×
784
        }
785
    }
33✔
786

787
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
33✔
788
    while (it.hasNext() == true)
37✔
789
    {
790
        VCWidget* child = it.next();
4✔
791
        if (child->parent() == this)
4✔
792
            child->updateFeedback();
4✔
793
    }
794
}
33✔
795

796
/*****************************************************************************
797
 * External input
798
 *****************************************************************************/
799

800
void VCFrame::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
801
{
802
    if (isEnabled() == false)
×
803
        return;
×
804

805
    quint32 pagedCh = (page() << 16) | channel;
×
806

807
    if (checkInputSource(universe, pagedCh, value, sender(), enableInputSourceId) && value)
×
808
        setDisableState(!isDisabled());
×
809
    else if (checkInputSource(universe, pagedCh, value, sender(), previousPageInputSourceId) && value)
×
810
        slotPreviousPage();
×
811
    else if (checkInputSource(universe, pagedCh, value, sender(), nextPageInputSourceId) && value)
×
812
        slotNextPage();
×
813
    else
814
    {
815
        foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
×
816
        {
817
            if (shortcut->m_inputSource != NULL &&
×
818
                    shortcut->m_inputSource->universe() == universe &&
×
819
                    shortcut->m_inputSource->channel() == pagedCh)
×
820
            {
821
                slotSetPage(shortcut->m_page);
×
822
            }
823
        }
×
824
    }
825
}
826

827
/*****************************************************************************
828
 * Clipboard
829
 *****************************************************************************/
830

831
VCWidget* VCFrame::createCopy(VCWidget* parent) const
1✔
832
{
833
    Q_ASSERT(parent != NULL);
1✔
834

835
    VCFrame* frame = new VCFrame(parent, m_doc, true);
1✔
836
    if (frame->copyFrom(this) == false)
1✔
837
    {
838
        delete frame;
×
839
        frame = NULL;
×
840
    }
841

842
    return frame;
1✔
843
}
844

845
bool VCFrame::copyFrom(const VCWidget* widget)
2✔
846
{
847
    const VCFrame* frame = qobject_cast<const VCFrame*> (widget);
2✔
848
    if (frame == NULL)
2✔
849
        return false;
1✔
850

851
    setHeaderVisible(frame->m_showHeader);
1✔
852
    setEnableButtonVisible(frame->m_showEnableButton);
1✔
853

854
    setMultipageMode(frame->m_multiPageMode);
1✔
855
    setTotalPagesNumber(frame->m_totalPagesNumber);
1✔
856

857
    setPagesLoop(frame->m_pagesLoop);
1✔
858

859
    setEnableKeySequence(frame->m_enableKeySequence);
1✔
860
    setNextPageKeySequence(frame->m_nextPageKeySequence);
1✔
861
    setPreviousPageKeySequence(frame->m_previousPageKeySequence);
1✔
862
    setShortcuts(frame->shortcuts());
1✔
863

864
    QListIterator <VCWidget*> it(widget->findChildren<VCWidget*>());
1✔
865
    while (it.hasNext() == true)
2✔
866
    {
867
        VCWidget* child = it.next();
1✔
868
        VCWidget* childCopy = NULL;
1✔
869

870
        /* findChildren() is recursive, so the list contains all
871
           possible child widgets below this frame. Each frame must
872
           save only its direct children to preserve hierarchy, so
873
           save only such widgets that have this widget as their
874
           direct parent. */
875
        if (child->parentWidget() == widget)
1✔
876
        {
877
            childCopy = child->createCopy(this);
1✔
878
            VirtualConsole::instance()->addWidgetInMap(childCopy);
1✔
879

880
            qDebug() << "Child copy in parent:" << childCopy->caption() << ", page:" << childCopy->page();
1✔
881
        }
882

883
        if (childCopy != NULL)
1✔
884
        {
885
            addWidgetToPageMap(childCopy);
1✔
886

887
            if (childCopy->type() == VCWidget::SliderWidget)
1✔
888
            {
889
                VCSlider *slider = qobject_cast<VCSlider*>(childCopy);
×
890
                // always connect a slider as it it was a submaster
891
                // cause this signal is emitted only when a slider is
892
                // a submaster
893
                connect(slider, SIGNAL(submasterValueChanged(qreal)),
×
894
                        this, SLOT(slotSubmasterValueChanged(qreal)));
895
            }
896
        }
897
    }
898

899
    if (m_multiPageMode)
1✔
900
        slotSetPage(frame->m_currentPage);
×
901

902
    /* Copy common stuff */
903
    return VCWidget::copyFrom(widget);
1✔
904
}
1✔
905

906
/*****************************************************************************
907
 * Properties
908
 *****************************************************************************/
909

910
void VCFrame::applyProperties(VCFrameProperties const& prop)
×
911
{
912
    if (multipageMode() == true && prop.cloneWidgets() == true && m_pagesMap.isEmpty() == false)
×
913
    {
914
        for (int pg = 1; pg < totalPagesNumber(); pg++)
×
915
        {
916
            QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
917
            while (it.hasNext() == true)
×
918
            {
919
                VCWidget* child = it.next();
×
920
                if (child->page() == 0 && child->parentWidget() == this)
×
921
                {
922
                    VCWidget *newWidget = child->createCopy(this);
×
923
                    VirtualConsole::instance()->addWidgetInMap(newWidget);
×
924
                    //qDebug() << "Cloning:" << newWidget->caption() << ", copy page:" << newWidget->page() << ", page to set:" << pg;
925
                    newWidget->setPage(pg);
×
926
                    newWidget->remapInputSources(pg);
×
927
                    newWidget->show();
×
928

929
                    bool multiPageFrame = false;
×
930
                    if (newWidget->type() == VCWidget::FrameWidget || newWidget->type() == VCWidget::SoloFrameWidget)
×
931
                    {
932
                        VCFrame *fr = qobject_cast<VCFrame *>(newWidget);
×
933
                        multiPageFrame = fr->multipageMode();
×
934
                    }
935
                    /** If the cloned widget is again a multipage frame, then there's not much
936
                     *  that can be done to distinguish nested pages, so we leave the children
937
                     *  mapping as it is */
938
                    if (multiPageFrame == false)
×
939
                    {
940
                        /**
941
                         *  Remap input sources to the new page, otherwise
942
                         *  all the cloned widgets would respond to the
943
                         *  same controls
944
                         */
945
                        foreach (VCWidget* widget, newWidget->findChildren<VCWidget*>())
×
946
                        {
947
                            //qDebug() << "Child" << widget->caption() << ", page:" << widget->page() << ", new page:" << pg;
948
                            widget->setPage(pg);
×
949
                            widget->remapInputSources(pg);
×
950
                        }
×
951
                    }
952

953
                    addWidgetToPageMap(newWidget);
×
954
                }
955
            }
956
        }
×
957
        slotSetPage(0);
×
958
    }
959
    else if (multipageMode() == false)
×
960
    {
961
        setTotalPagesNumber(1);
×
962
        resize(QSize(this->width(), this->height()));
×
963

964
        QMapIterator <VCWidget*, int> it(m_pagesMap);
×
965
        while (it.hasNext() == true)
×
966
        {
967
            it.next();
×
968
            int page = it.value();
×
969
            VCWidget *widget = it.key();
×
970
            if (page > 0)
×
971
            {
972
                removeWidgetFromPageMap(widget);
×
973
                delete widget;
×
974
            }
975
            else
976
            {
977
                widget->setEnabled(true);
×
978
                widget->show();
×
979
                widget->updateFeedback();
×
980
            }
981
        }
982
    }
×
983
    VirtualConsole* vc = VirtualConsole::instance();
×
984
    if (vc != NULL)
×
985
        vc->reselectWidgets();
×
986
}
×
987

988
void VCFrame::editProperties()
×
989
{
990
    if (isBottomFrame() == true)
×
991
        return;
×
992

993
    VCFrameProperties prop(NULL, this, m_doc);
×
994
    if (prop.exec() == QDialog::Accepted)
×
995
    {
996
        applyProperties(prop);
×
997
    }
998
}
×
999

1000
/*****************************************************************************
1001
 * Load & Save
1002
 *****************************************************************************/
1003

1004
bool VCFrame::loadXML(QXmlStreamReader &root)
4✔
1005
{
1006
    bool disableState = false;
4✔
1007

1008
    if (root.name() != xmlTagName())
4✔
1009
    {
1010
        qWarning() << Q_FUNC_INFO << "Frame node not found";
1✔
1011
        return false;
1✔
1012
    }
1013

1014
    /* Widget commons */
1015
    loadXMLCommon(root);
3✔
1016

1017
    // Sorted list for new shortcuts
1018
    QList<VCFramePageShortcut *> newShortcuts;
3✔
1019

1020
    /* Children */
1021
    while (root.readNextStartElement())
14✔
1022
    {
1023
        /*
1024
        qDebug() << "VC Frame <" << caption() << "> tag:" << root.name();
1025
        if (root.attributes().hasAttribute("Caption"))
1026
            qDebug() << "Widget caption:" << root.attributes().value("Caption").toString();
1027
        */
1028

1029
        if (root.name() == KXMLQLCWindowState)
11✔
1030
        {
1031
            /* Frame geometry (visibility is ignored) */
1032
            int x = 0, y = 0, w = 0, h = 0;
1✔
1033
            bool visible = false;
1✔
1034
            loadXMLWindowState(root, &x, &y, &w, &h, &visible);
1✔
1035
            setGeometry(x, y, w, h);
1✔
1036
            m_width = w;
1✔
1037
            m_height = h;
1✔
1038
        }
1039
        else if (root.name() == KXMLQLCVCWidgetAppearance)
10✔
1040
        {
1041
            /* Frame appearance */
1042
            loadXMLAppearance(root);
×
1043
        }
1044
        else if (root.name() == KXMLQLCVCFrameAllowChildren)
10✔
1045
        {
1046
            /* Allow children */
1047
            if (root.readElementText() == KXMLQLCTrue)
1✔
1048
                setAllowChildren(true);
×
1049
            else
1050
                setAllowChildren(false);
1✔
1051
        }
1052
        else if (root.name() == KXMLQLCVCFrameAllowResize)
9✔
1053
        {
1054
            /* Allow resize */
1055
            if (root.readElementText() == KXMLQLCTrue)
1✔
1056
                setAllowResize(true);
×
1057
            else
1058
                setAllowResize(false);
1✔
1059
        }
1060
        else if (root.name() == KXMLQLCVCFrameIsCollapsed)
8✔
1061
        {
1062
            /* Collapsed */
1063
            if (root.readElementText() == KXMLQLCTrue && m_collapseButton != NULL)
×
1064
                m_collapseButton->toggle();
×
1065
        }
1066
        else if (root.name() == KXMLQLCVCFrameIsDisabled)
8✔
1067
        {
1068
            /* Enabled */
1069
            if (root.readElementText() == KXMLQLCTrue)
×
1070
                disableState = true;
×
1071
        }
1072
        else if (root.name() == KXMLQLCVCFrameShowHeader)
8✔
1073
        {
1074
            if (root.readElementText() == KXMLQLCTrue)
×
1075
                setHeaderVisible(true);
×
1076
            else
1077
                setHeaderVisible(false);
×
1078
        }
1079
        else if (root.name() == KXMLQLCVCFrameShowEnableButton)
8✔
1080
        {
1081
            if (root.readElementText() == KXMLQLCTrue)
×
1082
                setEnableButtonVisible(true);
×
1083
            else
1084
                setEnableButtonVisible(false);
×
1085
        }
1086
        else if (this->type() == SoloFrameWidget && root.name() == KXMLQLCVCSoloFrameMixing)
8✔
1087
        {
1088
            if (root.readElementText() == KXMLQLCTrue)
×
1089
                reinterpret_cast<VCSoloFrame*>(this)->setSoloframeMixing(true);
×
1090
            else
1091
                reinterpret_cast<VCSoloFrame*>(this)->setSoloframeMixing(false);
×
1092
        }
1093
        else if (this->type() == SoloFrameWidget && root.name() == KXMLQLCVCSoloFrameExclude)
8✔
1094
        {
1095
            if (root.readElementText() == KXMLQLCTrue)
×
1096
                reinterpret_cast<VCSoloFrame*>(this)->setExcludeMonitoredFunctions(true);
×
1097
            else
1098
                reinterpret_cast<VCSoloFrame*>(this)->setExcludeMonitoredFunctions(false);
×
1099
        }
1100
        else if (root.name() == KXMLQLCVCFrameMultipage)
8✔
1101
        {
1102
            setMultipageMode(true);
×
1103
            QXmlStreamAttributes attrs = root.attributes();
×
1104
            if (attrs.hasAttribute(KXMLQLCVCFramePagesNumber))
×
1105
                setTotalPagesNumber(attrs.value(KXMLQLCVCFramePagesNumber).toString().toInt());
×
1106

1107
            if (attrs.hasAttribute(KXMLQLCVCFrameCurrentPage))
×
1108
                slotSetPage(attrs.value(KXMLQLCVCFrameCurrentPage).toString().toInt());
×
1109
            root.skipCurrentElement();
×
1110
        }
×
1111
        else if (root.name() == KXMLQLCVCFrameEnableSource)
8✔
1112
        {
1113
            QString str = loadXMLSources(root, enableInputSourceId);
×
1114
            if (str.isEmpty() == false)
×
1115
                setEnableKeySequence(stripKeySequence(QKeySequence(str)));
×
1116
        }
×
1117
        else if (root.name() == KXMLQLCVCFrameNext)
8✔
1118
        {
1119
            QString str = loadXMLSources(root, nextPageInputSourceId);
×
1120
            if (str.isEmpty() == false)
×
1121
                setNextPageKeySequence(stripKeySequence(QKeySequence(str)));
×
1122
        }
×
1123
        else if (root.name() == KXMLQLCVCFramePrevious)
8✔
1124
        {
1125
            QString str = loadXMLSources(root, previousPageInputSourceId);
×
1126
            if (str.isEmpty() == false)
×
1127
                setPreviousPageKeySequence(stripKeySequence(QKeySequence(str)));
×
1128
        }
×
1129
        else if (root.name() == KXMLQLCVCFramePagesLoop)
8✔
1130
        {
1131
            if (root.readElementText() == KXMLQLCTrue)
×
1132
                setPagesLoop(true);
×
1133
            else
1134
                setPagesLoop(false);
×
1135
        }
1136
        else if (root.name() == KXMLQLCVCFramePageShortcut)
8✔
1137
        {
1138
            VCFramePageShortcut *shortcut = new VCFramePageShortcut(0xFF, 0xFF);
×
1139
            if (shortcut->loadXML(root))
×
1140
            {
1141
                shortcut->m_id = VCFrame::shortcutsBaseInputSourceId + shortcut->m_page;
×
1142
                newShortcuts.append(shortcut);
×
1143
            }
1144
        }
1145
        else if (root.name() == KXMLQLCVCFrame)
8✔
1146
        {
1147
            /* Create a new frame into its parent */
1148
            VCFrame* frame = new VCFrame(this, m_doc, true);
1✔
1149
            if (frame->loadXML(root) == false)
1✔
1150
                delete frame;
×
1151
            else
1152
            {
1153
                addWidgetToPageMap(frame);
1✔
1154
                frame->show();
1✔
1155
            }
1156
        }
1157
        else if (root.name() == KXMLQLCVCLabel)
7✔
1158
        {
1159
            /* Create a new label into its parent */
1160
            VCLabel* label = new VCLabel(this, m_doc);
1✔
1161
            if (label->loadXML(root) == false)
1✔
1162
                delete label;
×
1163
            else
1164
            {
1165
                addWidgetToPageMap(label);
1✔
1166
                label->show();
1✔
1167
            }
1168
        }
1169
        else if (root.name() == KXMLQLCVCButton)
6✔
1170
        {
1171
            /* Create a new button into its parent */
1172
            VCButton* button = new VCButton(this, m_doc);
1✔
1173
            if (button->loadXML(root) == false)
1✔
1174
                delete button;
×
1175
            else
1176
            {
1177
                addWidgetToPageMap(button);
1✔
1178
                button->show();
1✔
1179
            }
1180
        }
1181
        else if (root.name() == KXMLQLCVCXYPad)
5✔
1182
        {
1183
            /* Create a new xy pad into its parent */
1184
            VCXYPad* xypad = new VCXYPad(this, m_doc);
1✔
1185
            if (xypad->loadXML(root) == false)
1✔
1186
                delete xypad;
×
1187
            else
1188
            {
1189
                addWidgetToPageMap(xypad);
1✔
1190
                xypad->show();
1✔
1191
            }
1192
        }
1193
        else if (root.name() == KXMLQLCVCSlider)
4✔
1194
        {
1195
            /* Create a new slider into its parent */
1196
            VCSlider* slider = new VCSlider(this, m_doc);
1✔
1197
            if (slider->loadXML(root) == false)
1✔
1198
            {
1199
                delete slider;
×
1200
            }
1201
            else
1202
            {
1203
                addWidgetToPageMap(slider);
1✔
1204
                slider->show();
1✔
1205
                // always connect a slider as if it was a submaster
1206
                // cause this signal is emitted only when a slider is
1207
                // a submaster
1208
                connect(slider, SIGNAL(submasterValueChanged(qreal)),
1✔
1209
                        this, SLOT(slotSubmasterValueChanged(qreal)));
1210
            }
1211
        }
1212
        else if (root.name() == KXMLQLCVCSoloFrame)
3✔
1213
        {
1214
            /* Create a new frame into its parent */
1215
            VCSoloFrame* soloframe = new VCSoloFrame(this, m_doc, true);
1✔
1216
            if (soloframe->loadXML(root) == false)
1✔
1217
                delete soloframe;
×
1218
            else
1219
            {
1220
                if (m_doc->mode() == Doc::Operate)
1✔
1221
                    soloframe->updateChildrenConnection(true);
×
1222
                addWidgetToPageMap(soloframe);
1✔
1223
                soloframe->show();
1✔
1224
            }
1225
        }
1226
        else if (root.name() == KXMLQLCVCCueList)
2✔
1227
        {
1228
            /* Create a new cuelist into its parent */
1229
            VCCueList* cuelist = new VCCueList(this, m_doc);
1✔
1230
            if (cuelist->loadXML(root) == false)
1✔
1231
                delete cuelist;
×
1232
            else
1233
            {
1234
                addWidgetToPageMap(cuelist);
1✔
1235
                cuelist->show();
1✔
1236
            }
1237
        }
1238
        else if (root.name() == KXMLQLCVCSpeedDial)
1✔
1239
        {
1240
            /* Create a new speed dial into its parent */
1241
            VCSpeedDial* dial = new VCSpeedDial(this, m_doc);
×
1242
            if (dial->loadXML(root) == false)
×
1243
                delete dial;
×
1244
            else
1245
            {
1246
                addWidgetToPageMap(dial);
×
1247
                dial->show();
×
1248
            }
1249
        }
1250
        else if (root.name() == KXMLQLCVCAudioTriggers)
1✔
1251
        {
1252
            VCAudioTriggers* triggers = new VCAudioTriggers(this, m_doc);
×
1253
            if (triggers->loadXML(root) == false)
×
1254
                delete triggers;
×
1255
            else
1256
            {
1257
                addWidgetToPageMap(triggers);
×
1258
                triggers->show();
×
1259
            }
1260
        }
1261
        else if (root.name() == KXMLQLCVCClock)
1✔
1262
        {
1263
            /* Create a new VCClock into its parent */
1264
            VCClock* clock = new VCClock(this, m_doc);
×
1265
            if (clock->loadXML(root) == false)
×
1266
                delete clock;
×
1267
            else
1268
            {
1269
                addWidgetToPageMap(clock);
×
1270
                clock->show();
×
1271
            }
1272
        }
1273
        else if (root.name() == KXMLQLCVCMatrix)
1✔
1274
        {
1275
            /* Create a new VCMatrix into its parent */
1276
            VCMatrix* matrix = new VCMatrix(this, m_doc);
×
1277
            if (matrix->loadXML(root) == false)
×
1278
                delete matrix;
×
1279
            else
1280
            {
1281
                addWidgetToPageMap(matrix);
×
1282
                matrix->show();
×
1283
            }
1284
        }
1285
        else
1286
        {
1287
            qWarning() << Q_FUNC_INFO << "Unknown frame tag:" << root.name().toString();
1✔
1288
            root.skipCurrentElement();
1✔
1289
        }
1290
    }
1291

1292
    if (multipageMode() == true)
3✔
1293
    {
1294
        if (newShortcuts.count() == m_totalPagesNumber)
×
1295
            setShortcuts(newShortcuts);
×
1296
        else
1297
            qWarning() << Q_FUNC_INFO << "Shortcut number does not match page number";
×
1298

1299
        // Set page again to update header
1300
        slotSetPage(m_currentPage);
×
1301
    }
1302

1303
    if (disableState == true)
3✔
1304
        setDisableState(true);
×
1305

1306
    return true;
3✔
1307
}
3✔
1308

1309
bool VCFrame::saveXML(QXmlStreamWriter *doc)
3✔
1310
{
1311
    Q_ASSERT(doc != NULL);
3✔
1312

1313
    /* VC Frame entry */
1314
    doc->writeStartElement(xmlTagName());
3✔
1315

1316
    saveXMLCommon(doc);
3✔
1317

1318
    /* Save appearance */
1319
    saveXMLAppearance(doc);
3✔
1320

1321
    if (isBottomFrame() == false)
3✔
1322
    {
1323
        /* Save widget proportions only for child frames */
1324
        if (isCollapsed())
2✔
1325
        {
1326
            resize(QSize(m_width, m_height));
×
1327
            saveXMLWindowState(doc);
×
1328
            resize(QSize(200, 40));
×
1329
        }
1330
        else
1331
            saveXMLWindowState(doc);
2✔
1332

1333
        /* Allow children */
1334
        doc->writeTextElement(KXMLQLCVCFrameAllowChildren, allowChildren() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1335

1336
        /* Allow resize */
1337
        doc->writeTextElement(KXMLQLCVCFrameAllowResize, allowResize() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1338

1339
        /* ShowHeader */
1340
        doc->writeTextElement(KXMLQLCVCFrameShowHeader, isHeaderVisible() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1341

1342
        /* ShowEnableButton */
1343
        doc->writeTextElement(KXMLQLCVCFrameShowEnableButton, isEnableButtonVisible() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1344

1345
        /* Solo frame mixing */
1346
        if (this->type() == SoloFrameWidget)
2✔
1347
        {
1348
            VCSoloFrame *solo = reinterpret_cast<VCSoloFrame*>(this);
×
1349
            if (solo->soloframeMixing())
×
1350
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCTrue);
×
1351
            else
1352
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCFalse);
×
1353

1354
            if (solo->excludeMonitoredFunctions())
×
1355
                doc->writeTextElement(KXMLQLCVCSoloFrameExclude, KXMLQLCTrue);
×
1356
        }
1357

1358
        /* Collapsed */
1359
        doc->writeTextElement(KXMLQLCVCFrameIsCollapsed, isCollapsed() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1360

1361
        /* Disabled */
1362
        doc->writeTextElement(KXMLQLCVCFrameIsDisabled, isDisabled() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1363

1364
        /* Enable control */
1365
        QString keySeq = m_enableKeySequence.toString();
2✔
1366
        QSharedPointer<QLCInputSource> enableSrc = inputSource(enableInputSourceId);
2✔
1367

1368
        if (keySeq.isEmpty() == false || (!enableSrc.isNull() && enableSrc->isValid()))
2✔
1369
        {
1370
            doc->writeStartElement(KXMLQLCVCFrameEnableSource);
×
1371
            if (keySeq.isEmpty() == false)
×
1372
                doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1373
            saveXMLInput(doc, enableSrc);
×
1374
            doc->writeEndElement();
×
1375
        }
1376

1377
        /* Multipage mode */
1378
        if (multipageMode() == true)
2✔
1379
        {
1380
            doc->writeStartElement(KXMLQLCVCFrameMultipage);
×
1381
            doc->writeAttribute(KXMLQLCVCFramePagesNumber, QString::number(totalPagesNumber()));
×
1382
            doc->writeAttribute(KXMLQLCVCFrameCurrentPage, QString::number(currentPage()));
×
1383
            doc->writeEndElement();
×
1384

1385
            /* Next page */
1386
            keySeq = m_nextPageKeySequence.toString();
×
1387
            QSharedPointer<QLCInputSource> nextSrc = inputSource(nextPageInputSourceId);
×
1388

1389
            if (keySeq.isEmpty() == false || (!nextSrc.isNull() && nextSrc->isValid()))
×
1390
            {
1391
                doc->writeStartElement(KXMLQLCVCFrameNext);
×
1392
                if (keySeq.isEmpty() == false)
×
1393
                    doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1394
                saveXMLInput(doc, nextSrc);
×
1395
                doc->writeEndElement();
×
1396
            }
1397

1398
            /* Previous page */
1399
            keySeq = m_previousPageKeySequence.toString();
×
1400
            QSharedPointer<QLCInputSource> prevSrc = inputSource(previousPageInputSourceId);
×
1401

1402
            if (keySeq.isEmpty() == false || (!prevSrc.isNull() && prevSrc->isValid()))
×
1403
            {
1404
                doc->writeStartElement(KXMLQLCVCFramePrevious);
×
1405
                if (keySeq.isEmpty() == false)
×
1406
                    doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1407
                saveXMLInput(doc, prevSrc);
×
1408
                doc->writeEndElement();
×
1409
            }
1410

1411
            /* Page shortcuts */
1412
            foreach (VCFramePageShortcut *shortcut, shortcuts())
×
1413
                shortcut->saveXML(doc);
×
1414

1415
            /* Pages Loop */
1416
            doc->writeTextElement(KXMLQLCVCFramePagesLoop, m_pagesLoop ? KXMLQLCTrue : KXMLQLCFalse);
×
1417
        }
×
1418
    }
2✔
1419

1420
    /* Save children */
1421
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
3✔
1422
    while (it.hasNext() == true)
6✔
1423
    {
1424
        VCWidget* widget = it.next();
3✔
1425

1426
        /* findChildren() is recursive, so the list contains all
1427
           possible child widgets below this frame. Each frame must
1428
           save only its direct children to preserve hierarchy, so
1429
           save only such widgets that have this widget as their
1430
           direct parent. */
1431
        if (widget->parentWidget() == this)
3✔
1432
            widget->saveXML(doc);
2✔
1433
    }
1434

1435
    /* End the <Frame> tag */
1436
    doc->writeEndElement();
3✔
1437

1438
    return true;
3✔
1439
}
3✔
1440

1441
void VCFrame::postLoad()
3✔
1442
{
1443
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
3✔
1444
    while (it.hasNext() == true)
10✔
1445
    {
1446
        VCWidget* widget = it.next();
7✔
1447

1448
        /* findChildren() is recursive, so the list contains all
1449
           possible child widgets below this frame. Each frame must
1450
           save only its direct children to preserve hierarchy, so
1451
           save only such widgets that have this widget as their
1452
           direct parent. */
1453
        if (widget->parentWidget() == this)
7✔
1454
            widget->postLoad();
7✔
1455
    }
1456
}
3✔
1457

1458
QString VCFrame::xmlTagName() const
6✔
1459
{
1460
    return KXMLQLCVCFrame;
6✔
1461
}
1462

1463
/*****************************************************************************
1464
 * Custom menu
1465
 *****************************************************************************/
1466

1467
QMenu* VCFrame::customMenu(QMenu* parentMenu) const
8✔
1468
{
1469
    QMenu* menu = NULL;
8✔
1470
    VirtualConsole* vc = VirtualConsole::instance();
8✔
1471

1472
    if (allowChildren() == true && vc != NULL)
8✔
1473
    {
1474
        /* Basically, just returning VC::addMenu() would suffice here, but
1475
           since the returned menu will be deleted when the current widget
1476
           changes, we have to copy the menu's contents into a new menu. */
1477
        menu = new QMenu(parentMenu);
8✔
1478
        menu->setTitle(tr("Add"));
8✔
1479
        QListIterator <QAction*> it(vc->addMenu()->actions());
8✔
1480
        while (it.hasNext() == true)
144✔
1481
            menu->addAction(it.next());
136✔
1482
    }
8✔
1483

1484
    return menu;
8✔
1485
}
1486

1487
/*****************************************************************************
1488
 * Event handlers
1489
 *****************************************************************************/
1490

1491
void VCFrame::handleWidgetSelection(QMouseEvent* e)
4✔
1492
{
1493
    /* No point coming here if there is no VC */
1494
    VirtualConsole* vc = VirtualConsole::instance();
4✔
1495
    if (vc == NULL)
4✔
1496
        return;
×
1497

1498
    /* Don't allow selection of the bottom frame. Selecting it will always
1499
       actually clear the current selection. */
1500
    if (isBottomFrame() == false)
4✔
1501
        VCWidget::handleWidgetSelection(e);
1✔
1502
    else
1503
        vc->clearWidgetSelection();
3✔
1504
}
1505

1506
void VCFrame::mouseMoveEvent(QMouseEvent* e)
2✔
1507
{
1508
    if (isBottomFrame() == false)
2✔
1509
        VCWidget::mouseMoveEvent(e);
1✔
1510
    else
1511
        QWidget::mouseMoveEvent(e);
1✔
1512

1513
    if (isCollapsed() == false)
2✔
1514
    {
1515
        m_width = this->width();
2✔
1516
        m_height = this->height();
2✔
1517
    }
1518
}
2✔
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