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

mcallegari / qlcplus / 19409821768

16 Nov 2025 06:06PM UTC coverage: 34.233% (-0.01%) from 34.243%
19409821768

push

github

mcallegari
vc/soloframe: add an option to exclude functions monitored by buttons to be stopped

3 of 38 new or added lines in 9 files covered. (7.89%)

2 existing lines in 2 files now uncovered.

17724 of 51774 relevant lines covered (34.23%)

19630.45 hits per line

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

45.16
/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()
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()
2✔
490
{
491
    return m_totalPagesNumber;
2✔
492
}
493

494
int VCFrame::currentPage()
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();
×
663
        if (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->parent() == this && child->type() == SliderWidget)
2✔
675
        {
676
            VCSlider* slider = reinterpret_cast<VCSlider*>(child);
×
677
            if (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();
×
694
        if (child->parent() == this)
×
695
            child->adjustIntensity(val);
×
696
    }
697
}
×
698

699
/*****************************************************************************
700
 * Key Sequences
701
 *****************************************************************************/
702

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

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

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

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

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

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

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

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

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

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

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

794
/*****************************************************************************
795
 * External input
796
 *****************************************************************************/
797

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

803
    quint32 pagedCh = (page() << 16) | channel;
×
804

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

825
/*****************************************************************************
826
 * Clipboard
827
 *****************************************************************************/
828

829
VCWidget* VCFrame::createCopy(VCWidget* parent)
1✔
830
{
831
    Q_ASSERT(parent != NULL);
1✔
832

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

840
    return frame;
1✔
841
}
842

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

849
    setHeaderVisible(frame->m_showHeader);
1✔
850
    setEnableButtonVisible(frame->m_showEnableButton);
1✔
851

852
    setMultipageMode(frame->m_multiPageMode);
1✔
853
    setTotalPagesNumber(frame->m_totalPagesNumber);
1✔
854

855
    setPagesLoop(frame->m_pagesLoop);
1✔
856

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

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

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

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

881
        if (childCopy != NULL)
1✔
882
        {
883
            addWidgetToPageMap(childCopy);
1✔
884

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

897
    if (m_multiPageMode)
1✔
898
        slotSetPage(frame->m_currentPage);
×
899

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

904
/*****************************************************************************
905
 * Properties
906
 *****************************************************************************/
907

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

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

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

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

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

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

998
/*****************************************************************************
999
 * Load & Save
1000
 *****************************************************************************/
1001

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

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

1012
    /* Widget commons */
1013
    loadXMLCommon(root);
3✔
1014

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

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

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

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

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

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

1301
    if (disableState == true)
3✔
1302
        setDisableState(true);
×
1303

1304
    return true;
3✔
1305
}
3✔
1306

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

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

1314
    saveXMLCommon(doc);
3✔
1315

1316
    /* Save appearance */
1317
    saveXMLAppearance(doc);
3✔
1318

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

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

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

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

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

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

NEW
1352
            if (solo->excludeMonitoredFunctions())
×
NEW
1353
                doc->writeTextElement(KXMLQLCVCSoloFrameExclude, KXMLQLCTrue);
×
1354
        }
1355

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1436
    return true;
3✔
1437
}
3✔
1438

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

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

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

1461
/*****************************************************************************
1462
 * Custom menu
1463
 *****************************************************************************/
1464

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

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

1482
    return menu;
8✔
1483
}
1484

1485
/*****************************************************************************
1486
 * Event handlers
1487
 *****************************************************************************/
1488

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

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

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

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