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

mcallegari / qlcplus / 13633248611

03 Mar 2025 02:31PM UTC coverage: 31.871% (+0.4%) from 31.5%
13633248611

push

github

web-flow
actions: add chrpath to profile

14689 of 46089 relevant lines covered (31.87%)

26426.11 hits per line

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

45.6
/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);
190✔
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);
26✔
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);
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;
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;
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;
498
    return m_currentPage;
×
499
}
500

501
void VCFrame::updatePageCombo()
2✔
502
{
503
    if (m_pageCombo == NULL || shortcuts().isEmpty())
2✔
504
        return;
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
    }
536
    updatePageCombo();
2✔
537
}
2✔
538

539
void VCFrame::resetShortcuts()
2✔
540
{
541
    int count = m_pageShortcuts.count();
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
        slotSetPage(m_totalPagesNumber - 1);
×
579
    else
580
        slotSetPage(m_currentPage - 1);
×
581
    sendFeedback(m_currentPage, previousPageInputSourceId);
×
582
}
×
583

584
void VCFrame::slotNextPage()
×
585
{
586
    if (m_pagesLoop && m_currentPage == m_totalPagesNumber - 1)
×
587
        slotSetPage(0);
×
588
    else
589
        slotSetPage(m_currentPage + 1);
×
590

591
    sendFeedback(m_currentPage, nextPageInputSourceId);
×
592
}
×
593

