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

mcallegari / qlcplus / 19144422256

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

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 hits per line

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

45.43
/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 (root.name() == KXMLQLCVCSoloFrameMixing && this->type() == SoloFrameWidget)
16✔
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 (root.name() == KXMLQLCVCFrameMultipage)
8✔
1092
        {
1093
            setMultipageMode(true);
×
1094
            QXmlStreamAttributes attrs = root.attributes();
×
1095
            if (attrs.hasAttribute(KXMLQLCVCFramePagesNumber))
×
1096
                setTotalPagesNumber(attrs.value(KXMLQLCVCFramePagesNumber).toString().toInt());
×
1097

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

1283
    if (multipageMode() == true)
3✔
1284
    {
1285
        if (newShortcuts.count() == m_totalPagesNumber)
×
1286
            setShortcuts(newShortcuts);
×
1287
        else
1288
            qWarning() << Q_FUNC_INFO << "Shortcut number does not match page number";
×
1289

1290
        // Set page again to update header
1291
        slotSetPage(m_currentPage);
×
1292
    }
1293

1294
    if (disableState == true)
3✔
1295
        setDisableState(true);
×
1296

1297
    return true;
3✔
1298
}
3✔
1299

1300
bool VCFrame::saveXML(QXmlStreamWriter *doc)
3✔
1301
{
1302
    Q_ASSERT(doc != NULL);
3✔
1303

1304
    /* VC Frame entry */
1305
    doc->writeStartElement(xmlTagName());
3✔
1306

1307
    saveXMLCommon(doc);
3✔
1308

1309
    /* Save appearance */
1310
    saveXMLAppearance(doc);
3✔
1311

1312
    if (isBottomFrame() == false)
3✔
1313
    {
1314
        /* Save widget proportions only for child frames */
1315
        if (isCollapsed())
2✔
1316
        {
1317
            resize(QSize(m_width, m_height));
×
1318
            saveXMLWindowState(doc);
×
1319
            resize(QSize(200, 40));
×
1320
        }
1321
        else
1322
            saveXMLWindowState(doc);
2✔
1323

1324
        /* Allow children */
1325
        doc->writeTextElement(KXMLQLCVCFrameAllowChildren, allowChildren() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1326

1327
        /* Allow resize */
1328
        doc->writeTextElement(KXMLQLCVCFrameAllowResize, allowResize() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1329

1330
        /* ShowHeader */
1331
        doc->writeTextElement(KXMLQLCVCFrameShowHeader, isHeaderVisible() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1332

1333
        /* ShowEnableButton */
1334
        doc->writeTextElement(KXMLQLCVCFrameShowEnableButton, isEnableButtonVisible() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1335

1336
        /* Solo frame mixing */
1337
        if (this->type() == SoloFrameWidget)
2✔
1338
        {
1339
            if (reinterpret_cast<VCSoloFrame*>(this)->soloframeMixing())
×
1340
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCTrue);
×
1341
            else
1342
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCFalse);
×
1343
        }
1344

1345
        /* Collapsed */
1346
        doc->writeTextElement(KXMLQLCVCFrameIsCollapsed, isCollapsed() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1347

1348
        /* Disabled */
1349
        doc->writeTextElement(KXMLQLCVCFrameIsDisabled, isDisabled() ? KXMLQLCTrue : KXMLQLCFalse);
6✔
1350

1351
        /* Enable control */
1352
        QString keySeq = m_enableKeySequence.toString();
2✔
1353
        QSharedPointer<QLCInputSource> enableSrc = inputSource(enableInputSourceId);
2✔
1354

1355
        if (keySeq.isEmpty() == false || (!enableSrc.isNull() && enableSrc->isValid()))
2✔
1356
        {
1357
            doc->writeStartElement(KXMLQLCVCFrameEnableSource);
×
1358
            if (keySeq.isEmpty() == false)
×
1359
                doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1360
            saveXMLInput(doc, enableSrc);
×
1361
            doc->writeEndElement();
×
1362
        }
1363

1364
        /* Multipage mode */
1365
        if (multipageMode() == true)
2✔
1366
        {
1367
            doc->writeStartElement(KXMLQLCVCFrameMultipage);
×
1368
            doc->writeAttribute(KXMLQLCVCFramePagesNumber, QString::number(totalPagesNumber()));
×
1369
            doc->writeAttribute(KXMLQLCVCFrameCurrentPage, QString::number(currentPage()));
×
1370
            doc->writeEndElement();
×
1371

1372
            /* Next page */
1373
            keySeq = m_nextPageKeySequence.toString();
×
1374
            QSharedPointer<QLCInputSource> nextSrc = inputSource(nextPageInputSourceId);
×
1375

1376
            if (keySeq.isEmpty() == false || (!nextSrc.isNull() && nextSrc->isValid()))
×
1377
            {
1378
                doc->writeStartElement(KXMLQLCVCFrameNext);
×
1379
                if (keySeq.isEmpty() == false)
×
1380
                    doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1381
                saveXMLInput(doc, nextSrc);
×
1382
                doc->writeEndElement();
×
1383
            }
1384

1385
            /* Previous page */
1386
            keySeq = m_previousPageKeySequence.toString();
×
1387
            QSharedPointer<QLCInputSource> prevSrc = inputSource(previousPageInputSourceId);
×
1388

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

1398
            /* Page shortcuts */
1399
            foreach (VCFramePageShortcut *shortcut, shortcuts())
×
1400
                shortcut->saveXML(doc);
×
1401

1402
            /* Pages Loop */
1403
            doc->writeTextElement(KXMLQLCVCFramePagesLoop, m_pagesLoop ? KXMLQLCTrue : KXMLQLCFalse);
×
1404
        }
×
1405
    }
2✔
1406

1407
    /* Save children */
1408
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
3✔
1409
    while (it.hasNext() == true)
6✔
1410
    {
1411
        VCWidget* widget = it.next();
3✔
1412

1413
        /* findChildren() is recursive, so the list contains all
1414
           possible child widgets below this frame. Each frame must
1415
           save only its direct children to preserve hierarchy, so
1416
           save only such widgets that have this widget as their
1417
           direct parent. */
1418
        if (widget->parentWidget() == this)
3✔
1419
            widget->saveXML(doc);
2✔
1420
    }
1421

1422
    /* End the <Frame> tag */
1423
    doc->writeEndElement();
3✔
1424

1425
    return true;
3✔
1426
}
3✔
1427

1428
void VCFrame::postLoad()
3✔
1429
{
1430
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
3✔
1431
    while (it.hasNext() == true)
10✔
1432
    {
1433
        VCWidget* widget = it.next();
7✔
1434

1435
        /* findChildren() is recursive, so the list contains all
1436
           possible child widgets below this frame. Each frame must
1437
           save only its direct children to preserve hierarchy, so
1438
           save only such widgets that have this widget as their
1439
           direct parent. */
1440
        if (widget->parentWidget() == this)
7✔
1441
            widget->postLoad();
7✔
1442
    }
1443
}
3✔
1444

1445
QString VCFrame::xmlTagName() const
6✔
1446
{
1447
    return KXMLQLCVCFrame;
6✔
1448
}
1449

1450
/*****************************************************************************
1451
 * Custom menu
1452
 *****************************************************************************/
1453

1454
QMenu* VCFrame::customMenu(QMenu* parentMenu)
8✔
1455
{
1456
    QMenu* menu = NULL;
8✔
1457
    VirtualConsole* vc = VirtualConsole::instance();
8✔
1458

1459
    if (allowChildren() == true && vc != NULL)
8✔
1460
    {
1461
        /* Basically, just returning VC::addMenu() would suffice here, but
1462
           since the returned menu will be deleted when the current widget
1463
           changes, we have to copy the menu's contents into a new menu. */
1464
        menu = new QMenu(parentMenu);
8✔
1465
        menu->setTitle(tr("Add"));
8✔
1466
        QListIterator <QAction*> it(vc->addMenu()->actions());
8✔
1467
        while (it.hasNext() == true)
144✔
1468
            menu->addAction(it.next());
136✔
1469
    }
8✔
1470

1471
    return menu;
8✔
1472
}
1473

1474
/*****************************************************************************
1475
 * Event handlers
1476
 *****************************************************************************/
1477

1478
void VCFrame::handleWidgetSelection(QMouseEvent* e)
4✔
1479
{
1480
    /* No point coming here if there is no VC */
1481
    VirtualConsole* vc = VirtualConsole::instance();
4✔
1482
    if (vc == NULL)
4✔
1483
        return;
×
1484

1485
    /* Don't allow selection of the bottom frame. Selecting it will always
1486
       actually clear the current selection. */
1487
    if (isBottomFrame() == false)
4✔
1488
        VCWidget::handleWidgetSelection(e);
1✔
1489
    else
1490
        vc->clearWidgetSelection();
3✔
1491
}
1492

1493
void VCFrame::mouseMoveEvent(QMouseEvent* e)
2✔
1494
{
1495
    if (isBottomFrame() == false)
2✔
1496
        VCWidget::mouseMoveEvent(e);
1✔
1497
    else
1498
        QWidget::mouseMoveEvent(e);
1✔
1499

1500
    if (isCollapsed() == false)
2✔
1501
    {
1502
        m_width = this->width();
2✔
1503
        m_height = this->height();
2✔
1504
    }
1505
}
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