594
void VCFrame::slotSetPage(int pageNum)
17✔
595
{
596
    if (m_pageCombo)
17✔
597
    {
598
        if (pageNum >= 0 && pageNum < m_totalPagesNumber)
×
599
            m_currentPage = pageNum;
×
600

601
        m_pageCombo->blockSignals(true);
×
602
        m_pageCombo->setCurrentIndex(m_currentPage);
×
603
        m_pageCombo->blockSignals(false);
×
604
        setCaption(caption());
×
605

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

630
void VCFrame::slotModeChanged(Doc::Mode mode)
21✔
631
{
632
    if (mode == Doc::Operate)
21✔
633
    {
634
        if (isDisabled())
16✔
635
            slotEnableButtonClicked(false);
×
636
        slotSetPage(currentPage());
16✔
637
        updateSubmasterValue();
16✔
638
        updateFeedback();
16✔
639
    }
640

641
    VCWidget::slotModeChanged(mode);
21✔
642
}
21✔
643

644
/*********************************************************************
645
 * Submasters
646
 *********************************************************************/
647

648
void VCFrame::slotSubmasterValueChanged(qreal value)
×
649
{
650
    qDebug() << Q_FUNC_INFO << "val:" << value;
651
    VCSlider *submaster = qobject_cast<VCSlider *>(sender());
×
652
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
653
    while (it.hasNext() == true)
×
654
    {
655
        VCWidget *child = it.next();
×
656
        if (child->parent() == this && child != submaster)
×
657
            child->adjustIntensity(value);
×
658
    }
659
}
×
660

661
void VCFrame::updateSubmasterValue()
16✔
662
{
663
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
32✔
664
    while (it.hasNext() == true)
34✔
665
    {
666
        VCWidget* child = it.next();
2✔
667
        if (child->parent() == this && child->type() == SliderWidget)
2✔
668
        {
669
            VCSlider* slider = reinterpret_cast<VCSlider*>(child);
670
            if (slider->sliderMode() == VCSlider::Submaster)
×
671
                slider->emitSubmasterValue();
×
672
        }
673
    }
674
}
16✔
675

676
void VCFrame::adjustIntensity(qreal val)
×
677
{
678
    VCWidget::adjustIntensity(val);
×
679

680
    if (isDisabled())
×
681
        return;
×
682

683
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
×
684
    while (it.hasNext() == true)
×
685
    {
686
        VCWidget *child = it.next();
×
687
        if (child->parent() == this)
×
688
            child->adjustIntensity(val);
×
689
    }
690
}
691

692
/*****************************************************************************
693
 * Key Sequences
694
 *****************************************************************************/
695

696
void VCFrame::setEnableKeySequence(const QKeySequence &keySequence)
2✔
697
{
698
    m_enableKeySequence = QKeySequence(keySequence);
2✔
699
}
2✔
700

701
QKeySequence VCFrame::enableKeySequence() const
1✔
702
{
703
    return m_enableKeySequence;
1✔
704
}
705

706
void VCFrame::setNextPageKeySequence(const QKeySequence& keySequence)
2✔
707
{
708
    m_nextPageKeySequence = QKeySequence(keySequence);
2✔
709
}
2✔
710

711
QKeySequence VCFrame::nextPageKeySequence() const
1✔
712
{
713
    return m_nextPageKeySequence;
1✔
714
}
715

716
void VCFrame::setPreviousPageKeySequence(const QKeySequence& keySequence)
2✔
717
{
718
    m_previousPageKeySequence = QKeySequence(keySequence);
2✔
719
}
2✔
720

721
QKeySequence VCFrame::previousPageKeySequence() const
1✔
722
{
723
    return m_previousPageKeySequence;
1✔
724
}
725

726
void VCFrame::slotKeyPressed(const QKeySequence& keySequence)
×
727
{
728
    if (isEnabled() == false)
×
729
        return;
730

731
    if (m_enableKeySequence == keySequence)
×
732
        setDisableState(!isDisabled());
×
733
    else if (m_previousPageKeySequence == keySequence)
×
734
        slotPreviousPage();
×
735
    else if (m_nextPageKeySequence == keySequence)
×
736
        slotNextPage();
×
737
    else
738
    {
739
        foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
×
740
        {
741
            if (shortcut->m_keySequence == keySequence)
×
742
                slotSetPage(shortcut->m_page);
×
743
        }
744
    }
745
}
746

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

766
    foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
66✔
767
    {
768
        QSharedPointer<QLCInputSource> src = shortcut->m_inputSource;
769
        if (!src.isNull() && src->isValid() == true)
×
770
        {
771
            if (m_currentPage == shortcut->m_page)
×
772
                sendFeedback(src->feedbackValue(QLCInputFeedback::UpperValue), src);
×
773
            else
774
                sendFeedback(src->feedbackValue(QLCInputFeedback::LowerValue), src);
×
775
        }
776
    }
777

778
    QListIterator <VCWidget*> it(this->findChildren<VCWidget*>());
66✔
779
    while (it.hasNext() == true)
70✔
780
    {
781
        VCWidget* child = it.next();
4✔
782
        if (child->parent() == this)
4✔
783
            child->updateFeedback();
4✔
784
    }
785
}
33✔
786

787
/*****************************************************************************
788
 * External input
789
 *****************************************************************************/
790

791
void VCFrame::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
×
792
{
793
    if (isEnabled() == false)
×
794
        return;
795

796
    quint32 pagedCh = (page() << 16) | channel;
×
797

798
    if (checkInputSource(universe, pagedCh, value, sender(), enableInputSourceId) && value)
×
799
        setDisableState(!isDisabled());
×
800
    else if (checkInputSource(universe, pagedCh, value, sender(), previousPageInputSourceId) && value)
×
801
        slotPreviousPage();
×
802
    else if (checkInputSource(universe, pagedCh, value, sender(), nextPageInputSourceId) && value)
×
803
        slotNextPage();
×
804
    else
805
    {
806
        foreach (VCFramePageShortcut* shortcut, m_pageShortcuts)
×
807
        {
808
            if (shortcut->m_inputSource != NULL &&
×
809
                    shortcut->m_inputSource->universe() == universe &&
×
810
                    shortcut->m_inputSource->channel() == pagedCh)
×
811
            {
812
                slotSetPage(shortcut->m_page);
×
813
            }
814
        }
815
    }
816
}
817

818
/*****************************************************************************
819
 * Clipboard
820
 *****************************************************************************/
821

822
VCWidget* VCFrame::createCopy(VCWidget* parent)
1✔
823
{
824
    Q_ASSERT(parent != NULL);
825

826
    VCFrame* frame = new VCFrame(parent, m_doc, true);
1✔
827
    if (frame->copyFrom(this) == false)
1✔
828
    {
829
        delete frame;
×
830
        frame = NULL;
831
    }
832

833
    return frame;
1✔
834
}
835

836
bool VCFrame::copyFrom(const VCWidget* widget)
2✔
837
{
838
    const VCFrame* frame = qobject_cast<const VCFrame*> (widget);
839
    if (frame == NULL)
2✔
840
        return false;
841

842
    setHeaderVisible(frame->m_showHeader);
1✔
843
    setEnableButtonVisible(frame->m_showEnableButton);
1✔
844

845
    setMultipageMode(frame->m_multiPageMode);
1✔
846
    setTotalPagesNumber(frame->m_totalPagesNumber);
1✔
847

848
    setPagesLoop(frame->m_pagesLoop);
1✔
849

850
    setEnableKeySequence(frame->m_enableKeySequence);
1✔
851
    setNextPageKeySequence(frame->m_nextPageKeySequence);
1✔
852
    setPreviousPageKeySequence(frame->m_previousPageKeySequence);
1✔
853
    setShortcuts(frame->shortcuts());
1✔
854

855
    QListIterator <VCWidget*> it(widget->findChildren<VCWidget*>());
2✔
856
    while (it.hasNext() == true)
3✔
857
    {
858
        VCWidget* child = it.next();
1✔
859
        VCWidget* childCopy = NULL;
860

861
        /* findChildren() is recursive, so the list contains all
862
           possible child widgets below this frame. Each frame must
863
           save only its direct children to preserve hierarchy, so
864
           save only such widgets that have this widget as their
865
           direct parent. */
866
        if (child->parentWidget() == widget)
1✔
867
        {
868
            childCopy = child->createCopy(this);
1✔
869
            VirtualConsole::instance()->addWidgetInMap(childCopy);
1✔
870

871
            qDebug() << "Child copy in parent:" << childCopy->caption() << ", page:" << childCopy->page();
872
        }
873

874
        if (childCopy != NULL)
1✔
875
        {
876
            addWidgetToPageMap(childCopy);
1✔
877

878
            if (childCopy->type() == VCWidget::SliderWidget)
1✔
879
            {
880
                VCSlider *slider = qobject_cast<VCSlider*>(childCopy);
881
                // always connect a slider as it it was a submaster
882
                // cause this signal is emitted only when a slider is
883
                // a submaster
884
                connect(slider, SIGNAL(submasterValueChanged(qreal)),
×
885
                        this, SLOT(slotSubmasterValueChanged(qreal)));
886
            }
887
        }
888
    }
889

890
    if (m_multiPageMode)
1✔
891
        slotSetPage(frame->m_currentPage);
×
892

893
    /* Copy common stuff */
894
    return VCWidget::copyFrom(widget);
1✔
895
}
896

897
/*****************************************************************************
898
 * Properties
899
 *****************************************************************************/
900

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

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

944
                    addWidgetToPageMap(newWidget);
×
945
                }
946
            }
947
        }
948
        slotSetPage(0);
×
949
    }
950
    else if (multipageMode() == false)
×
951
    {
952
        setTotalPagesNumber(1);
×
953
        resize(QSize(this->width(), this->height()));
×
954

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

979
void VCFrame::editProperties()
×
980
{
981
    if (isBottomFrame() == true)
×
982
        return;
×
983

984
    VCFrameProperties prop(NULL, this, m_doc);
×
985
    if (prop.exec() == QDialog::Accepted)
×
986
    {
987
        applyProperties(prop);
×
988
    }
989
}
×
990

991
/*****************************************************************************
992
 * Load & Save
993
 *****************************************************************************/
994

995
bool VCFrame::loadXML(QXmlStreamReader &root)
4✔
996
{
997
    bool disableState = false;
998

999
    if (root.name() != xmlTagName())
8✔
1000
    {
1001
        qWarning() << Q_FUNC_INFO << "Frame node not found";
1✔
1002
        return false;
1✔
1003
    }
1004

1005
    /* Widget commons */
1006
    loadXMLCommon(root);
3✔
1007

1008
    // Sorted list for new shortcuts
1009
    QList<VCFramePageShortcut *> newShortcuts;
1010

1011
    /* Children */
1012
    while (root.readNextStartElement())
14✔
1013
    {
1014
        /*
1015
        qDebug() << "VC Frame <" << caption() << "> tag:" << root.name();
1016
        if (root.attributes().hasAttribute("Caption"))
1017
            qDebug() << "Widget caption:" << root.attributes().value("Caption").toString();
1018
        */
1019

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

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

1276
    if (multipageMode() == true)
3✔
1277
    {
1278
        if (newShortcuts.count() == m_totalPagesNumber)
×
1279
            setShortcuts(newShortcuts);
×
1280
        else
1281
            qWarning() << Q_FUNC_INFO << "Shortcut number does not match page number";
×
1282

1283
        // Set page again to update header
1284
        slotSetPage(m_currentPage);
×
1285
    }
1286

1287
    if (disableState == true)
3✔
1288
        setDisableState(true);
×
1289

1290
    return true;
1291
}
3✔
1292

1293
bool VCFrame::saveXML(QXmlStreamWriter *doc)
3✔
1294
{
1295
    Q_ASSERT(doc != NULL);
1296

1297
    /* VC Frame entry */
1298
    doc->writeStartElement(xmlTagName());
3✔
1299

1300
    saveXMLCommon(doc);
3✔
1301

1302
    /* Save appearance */
1303
    saveXMLAppearance(doc);
3✔
1304

1305
    if (isBottomFrame() == false)
3✔
1306
    {
1307
        /* Save widget proportions only for child frames */
1308
        if (isCollapsed())
2✔
1309
        {
1310
            resize(QSize(m_width, m_height));
×
1311
            saveXMLWindowState(doc);
×
1312
            resize(QSize(200, 40));
×
1313
        }
1314
        else
1315
            saveXMLWindowState(doc);
2✔
1316

1317
        /* Allow children */
1318
        doc->writeTextElement(KXMLQLCVCFrameAllowChildren, allowChildren() ? KXMLQLCTrue : KXMLQLCFalse);
3✔
1319

1320
        /* Allow resize */
1321
        doc->writeTextElement(KXMLQLCVCFrameAllowResize, allowResize() ? KXMLQLCTrue : KXMLQLCFalse);
3✔
1322

1323
        /* ShowHeader */
1324
        doc->writeTextElement(KXMLQLCVCFrameShowHeader, isHeaderVisible() ? KXMLQLCTrue : KXMLQLCFalse);
2✔
1325

1326
        /* ShowEnableButton */
1327
        doc->writeTextElement(KXMLQLCVCFrameShowEnableButton, isEnableButtonVisible() ? KXMLQLCTrue : KXMLQLCFalse);
2✔
1328

1329
        /* Solo frame mixing */
1330
        if (this->type() == SoloFrameWidget)
2✔
1331
        {
1332
            if (reinterpret_cast<VCSoloFrame*>(this)->soloframeMixing())
×
1333
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCTrue);
×
1334
            else
1335
                doc->writeTextElement(KXMLQLCVCSoloFrameMixing, KXMLQLCFalse);
×
1336
        }
1337

1338
        /* Collapsed */
1339
        doc->writeTextElement(KXMLQLCVCFrameIsCollapsed, isCollapsed() ? KXMLQLCTrue : KXMLQLCFalse);
4✔
1340

1341
        /* Disabled */
1342
        doc->writeTextElement(KXMLQLCVCFrameIsDisabled, isDisabled() ? KXMLQLCTrue : KXMLQLCFalse);
4✔
1343

1344
        /* Enable control */
1345
        QString keySeq = m_enableKeySequence.toString();
2✔
1346
        QSharedPointer<QLCInputSource> enableSrc = inputSource(enableInputSourceId);
2✔
1347

1348
        if (keySeq.isEmpty() == false || (!enableSrc.isNull() && enableSrc->isValid()))
2✔
1349
        {
1350
            doc->writeStartElement(KXMLQLCVCFrameEnableSource);
×
1351
            if (keySeq.isEmpty() == false)
×
1352
                doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1353
            saveXMLInput(doc, enableSrc);
×
1354
            doc->writeEndElement();
×
1355
        }
1356

1357
        /* Multipage mode */
1358
        if (multipageMode() == true)
2✔
1359
        {
1360
            doc->writeStartElement(KXMLQLCVCFrameMultipage);
×
1361
            doc->writeAttribute(KXMLQLCVCFramePagesNumber, QString::number(totalPagesNumber()));
×
1362
            doc->writeAttribute(KXMLQLCVCFrameCurrentPage, QString::number(currentPage()));
×
1363
            doc->writeEndElement();
×
1364

1365
            /* Next page */
1366
            keySeq = m_nextPageKeySequence.toString();
×
1367
            QSharedPointer<QLCInputSource> nextSrc = inputSource(nextPageInputSourceId);
×
1368

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

1378
            /* Previous page */
1379
            keySeq = m_previousPageKeySequence.toString();
×
1380
            QSharedPointer<QLCInputSource> prevSrc = inputSource(previousPageInputSourceId);
×
1381

1382
            if (keySeq.isEmpty() == false || (!prevSrc.isNull() && prevSrc->isValid()))
×
1383
            {
1384
                doc->writeStartElement(KXMLQLCVCFramePrevious);
×
1385
                if (keySeq.isEmpty() == false)
×
1386
                    doc->writeTextElement(KXMLQLCVCWidgetKey, keySeq);
×
1387
                saveXMLInput(doc, prevSrc);
×
1388
                doc->writeEndElement();
×
1389
            }
1390

1391
            /* Page shortcuts */
1392
            foreach (VCFramePageShortcut *shortcut, shortcuts())
×
1393
                shortcut->saveXML(doc);
×
1394

1395
            /* Pages Loop */
1396
            doc->writeTextElement(KXMLQLCVCFramePagesLoop, m_pagesLoop ? KXMLQLCTrue : KXMLQLCFalse);
×
1397
        }
1398
    }
2✔
1399

1400
    /* Save children */
1401
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
6✔
1402
    while (it.hasNext() == true)
9✔
1403
    {
1404
        VCWidget* widget = it.next();
3✔
1405

1406
        /* findChildren() is recursive, so the list contains all
1407
           possible child widgets below this frame. Each frame must
1408
           save only its direct children to preserve hierarchy, so
1409
           save only such widgets that have this widget as their
1410
           direct parent. */
1411
        if (widget->parentWidget() == this)
3✔
1412
            widget->saveXML(doc);
2✔
1413
    }
1414

1415
    /* End the <Frame> tag */
1416
    doc->writeEndElement();
3✔
1417

1418
    return true;
3✔
1419
}
1420

1421
void VCFrame::postLoad()
3✔
1422
{
1423
    QListIterator <VCWidget*> it(findChildren<VCWidget*>());
6✔
1424
    while (it.hasNext() == true)
13✔
1425
    {
1426
        VCWidget* widget = it.next();
7✔
1427

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

1438
QString VCFrame::xmlTagName() const
6✔
1439
{
1440
    return KXMLQLCVCFrame;
6✔
1441
}
1442

1443
/*****************************************************************************
1444
 * Custom menu
1445
 *****************************************************************************/
1446

1447
QMenu* VCFrame::customMenu(QMenu* parentMenu)
8✔
1448
{
1449
    QMenu* menu = NULL;
1450
    VirtualConsole* vc = VirtualConsole::instance();
8✔
1451

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

1464
    return menu;
8✔
1465
}
1466

1467
/*****************************************************************************
1468
 * Event handlers
1469
 *****************************************************************************/
1470

1471
void VCFrame::handleWidgetSelection(QMouseEvent* e)
4✔
1472
{
1473
    /* No point coming here if there is no VC */
1474
    VirtualConsole* vc = VirtualConsole::instance();
4✔
1475
    if (vc == NULL)
4✔
1476
        return;
1477

1478
    /* Don't allow selection of the bottom frame. Selecting it will always
1479
       actually clear the current selection. */
1480
    if (isBottomFrame() == false)
4✔
1481
        VCWidget::handleWidgetSelection(e);
1✔
1482
    else
1483
        vc->clearWidgetSelection();
3✔
1484
}
1485

1486
void VCFrame::mouseMoveEvent(QMouseEvent* e)
2✔
1487
{
1488
    if (isBottomFrame() == false)
2✔
1489
        VCWidget::mouseMoveEvent(e);
1✔
1490
    else
1491
        QWidget::mouseMoveEvent(e);
1✔
1492

1493
    if (isCollapsed() == false)
2✔
1494
    {
1495
        m_width = this->width();
2✔
1496
        m_height = this->height();
2✔
1497
    }
1498
}
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

© 2025 Coveralls, Inc