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

mcallegari / qlcplus / 17074071240

19 Aug 2025 03:18PM UTC coverage: 34.258% (-0.03%) from 34.287%
17074071240

Pull #1795

github

web-flow
Merge b8548c089 into 022b66999
Pull Request #1795: Fix/qt6 android build

22 of 111 new or added lines in 7 files covered. (19.82%)

2 existing lines in 1 file now uncovered.

17722 of 51731 relevant lines covered (34.26%)

19401.42 hits per line

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

72.76
/ui/src/virtualconsole/vcwidget.cpp
1
/*
2
  Q Light Controller Plus
3
  vcwidget.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 <QStyleOptionFrame>
22
#include <QXmlStreamReader>
23
#include <QXmlStreamWriter>
24
#include <QApplication>
25
#include <QInputDialog>
26
#include <QColorDialog>
27
#include <QFileDialog>
28
#include <QFontDialog>
29
#include <QMessageBox>
30
#include <QMouseEvent>
31
#include <QMetaObject>
32
#include <QPainter>
33
#include <QPalette>
34
#include <QCursor>
35
#include <QPixmap>
36
#include <QDebug>
37
#include <QBrush>
38
#include <QPoint>
39
#include <QStyle>
40
#include <QSize>
41
#include <QMenu>
42
#include <QList>
43

44
#include "qlcinputsource.h"
45
#include "qlcfile.h"
46

47
#include "qlcinputchannel.h"
48
#include "virtualconsole.h"
49
#include "inputpatch.h"
50
#include "vcwidget.h"
51
#include "doc.h"
52

53
#define GRID_RESOLUTION 5
54

55
VCWidget::VCWidget(QWidget* parent, Doc* doc)
177✔
56
    : QWidget(parent)
57
    , m_doc(doc)
177✔
58
    , m_id(invalidId())
354✔
59
    , m_disableState(false)
177✔
60
    , m_page(0)
177✔
61
    , m_allowChildren(false)
177✔
62
    , m_allowResize(true)
177✔
63
    , m_intensityOverrideId(Function::invalidAttributeId())
177✔
64
    , m_intensity(1.0)
177✔
65
    , m_liveEdit(VirtualConsole::instance()->liveEdit())
354✔
66
{
67
    Q_ASSERT(parent != NULL);
177✔
68
    Q_ASSERT(doc != NULL);
177✔
69

70
    /* Set the class name "VCWidget" as the object name as well */
71
    setObjectName(VCWidget::staticMetaObject.className());
177✔
72

73
    setMinimumSize(QSize(20, 20));
177✔
74

75
    m_type = UnknownWidget;
177✔
76
    m_hasCustomBackgroundColor = false;
177✔
77
    m_hasCustomForegroundColor = false;
177✔
78
    m_backgroundImage = QString();
177✔
79
    m_hasCustomFont = false;
177✔
80
    m_frameStyle = KVCFrameStyleNone;
177✔
81

82
    m_resizeMode = false;
177✔
83

84
    setBackgroundRole(QPalette::Window);
177✔
85
    setAutoFillBackground(true);
177✔
86
    setEnabled(true);
177✔
87

88
    connect(m_doc, SIGNAL(modeChanged(Doc::Mode)),
177✔
89
            this, SLOT(slotModeChanged(Doc::Mode)));
90

91
    /* Listen to the virtual console key signals */
92
    connect(VirtualConsole::instance(), SIGNAL(keyPressed(const QKeySequence&)),
177✔
93
            this, SLOT(slotKeyPressed(const QKeySequence&)));
94
    connect(VirtualConsole::instance(), SIGNAL(keyReleased(const QKeySequence&)),
177✔
95
            this, SLOT(slotKeyReleased(const QKeySequence&)));
96
}
177✔
97

98
VCWidget::~VCWidget()
177✔
99
{
100
}
177✔
101

102
/*****************************************************************************
103
 * ID
104
 *****************************************************************************/
105

106
void VCWidget::setID(quint32 id)
1✔
107
{
108
    /* Don't set doc modified status or emit changed signal, because this
109
       function is called only once during widget creation. */
110
    m_id = id;
1✔
111
}
1✔
112

113
quint32 VCWidget::id() const
18✔
114
{
115
    return m_id;
18✔
116
}
117

118
quint32 VCWidget::invalidId()
197✔
119
{
120
    return UINT_MAX;
197✔
121
}
122

123
/*********************************************************************
124
 * Type
125
 *********************************************************************/
126

127
void VCWidget::setType(int type)
153✔
128
{
129
    m_type = type;
153✔
130
}
153✔
131

132
int VCWidget::type()
5✔
133
{
134
    return m_type;
5✔
135
}
136

137
QString VCWidget::typeToString(int type)
×
138
{
139
    switch (type)
×
140
    {
141

142
        case ButtonWidget: return QString(tr("Button"));
×
143
        case SliderWidget: return QString(tr("Slider"));
×
144
        case XYPadWidget: return QString(tr("XYPad"));
×
145
        case FrameWidget: return QString(tr("Frame"));
×
146
        case SoloFrameWidget: return QString(tr("Solo frame"));
×
147
        case SpeedDialWidget: return QString(tr("Speed dial"));
×
148
        case CueListWidget: return QString(tr("Cue list"));
×
149
        case LabelWidget: return QString(tr("Label"));
×
150
        case AudioTriggersWidget: return QString(tr("Audio Triggers"));
×
151
        case AnimationWidget: return QString(tr("Animation"));
×
152
        case ClockWidget: return QString(tr("Clock"));
×
153
        case UnknownWidget:
×
154
        default:
155
             return QString(tr("Unknown"));
×
156
    }
157
    return QString(tr("Unknown"));
158
}
159

160
QIcon VCWidget::typeToIcon(int type)
×
161
{
162
    switch (type)
×
163
    {
164
        case ButtonWidget: return QIcon(":/button.png");
×
165
        case SliderWidget: return QIcon(":/slider.png");
×
166
        case XYPadWidget: return QIcon(":/xypad.png");
×
167
        case FrameWidget: return QIcon(":/frame.png");
×
168
        case SoloFrameWidget: return QIcon(":/soloframe.png");
×
169
        case SpeedDialWidget: return QIcon(":/speed.png");
×
170
        case CueListWidget: return QIcon(":/cuelist.png");
×
171
        case LabelWidget: return QIcon(":/label.png");
×
172
        case AudioTriggersWidget: return QIcon(":/audioinput.png");
×
173
        case AnimationWidget: return QIcon(":/rgbmatrix.png");
×
174
        case ClockWidget: return QIcon(":/clock.png");
×
175
        case UnknownWidget:
×
176
        default:
177
             return QIcon(":/virtualconsole.png");
×
178
    }
179
    return QIcon(":/virtualconsole.png");
180
}
181

182
/*********************************************************************
183
 * Disable state
184
 *********************************************************************/
185

186
void VCWidget::setDisableState(bool disable)
×
187
{
188
    m_disableState = disable;
×
189
    if (mode() == Doc::Operate)
×
190
    {
191
        setEnabled(!disable);
×
192
        enableWidgetUI(!disable);
×
193
    }
194

195
    emit disableStateChanged(m_disableState);
×
196
}
×
197

198
void VCWidget::enableWidgetUI(bool enable)
×
199
{
200
    Q_UNUSED(enable)
201
}
×
202

203
bool VCWidget::isDisabled()
76✔
204
{
205
    return m_disableState;
76✔
206
}
207

208
/*********************************************************************
209
 * Page
210
 *********************************************************************/
211

212
void VCWidget::setPage(int pNum)
×
213
{
214
    m_page = pNum;
×
215
}
×
216

217
int VCWidget::page()
46✔
218
{
219
    return m_page;
46✔
220
}
221

222
/*****************************************************************************
223
 * Clipboard
224
 *****************************************************************************/
225

226
bool VCWidget::copyFrom(const VCWidget* widget)
9✔
227
{
228
    if (widget == NULL)
9✔
229
        return false;
1✔
230

231
    setBackgroundImage(widget->m_backgroundImage);
8✔
232

233
    m_hasCustomBackgroundColor = widget->m_hasCustomBackgroundColor;
8✔
234
    if (m_hasCustomBackgroundColor == true)
8✔
235
        setBackgroundColor(widget->backgroundColor());
1✔
236

237
    m_hasCustomForegroundColor = widget->m_hasCustomForegroundColor;
8✔
238
    if (m_hasCustomForegroundColor == true)
8✔
239
        setForegroundColor(widget->foregroundColor());
1✔
240

241
    m_hasCustomFont = widget->m_hasCustomFont;
8✔
242
    if (m_hasCustomFont == true)
8✔
243
        setFont(widget->font());
1✔
244

245
    m_frameStyle = widget->m_frameStyle;
8✔
246

247
    setGeometry(widget->geometry());
8✔
248
    setCaption(widget->caption());
8✔
249

250
    m_allowChildren = widget->m_allowChildren;
8✔
251
    m_allowResize = widget->m_allowResize;
8✔
252

253
    QHashIterator <quint8, QSharedPointer<QLCInputSource> > it(widget->m_inputs);
8✔
254
    while (it.hasNext() == true)
11✔
255
    {
256
        it.next();
3✔
257
        quint8 id = it.key();
3✔
258
        QSharedPointer<QLCInputSource> src(new QLCInputSource(it.value()->universe(), it.value()->channel()));
3✔
259
        src->setFeedbackValue(QLCInputFeedback::LowerValue, it.value()->feedbackValue(QLCInputFeedback::LowerValue));
3✔
260
        src->setFeedbackValue(QLCInputFeedback::UpperValue, it.value()->feedbackValue(QLCInputFeedback::UpperValue));
3✔
261
        src->setFeedbackValue(QLCInputFeedback::MonitorValue, it.value()->feedbackValue(QLCInputFeedback::MonitorValue));
3✔
262
        src->setFeedbackExtraParams(QLCInputFeedback::LowerValue, it.value()->feedbackExtraParams(QLCInputFeedback::LowerValue));
3✔
263
        src->setFeedbackExtraParams(QLCInputFeedback::UpperValue, it.value()->feedbackExtraParams(QLCInputFeedback::UpperValue));
3✔
264
        src->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, it.value()->feedbackExtraParams(QLCInputFeedback::MonitorValue));
3✔
265
        setInputSource(src, id);
3✔
266
    }
3✔
267

268
    m_page = widget->m_page;
8✔
269

270
    return true;
8✔
271
}
8✔
272

273
/*****************************************************************************
274
 * Background image
275
 *****************************************************************************/
276

277
void VCWidget::setBackgroundImage(const QString& path)
14✔
278
{
279
    QPalette pal = palette();
14✔
280

281
    m_hasCustomBackgroundColor = false;
14✔
282
    m_backgroundImage = path;
14✔
283

284
    pal.setBrush(QPalette::Window, QBrush(QPixmap(path)));
14✔
285
    setPalette(pal);
14✔
286

287
    m_doc->setModified();
14✔
288
}
14✔
289

290
QString VCWidget::backgroundImage() const
24✔
291
{
292
    return m_backgroundImage;
24✔
293
}
294

295

296
/*****************************************************************************
297
 * Background color
298
 *****************************************************************************/
299

300
void VCWidget::setBackgroundColor(const QColor& color)
11✔
301
{
302
    QPalette pal = palette();
11✔
303

304
    m_hasCustomBackgroundColor = true;
11✔
305
    m_backgroundImage = QString();
11✔
306

307
    pal.setColor(QPalette::Window, color);
11✔
308
    setPalette(pal);
11✔
309

310
    m_doc->setModified();
11✔
311
}
11✔
312

313
QColor VCWidget::backgroundColor() const
11✔
314
{
315
    return palette().color(QPalette::Window);
11✔
316
}
317

318
bool VCWidget::hasCustomBackgroundColor() const
29✔
319
{
320
    return m_hasCustomBackgroundColor;
29✔
321
}
322

323
void VCWidget::resetBackgroundColor()
3✔
324
{
325
    QColor fg;
3✔
326

327
    m_hasCustomBackgroundColor = false;
3✔
328
    m_backgroundImage = QString();
3✔
329

330
    /* Store foreground color */
331
    if (m_hasCustomForegroundColor == true)
3✔
332
        fg = palette().color(QPalette::WindowText);
2✔
333

334
    /* Reset the whole palette to application palette */
335
    setPalette(QApplication::palette());
3✔
336
    /* setAutoFillBackground(false); */
337

338
    /* Restore foreground color */
339
    if (fg.isValid() == true)
3✔
340
    {
341
        QPalette pal = palette();
2✔
342
        pal.setColor(QPalette::WindowText, fg);
2✔
343
        setPalette(pal);
2✔
344
    }
2✔
345

346
    m_doc->setModified();
3✔
347
}
3✔
348

349
/*****************************************************************************
350
 * Foreground color
351
 *****************************************************************************/
352

353
void VCWidget::setForegroundColor(const QColor& color)
7✔
354
{
355
    QPalette pal = palette();
7✔
356

357
    m_hasCustomForegroundColor = true;
7✔
358

359
    pal.setColor(QPalette::WindowText, color);
7✔
360
    setPalette(pal);
7✔
361

362
    m_doc->setModified();
7✔
363
}
7✔
364

365
QColor VCWidget::foregroundColor() const
10✔
366
{
367
    return palette().color(QPalette::WindowText);
10✔
368
}
369

370
bool VCWidget::hasCustomForegroundColor() const
21✔
371
{
372
    return m_hasCustomForegroundColor;
21✔
373
}
374

375
void VCWidget::resetForegroundColor()
4✔
376
{
377
    QColor bg;
4✔
378

379
    m_hasCustomForegroundColor = false;
4✔
380

381
    /* Store background color */
382
    if (hasCustomBackgroundColor() == true)
4✔
383
        bg = palette().color(QPalette::Window);
2✔
384

385
    /* Reset the whole palette to application palette */
386
    setPalette(QApplication::palette());
4✔
387

388
    /* Restore foreground color (the first two emit Doc::modified() signal) */
389
    if (bg.isValid() == true)
4✔
390
        setBackgroundColor(bg);
2✔
391
    else if (backgroundImage().isEmpty() == false)
2✔
392
        setBackgroundImage(backgroundImage());
1✔
393
    else
394
        m_doc->setModified();
1✔
395
}
4✔
396

397
/*****************************************************************************
398
 * Font
399
 *****************************************************************************/
400

401
void VCWidget::setFont(const QFont& font)
10✔
402
{
403
    m_hasCustomFont = true;
10✔
404
    QWidget::setFont(font);
10✔
405
    m_doc->setModified();
10✔
406
}
10✔
407

408
QFont VCWidget::font() const
25✔
409
{
410
    return QWidget::font();
25✔
411
}
412

413
bool VCWidget::hasCustomFont() const
12✔
414
{
415
    return m_hasCustomFont;
12✔
416
}
417

418
void VCWidget::resetFont()
1✔
419
{
420
    QWidget::setFont(QApplication::font());
1✔
421
    m_hasCustomFont = false;
1✔
422
    m_doc->setModified();
1✔
423
}
1✔
424

425
/*****************************************************************************
426
 * Caption
427
 *****************************************************************************/
428

429
void VCWidget::setCaption(const QString& text)
88✔
430
{
431
    setWindowTitle(text);
88✔
432
    update();
88✔
433
    m_doc->setModified();
88✔
434
}
88✔
435

436
QString VCWidget::caption() const
54✔
437
{
438
    return windowTitle();
54✔
439
}
440

441
/*****************************************************************************
442
 * Frame style
443
 *****************************************************************************/
444

445
void VCWidget::setFrameStyle(int style)
230✔
446
{
447
    m_frameStyle = style;
230✔
448
    update();
230✔
449
    m_doc->setModified();
230✔
450
}
230✔
451

452
int VCWidget::frameStyle() const
83✔
453
{
454
    return m_frameStyle;
83✔
455
}
456

457
void VCWidget::resetFrameStyle()
1✔
458
{
459
    setFrameStyle(KVCFrameStyleNone);
1✔
460
}
1✔
461

462
QString VCWidget::frameStyleToString(int style)
13✔
463
{
464
    if (style == KVCFrameStyleSunken)
13✔
465
        return "Sunken";
6✔
466
    else if (style == KVCFrameStyleRaised)
7✔
467
        return "Raised";
2✔
468
    else
469
        return "None";
5✔
470
}
471

472
int VCWidget::stringToFrameStyle(const QString& style)
6✔
473
{
474
    if (style == "Sunken")
6✔
475
        return KVCFrameStyleSunken;
3✔
476
    else if (style == "Raised")
3✔
477
        return KVCFrameStyleRaised;
1✔
478
    else
479
        return KVCFrameStyleNone;
2✔
480
}
481

482
/*****************************************************************************
483
 * Allow adding children
484
 *****************************************************************************/
485

486
void VCWidget::setAllowChildren(bool allow)
99✔
487
{
488
    m_allowChildren = allow;
99✔
489
}
99✔
490

491
bool VCWidget::allowChildren() const
17✔
492
{
493
    return m_allowChildren;
17✔
494
}
495

496
/*********************************************************************
497
 * Allow resizing
498
 *********************************************************************/
499

500
void VCWidget::setAllowResize(bool allow)
5✔
501
{
502
    m_allowResize = allow;
5✔
503
}
5✔
504

505
bool VCWidget::allowResize() const
8✔
506
{
507
    return m_allowResize;
8✔
508
}
509

510
/*****************************************************************************
511
 * Properties
512
 *****************************************************************************/
513

514
void VCWidget::editProperties()
×
515
{
516
    QMessageBox::information(this, staticMetaObject.className(),
×
517
                             tr("This widget has no properties"));
×
518
}
×
519

520
/*********************************************************************
521
 * Intensity
522
 *********************************************************************/
523

524
void VCWidget::adjustFunctionIntensity(Function *f, qreal value)
11✔
525
{
526
    if (f == NULL)
11✔
527
        return;
×
528

529
    //qDebug() << "adjustFunctionIntensity" << caption() << "value" << value;
530

531
    if (m_intensityOverrideId == Function::invalidAttributeId())
11✔
532
        m_intensityOverrideId = f->requestAttributeOverride(Function::Intensity, value);
11✔
533
    else
534
        f->adjustAttribute(value, m_intensityOverrideId);
×
535
}
536

537
void VCWidget::resetIntensityOverrideAttribute()
12✔
538
{
539
    m_intensityOverrideId = Function::invalidAttributeId();
12✔
540
}
12✔
541

542
void VCWidget::adjustIntensity(qreal val)
×
543
{
544
    m_intensity = val;
×
545
}
×
546

547
qreal VCWidget::intensity() const
31✔
548
{
549
    return m_intensity;
31✔
550
}
551

552
/*****************************************************************************
553
 * External input
554
 *****************************************************************************/
555

556
bool VCWidget::acceptsInput()
63✔
557
{
558
    if (mode() == Doc::Design || isEnabled() == false || isDisabled())
63✔
559
        return false;
7✔
560

561
    return true;
56✔
562
}
563

564
bool VCWidget::checkInputSource(quint32 universe, quint32 channel,
49✔
565
                                uchar value, QObject *sender, quint32 id)
566
{
567
    QSharedPointer<QLCInputSource> const& src = m_inputs.value(id);
49✔
568
    if (src.isNull())
49✔
569
        return false;
8✔
570

571
    if (src->isValid() && src->universe() == universe && src->channel() == channel)
41✔
572
    {
573
        // if the event has been fired by an external controller
574
        // and this channel is set to relative mode, inform the input source
575
        // and don't allow the event to pass through. A synthetic event
576
        // will be generated by the input source itself
577
        if (src != sender && src->needsUpdate())
22✔
578
        {
579
            src->updateInputValue(value);
×
580
            return false;
×
581
        }
582
        return true;
22✔
583
    }
584

585
    return false;
19✔
586
}
49✔
587

588
void VCWidget::setInputSource(QSharedPointer<QLCInputSource> const& source, quint8 id)
36✔
589
{
590
    // Connect when the first valid input source is set
591
    if (m_inputs.isEmpty() == true && !source.isNull() && source->isValid() == true)
36✔
592
    {
593
        connect(m_doc->inputOutputMap(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
12✔
594
                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
595
        connect(m_doc->inputOutputMap(), SIGNAL(profileChanged(quint32,QString)),
12✔
596
                this, SLOT(slotInputProfileChanged(quint32,QString)));
597
    }
598

599
    // Clear previous source
600
    if (m_inputs.contains(id))
36✔
601
    {
602
        disconnect(m_inputs.value(id).data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
3✔
603
                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
604
        m_inputs.remove(id);
3✔
605
    }
606

607
    // Assign
608
    if (!source.isNull() && source->isValid() == true)
36✔
609
    {
610
        m_inputs.insert(id, source);
32✔
611
        // now check if the source is defined in the associated universe
612
        // profile and if it has specific settings
613
        InputPatch *ip = m_doc->inputOutputMap()->inputPatch(source->universe());
32✔
614
        if (ip != NULL)
32✔
615
        {
616
            QLCInputProfile *profile = ip->profile();
×
617
            if (profile != NULL)
×
618
            {
619
                // Do not care about the page since input profiles don't do either
620
                QLCInputChannel *ich = profile->channel(source->channel() & 0xFFFF);
×
621
                if (ich != NULL)
×
622
                {
623
                    // retrieve plugin specific params for feedback
624
                    if (source->feedbackExtraParams(QLCInputFeedback::LowerValue).toInt() == -1)
×
625
                        source->setFeedbackExtraParams(QLCInputFeedback::LowerValue, profile->channelExtraParams(ich));
×
626
                    if (source->feedbackExtraParams(QLCInputFeedback::UpperValue).toInt() == -1 ||
×
627
                        !source->feedbackExtraParams(QLCInputFeedback::UpperValue).isValid())
×
628
                        source->setFeedbackExtraParams(QLCInputFeedback::UpperValue, profile->channelExtraParams(ich));
×
629
                    if (source->feedbackExtraParams(QLCInputFeedback::MonitorValue).toInt() == -1)
×
630
                        source->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, profile->channelExtraParams(ich));
×
631

632
                    if (ich->movementType() == QLCInputChannel::Relative)
×
633
                    {
634
                        source->setWorkingMode(QLCInputSource::Relative);
×
635
                        source->setSensitivity(ich->movementSensitivity());
×
636
                        connect(source.data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
637
                                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
638
                    }
639
                    else if (ich->type() == QLCInputChannel::Encoder)
×
640
                    {
641
                        source->setWorkingMode(QLCInputSource::Encoder);
×
642
                        source->setSensitivity(ich->movementSensitivity());
×
643
                        connect(source.data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
644
                                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
645
                    }
646
                    else if (ich->type() == QLCInputChannel::Button)
×
647
                    {
648
                        if (ich->sendExtraPress() == true)
×
649
                        {
650
                            source->setSendExtraPressRelease(true);
×
651
                            connect(source.data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
652
                                    this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
653
                        }
654

655
                        // user custom feedback have precedence over input profile custom feedback
656
                        uchar lower = source->feedbackValue(QLCInputFeedback::LowerValue) != 0 ?
×
657
                                      source->feedbackValue(QLCInputFeedback::LowerValue) :
×
658
                                      ich->lowerValue();
×
659
                        uchar upper = source->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX ?
×
660
                                          source->feedbackValue(QLCInputFeedback::UpperValue) :
×
661
                                          ich->upperValue();
×
662

663
                        source->setFeedbackValue(QLCInputFeedback::LowerValue, lower);
×
664
                        source->setFeedbackValue(QLCInputFeedback::UpperValue, upper);
×
665
                    }
666
                }
667
            }
668
        }
669
    }
670

671
    // Disconnect when there are no more input sources present
672
    if (m_inputs.isEmpty() == true)
36✔
673
    {
674
        disconnect(m_doc->inputOutputMap(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
4✔
675
                   this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
676
        disconnect(m_doc->inputOutputMap(), SIGNAL(profileChanged(quint32,QString)),
4✔
677
                   this, SLOT(slotInputProfileChanged(quint32,QString)));
678
    }
679
}
36✔
680

681
QSharedPointer<QLCInputSource> VCWidget::inputSource(quint8 id) const
478✔
682
{
683
    return m_inputs.value(id);
478✔
684
}
685

686
void VCWidget::remapInputSources(int pgNum)
×
687
{
688
    QHash <quint8, QSharedPointer<QLCInputSource> >::iterator it = m_inputs.begin();
×
689
    for (; it != m_inputs.end(); it++)
×
690
    {
691
        const QSharedPointer<QLCInputSource>& src(it.value());
×
692
        src->setPage(pgNum);
×
693
        setInputSource(src, it.key());
×
694
    }
695
}
×
696

697
void VCWidget::sendFeedback(int value, quint8 id)
61✔
698
{
699
    /* Send input feedback */
700
    QSharedPointer<QLCInputSource> src = inputSource(id);
61✔
701
    sendFeedback(value, src);
61✔
702
}
61✔
703

704
void VCWidget::sendFeedback(int value, QSharedPointer<QLCInputSource> src, QVariant extraParams)
72✔
705
{
706
    if (src.isNull() || src->isValid() == false)
72✔
707
        return;
57✔
708

709
    // if in relative mode, send a "feedback" to this
710
    // input source so it can continue to emit values
711
    // from the right position
712
    if (src->needsUpdate())
15✔
713
        src->updateOuputValue(value);
×
714

715
    if (acceptsInput() == false)
15✔
716
        return;
3✔
717

718
    //qDebug() << "[VCWidget] Send feedback to uni" << src->universe() << "," << src->channel() << ", param" << extraParams;
719

720
    m_doc->inputOutputMap()->sendFeedBack(
24✔
721
        src->universe(), src->channel(), value,
722
        extraParams.isValid() ? extraParams : src->feedbackExtraParams(QLCInputFeedback::UpperValue));
24✔
723
}
724

NEW
725
void VCWidget::setBackgroundColor(int value, QSharedPointer<QLCInputSource> src)
×
726
{
NEW
727
    InputPatch *ip = m_doc->inputOutputMap()->inputPatch(src->universe());
×
NEW
728
    if (ip != NULL && ip->profile() != NULL)
×
729
    {
NEW
730
        QLCInputProfile *m_profile = ip->profile();
×
NEW
731
        if (m_profile->hasColorTable())
×
732
        {
NEW
733
            QMapIterator <uchar, QPair<QString, QColor>> it(m_profile->colorTable());
×
NEW
734
            while (it.hasNext() == true)
×
735
            {
NEW
736
                it.next();
×
NEW
737
                QPair<QString, QColor> lc = it.value();
×
738

NEW
739
                if (it.key() == value)
×
NEW
740
                    setBackgroundColor(lc.second);
×
NEW
741
            }
×
NEW
742
        }
×
743
    }
NEW
744
}
×
745

746
void VCWidget::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
1✔
747
{
748
    Q_UNUSED(universe);
749
    Q_UNUSED(channel);
750
    Q_UNUSED(value);
751
}
1✔
752

753
void VCWidget::slotInputProfileChanged(quint32 universe, const QString &profileName)
×
754
{
755
    qDebug() << "[VCWdget] input profile changed" << profileName;
×
756

757
    QLCInputProfile *profile = m_doc->inputOutputMap()->profile(profileName);
×
758

759
    foreach (QSharedPointer<QLCInputSource> const& source, m_inputs)
×
760
    {
761
        if (!source.isNull() && source->universe() == universe)
×
762
        {
763
            // if the profile has been unset, reset all the valid
764
            // input sources to work in absolute mode
765
            if (profile == NULL)
×
766
            {
767
                source->setWorkingMode(QLCInputSource::Absolute);
×
768
            }
769
            else
770
            {
771
                QLCInputChannel *ich = profile->channel(source->channel());
×
772
                if (ich != NULL)
×
773
                {
774
                    if (ich->movementType() == QLCInputChannel::Absolute)
×
775
                        source->setWorkingMode(QLCInputSource::Absolute);
×
776
                    else
777
                    {
778
                        source->setWorkingMode(QLCInputSource::Relative);
×
779
                        source->setSensitivity(ich->movementSensitivity());
×
780
                    }
781
                }
782
            }
783
        }
784
    }
×
785
}
×
786

787
/*****************************************************************************
788
 * Key sequence handler
789
 *****************************************************************************/
790

791
QKeySequence VCWidget::stripKeySequence(const QKeySequence& seq)
12✔
792
{
793
    /* In QLC 3.2.x it is possible to set shortcuts like CTRL+X, but since
794
       CTRL is now the tap modifier, it must be stripped away. */
795
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
796
    int keys[4] = { 0, 0, 0, 0 };
797
    for (int i = 0; i < (int)seq.count() && i < 4; i++)
798
    {
799
        if ((seq[i] & Qt::ControlModifier) != 0)
800
            keys[i] = seq[i] & (~Qt::ControlModifier);
801
        else
802
            keys[i] = seq[i];
803
    }
804
#else
805
    QKeyCombination keys[4] = { Qt::Key_unknown, QKeyCombination::fromCombined(0),
12✔
806
                               QKeyCombination::fromCombined(0), QKeyCombination::fromCombined(0)};
807
    for (int i = 0; i < (int)seq.count() && i < 4; i++)
24✔
808
    {
809
        if ((seq[i].toCombined() & Qt::ControlModifier) != 0)
12✔
810
            keys[i] = keys[i].fromCombined(seq[i].toCombined() & (~Qt::ControlModifier));
4✔
811
        else
812
            keys[i] = seq[i];
8✔
813
    }
814
#endif
815
    return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
24✔
816
}
817

818
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
819
{
820
    emit keyPressed(keySequence);
1✔
821
}
1✔
822

823
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
824
{
825
    emit keyReleased(keySequence);
1✔
826
}
1✔
827

828
/*****************************************************************************
829
 * Load & Save
830
 *****************************************************************************/
831

832
void VCWidget::postLoad()
6✔
833
{
834
    /* NOP */
835
}
6✔
836

837
bool VCWidget::loadXMLCommon(QXmlStreamReader &root)
14✔
838
{
839
    if (root.device() == NULL || root.hasError())
14✔
840
        return false;
×
841

842
    QXmlStreamAttributes attrs = root.attributes();
14✔
843

844
    /* ID */
845
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
846
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
847

848
    /* Caption */
849
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
850
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
6✔
851

852
    /* Page */
853
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
854
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
855

856
    return true;
14✔
857
}
14✔
858

859
bool VCWidget::loadXMLAppearance(QXmlStreamReader &root)
9✔
860
{
861
    if (root.device() == NULL || root.hasError())
9✔
862
        return false;
×
863

864
    if (root.name() != KXMLQLCVCWidgetAppearance)
9✔
865
    {
866
        qWarning() << Q_FUNC_INFO << "Appearance node not found!";
1✔
867
        return false;
1✔
868
    }
869

870
    /* Children */
871
    while (root.readNextStartElement())
24✔
872
    {
873
        if (root.name() == KXMLQLCVCFrameStyle)
16✔
874
        {
875
            setFrameStyle(stringToFrameStyle(root.readElementText()));
2✔
876
        }
877
        else if (root.name() == KXMLQLCVCWidgetForegroundColor)
14✔
878
        {
879
            QString str = root.readElementText();
2✔
880
            if (str != KXMLQLCVCWidgetColorDefault)
2✔
881
                setForegroundColor(QColor(str.toUInt()));
1✔
882
            else if (hasCustomForegroundColor() == true)
1✔
883
                resetForegroundColor();
1✔
884
        }
2✔
885
        else if (root.name() == KXMLQLCVCWidgetBackgroundColor)
12✔
886
        {
887
            QString str = root.readElementText();
2✔
888
            if (str != KXMLQLCVCWidgetColorDefault)
2✔
889
                setBackgroundColor(QColor(str.toUInt()));
1✔
890
        }
2✔
891
        else if (root.name() == KXMLQLCVCWidgetBackgroundImage)
10✔
892
        {
893
            QString str = root.readElementText();
2✔
894
            if (str != KXMLQLCVCWidgetBackgroundImageNone)
2✔
895
                setBackgroundImage(m_doc->denormalizeComponentPath(str));
1✔
896
        }
2✔
897
        else if (root.name() == KXMLQLCVCWidgetFont)
8✔
898
        {
899
            QString str = root.readElementText();
6✔
900
            if (str != KXMLQLCVCWidgetFontDefault)
6✔
901
            {
902
                QFont font;
6✔
903
                font.fromString(str);
6✔
904
                setFont(font);
6✔
905
            }
6✔
906
        }
6✔
907
        else
908
        {
909
            qWarning() << Q_FUNC_INFO << "Unknown appearance tag:" << root.name();
2✔
910
            root.skipCurrentElement();
2✔
911
        }
912
    }
913

914
    return true;
8✔
915
}
916

917
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
918
{
919
    QXmlStreamAttributes attrs = root.attributes();
7✔
920

921
    quint32 uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
7✔
922
    quint32 ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
7✔
923
    uchar min = 0, max = UCHAR_MAX, mon = UCHAR_MAX;
7✔
924

925
    QSharedPointer<QLCInputSource>newSrc = QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch));
7✔
926
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerValue))
7✔
927
        min = uchar(attrs.value(KXMLQLCVCWidgetInputLowerValue).toString().toUInt());
×
928
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperValue))
7✔
929
        max = uchar(attrs.value(KXMLQLCVCWidgetInputUpperValue).toString().toUInt());
×
930
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorValue))
7✔
931
        mon = uchar(attrs.value(KXMLQLCVCWidgetInputMonitorValue).toString().toUInt());
×
932

933
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
934
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
935
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
936

937
    // load feedback extra params
938
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerParams))
7✔
939
        newSrc->setFeedbackExtraParams(QLCInputFeedback::LowerValue, attrs.value(KXMLQLCVCWidgetInputLowerParams).toInt());
×
940
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperParams))
7✔
941
        newSrc->setFeedbackExtraParams(QLCInputFeedback::UpperValue, attrs.value(KXMLQLCVCWidgetInputUpperParams).toInt());
×
942
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorParams))
7✔
943
        newSrc->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, attrs.value(KXMLQLCVCWidgetInputMonitorParams).toInt());
×
944

945
    return newSrc;
14✔
946
}
7✔
947

948
bool VCWidget::loadXMLInput(QXmlStreamReader &root, const quint8 &id)
8✔
949
{
950
    if (root.device() == NULL || root.hasError())
8✔
951
        return false;
×
952

953
    if (root.name() != KXMLQLCVCWidgetInput)
8✔
954
        return false;
1✔
955

956
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
957

958
    setInputSource(newSrc, id);
7✔
959

960
    root.skipCurrentElement();
7✔
961

962
    return true;
7✔
963
}
7✔
964

965
QString VCWidget::loadXMLSources(QXmlStreamReader &root, quint8 sourceID)
6✔
966
{
967
    QString keyText;
6✔
968
    while (root.readNextStartElement())
14✔
969
    {
970
        if (root.name() == KXMLQLCVCWidgetInput)
8✔
971
        {
972
            loadXMLInput(root, sourceID);
4✔
973
        }
974
        else if (root.name() == KXMLQLCVCWidgetKey)
4✔
975
        {
976
            keyText = root.readElementText();
4✔
977
        }
978
        else
979
        {
980
            qWarning() << Q_FUNC_INFO << "Unknown source tag" << root.name().toString();
×
981
            root.skipCurrentElement();
×
982
        }
983
    }
984
    return keyText;
6✔
985
}
×
986

987
bool VCWidget::loadXMLInput(QXmlStreamReader &root, quint32* uni, quint32* ch) const
×
988
{
989
    if (root.name() != KXMLQLCVCWidgetInput)
×
990
    {
991
        qWarning() << Q_FUNC_INFO << "Input node not found!";
×
992
        return false;
×
993
    }
994
    else
995
    {
996
        QXmlStreamAttributes attrs = root.attributes();
×
997
        *uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
×
998
        *ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
×
999
        root.skipCurrentElement();
×
1000
    }
×
1001

1002
    return true;
×
1003
}
1004

1005
QString VCWidget::extraParamToString(QVariant param)
36✔
1006
{
1007
    if (param.isValid() == false)
36✔
1008
        return QString();
×
1009

1010
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1011
    if (param.type() == QVariant::Int && param.toInt() != -1)
1012
        return QString::number(param.toInt());
1013
#else
1014
    if (param.metaType().id() == QMetaType::Int && param.toInt() != -1)
36✔
1015
        return QString::number(param.toInt());
×
1016
#endif
1017
    return QString();
36✔
1018
}
1019

1020
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc)
7✔
1021
{
1022
    Q_ASSERT(doc != NULL);
7✔
1023

1024
    /* Caption */
1025
    doc->writeAttribute(KXMLQLCVCCaption, caption());
14✔
1026

1027
    /* ID */
1028
    if (id() != VCWidget::invalidId())
7✔
1029
        doc->writeAttribute(KXMLQLCVCWidgetID, QString::number(id()));
×
1030

1031
    /* Page */
1032
    if (page() != 0)
7✔
1033
        doc->writeAttribute(KXMLQLCVCWidgetPage, QString::number(page()));
×
1034

1035
    return true;
7✔
1036
}
1037

1038
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1039
{
1040
    Q_ASSERT(doc != NULL);
9✔
1041

1042
    QString str;
9✔
1043

1044
    /* VC appearance entry */
1045
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
18✔
1046

1047
    /* Frame style */
1048
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
18✔
1049

1050
    /* Foreground color */
1051
    if (hasCustomForegroundColor() == true)
9✔
1052
        str.setNum(foregroundColor().rgb());
1✔
1053
    else
1054
        str = KXMLQLCVCWidgetColorDefault;
8✔
1055
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
18✔
1056

1057
    /* Background color */
1058
    if (hasCustomBackgroundColor() == true)
9✔
1059
        str.setNum(backgroundColor().rgb());
1✔
1060
    else
1061
        str = KXMLQLCVCWidgetColorDefault;
8✔
1062
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
18✔
1063

1064
    /* Background image */
1065
    if (backgroundImage().isEmpty() == false)
9✔
1066
        str = m_doc->normalizeComponentPath(m_backgroundImage);
1✔
1067
    else
1068
        str = KXMLQLCVCWidgetBackgroundImageNone;
8✔
1069
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundImage, str);
18✔
1070

1071
    /* Font */
1072
    if (hasCustomFont() == true)
9✔
1073
        str = font().toString();
1✔
1074
    else
1075
        str = KXMLQLCVCWidgetFontDefault;
8✔
1076
    doc->writeTextElement(KXMLQLCVCWidgetFont, str);
18✔
1077

1078
    /* End the <Appearance> tag */
1079
    doc->writeEndElement();
9✔
1080

1081
    return true;
9✔
1082
}
9✔
1083

1084
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1085
{
1086
    return saveXMLInput(doc, inputSource());
4✔
1087
}
1088

1089
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1090
                            const QLCInputSource *src)
1091
{
1092
    Q_ASSERT(doc != NULL);
14✔
1093

1094
    if (src == NULL)
14✔
1095
        return false;
2✔
1096

1097
    if (src->isValid() == true)
12✔
1098
    {
1099
        doc->writeStartElement(KXMLQLCVCWidgetInput);
24✔
1100
        doc->writeAttribute(KXMLQLCVCWidgetInputUniverse, QString("%1").arg(src->universe()));
24✔
1101
        doc->writeAttribute(KXMLQLCVCWidgetInputChannel, QString("%1").arg(src->channel()));
24✔
1102
        if (src->feedbackValue(QLCInputFeedback::LowerValue) != 0)
12✔
1103
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerValue, QString::number(src->feedbackValue(QLCInputFeedback::LowerValue)));
×
1104
        if (src->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX)
12✔
1105
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperValue, QString::number(src->feedbackValue(QLCInputFeedback::UpperValue)));
24✔
1106
        if (src->feedbackValue(QLCInputFeedback::MonitorValue) != UCHAR_MAX)
12✔
1107
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorValue, QString::number(src->feedbackValue(QLCInputFeedback::MonitorValue)));
24✔
1108

1109
        // save feedback extra params
1110
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
12✔
1111

1112
        if (!extraParams.isEmpty())
12✔
1113
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1114

1115
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
12✔
1116

1117
        if (!extraParams.isEmpty())
12✔
1118
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperParams, extraParams);
×
1119

1120
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
12✔
1121

1122
        if (!extraParams.isEmpty())
12✔
1123
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorParams, extraParams);
×
1124

1125
        doc->writeEndElement();
12✔
1126
    }
12✔
1127

1128
    return true;
12✔
1129
}
1130

1131
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1132
                      QSharedPointer<QLCInputSource> const& src)
1133
{
1134
    return saveXMLInput(doc, src.data());
14✔
1135
}
1136

1137
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1138
{
1139
    Q_ASSERT(doc != NULL);
8✔
1140

1141
    /* Window state tag */
1142
    doc->writeStartElement(KXMLQLCWindowState);
16✔
1143

1144
    /* Visible status */
1145
    if (isVisible() == true)
8✔
1146
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
4✔
1147
    else
1148
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
12✔
1149

1150
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
16✔
1151
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
16✔
1152
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
16✔
1153
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
16✔
1154

1155
    doc->writeEndElement();
8✔
1156

1157
    return true;
8✔
1158
}
1159

1160
bool VCWidget::loadXMLWindowState(QXmlStreamReader &tag, int* x, int* y,
15✔
1161
                                  int* w, int* h, bool* visible)
1162
{
1163
    if (tag.device() == NULL || x == NULL || y == NULL || w == NULL || h == NULL ||
15✔
1164
            visible == NULL)
1165
        return false;
5✔
1166

1167
    if (tag.name() == KXMLQLCWindowState)
10✔
1168
    {
1169
        QXmlStreamAttributes attrs = tag.attributes();
9✔
1170
        *x = attrs.value(KXMLQLCWindowStateX).toString().toInt();
9✔
1171
        *y = attrs.value(KXMLQLCWindowStateY).toString().toInt();
9✔
1172
        *w = attrs.value(KXMLQLCWindowStateWidth).toString().toInt();
9✔
1173
        *h = attrs.value(KXMLQLCWindowStateHeight).toString().toInt();
9✔
1174

1175
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
18✔
1176
            *visible = true;
8✔
1177
        else
1178
            *visible = false;
1✔
1179
        tag.skipCurrentElement();
9✔
1180

1181
        return true;
9✔
1182
    }
9✔
1183
    else
1184
    {
1185
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1186
        return false;
1✔
1187
    }
1188
}
1189

1190
/*****************************************************************************
1191
 * QLC+ Mode change
1192
 *****************************************************************************/
1193

1194
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1195
{
1196
    if (m_doc->mode() == Doc::Design)
25✔
1197
        return;
25✔
1198

1199
    m_liveEdit = liveEdit;
×
1200

1201
    if (m_disableState)
×
1202
        setEnabled(m_liveEdit);
×
1203
    else
1204
        enableWidgetUI(!m_liveEdit);
×
1205

1206
    unsetCursor();
×
1207
    update();
×
1208
}
1209

1210
void VCWidget::cancelLiveEdit()
×
1211
{
1212
    m_liveEdit = false;
×
1213
}
×
1214

1215
void VCWidget::slotModeChanged(Doc::Mode mode)
66✔
1216
{
1217
    // make sure to exit from a 'deep' disable state
1218
    if (mode == Doc::Design)
66✔
1219
        setEnabled(true);
34✔
1220

1221
    /* Reset mouse cursor */
1222
    unsetCursor();
66✔
1223

1224
    /* Force an update to get rid of selection markers */
1225
    update();
66✔
1226
}
66✔
1227

1228
Doc::Mode VCWidget::mode() const
191✔
1229
{
1230
    Q_ASSERT(m_doc != NULL);
191✔
1231
    if (m_liveEdit)
191✔
1232
        return Doc::Design;
×
1233
    return m_doc->mode();
191✔
1234
}
1235

1236
/*****************************************************************************
1237
 * Widget menu
1238
 *****************************************************************************/
1239

1240
void VCWidget::invokeMenu(const QPoint& point)
×
1241
{
1242
    /* No point coming here if there is no VC instance */
1243
    VirtualConsole* vc = VirtualConsole::instance();
×
1244
    if (vc == NULL)
×
1245
        return;
×
1246

1247
    QMenu* menu = vc->editMenu();
×
1248
    Q_ASSERT(menu != NULL);
×
1249
    menu->exec(point);
×
1250
}
1251

1252
/*****************************************************************************
1253
 * Custom menu
1254
 *****************************************************************************/
1255

1256
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1257
{
1258
    Q_UNUSED(parentMenu);
1259
    return NULL;
3✔
1260
}
1261

1262
/*****************************************************************************
1263
 * Widget move & resize
1264
 *****************************************************************************/
1265

1266
void VCWidget::resize(const QSize& size)
244✔
1267
{
1268
    QSize sz(size);
244✔
1269

1270
    // Force grid settings
1271
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1272
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1273

1274
    // Resize
1275
    QWidget::resize(sz);
244✔
1276
}
244✔
1277

1278
void VCWidget::move(const QPoint& point)
13✔
1279
{
1280
    QPoint pt(point);
13✔
1281

1282
    // Force grid settings
1283
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1284
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1285

1286
    // Don't move beyond left or right
1287
    if (pt.x() < 0)
13✔
1288
        pt.setX(0);
1✔
1289
    else if (pt.x() + rect().width() > parentWidget()->width())
12✔
1290
        pt.setX(parentWidget()->width() - rect().width());
1✔
1291

1292
    // Don't move beyond top or bottom
1293
    if (pt.y() < 0)
13✔
1294
        pt.setY(0);
1✔
1295
    else if (pt.y() + rect().height() > parentWidget()->height())
12✔
1296
        pt.setY(parentWidget()->height() - rect().height());
1✔
1297

1298
    // Move
1299
    QWidget::move(pt);
13✔
1300

1301
    m_doc->setModified();
13✔
1302
}
13✔
1303

1304
QPoint VCWidget::lastClickPoint() const
2✔
1305
{
1306
    return m_mousePressPoint;
2✔
1307
}
1308

1309
/*****************************************************************************
1310
 * Event handlers
1311
 *****************************************************************************/
1312

1313
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1314
{
1315
    Q_UNUSED(e);
1316

1317
    /* No point coming here if there is no VC instance */
1318
    VirtualConsole* vc = VirtualConsole::instance();
32✔
1319
    if (vc == NULL)
32✔
1320
        return;
×
1321

1322
    QPainter painter(this);
32✔
1323

1324
    /* Draw frame according to style */
1325
    QStyleOptionFrame option;
32✔
1326
    option.initFrom(this);
32✔
1327

1328
    if (frameStyle() == KVCFrameStyleSunken)
32✔
1329
        option.state = QStyle::State_Sunken;
3✔
1330
    else if (frameStyle() == KVCFrameStyleRaised)
29✔
1331
        option.state = QStyle::State_Raised;
4✔
1332
    else
1333
        option.state = QStyle::State_None;
25✔
1334

1335
    if (mode() == Doc::Design)
32✔
1336
        option.state |= QStyle::State_Enabled;
28✔
1337

1338
    /* Draw a frame border if such is specified for this widget */
1339
    if (option.state != QStyle::State_None)
32✔
1340
        style()->drawPrimitive(QStyle::PE_Frame, &option, &painter, this);
29✔
1341

1342
    QWidget::paintEvent(e);
32✔
1343

1344
    /* Draw selection frame */
1345
    if (mode() == Doc::Design && vc->isWidgetSelected(this) == true)
32✔
1346
    {
1347
        /* Draw a dotted line around the widget */
1348
        QPen pen(Qt::DashLine);
4✔
1349
        pen.setColor(Qt::blue);
4✔
1350
        pen.setCapStyle(Qt::RoundCap);
4✔
1351
        pen.setWidth(0);
4✔
1352
        painter.setPen(pen);
4✔
1353
        painter.drawRect(0, 0, rect().width() - 1, rect().height() - 1);
4✔
1354

1355
        /* Draw a resize handle */
1356
        if (allowResize() == true)
4✔
1357
        {
1358
            QIcon icon(":/resize.png");
3✔
1359
            painter.drawPixmap(rect().width() - 16, rect().height() - 16,
3✔
1360
                               icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On));
6✔
1361
        }
3✔
1362
    }
4✔
1363
}
32✔
1364

1365
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1366
{
1367
    Q_ASSERT(e != NULL);
2✔
1368

1369
    if (mode() == Doc::Operate)
2✔
1370
    {
1371
        QWidget::mousePressEvent(e);
×
1372
        return;
×
1373
    }
1374

1375
    /* Perform widget de/selection in virtualconsole's selection buffer */
1376
    handleWidgetSelection(e);
2✔
1377

1378
    /* Resize mode */
1379
    if (m_resizeMode == true)
2✔
1380
    {
1381
        setMouseTracking(false);
×
1382
        m_resizeMode = false;
×
1383
    }
1384

1385
    /* Move, resize or context menu invocation */
1386
    if (e->button() & Qt::LeftButton || e->button() & Qt::MiddleButton)
2✔
1387
    {
1388
        /* Start moving or resizing based on where the click landed */
1389
        if (e->pos().x() > rect().width() - 10 && e->pos().y() > rect().height() - 10 && allowResize())
2✔
1390
        {
1391
            m_resizeMode = true;
×
1392
            setMouseTracking(true);
×
1393
            setCursor(QCursor(Qt::SizeFDiagCursor));
×
1394
        }
1395
        else
1396
        {
1397
            m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
2✔
1398
            setCursor(QCursor(Qt::SizeAllCursor));
2✔
1399
        }
1400
    }
1401
    else if (e->button() & Qt::RightButton)
×
1402
    {
1403
        /* Menu invocation */
1404
        m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
×
1405
        invokeMenu(mapToGlobal(e->pos()));
×
1406
    }
1407
}
1408

1409
void VCWidget::handleWidgetSelection(QMouseEvent* e)
3✔
1410
{
1411
    /* No point coming here if there is no VC */
1412
    VirtualConsole* vc = VirtualConsole::instance();
3✔
1413
    if (vc == NULL)
3✔
1414
        return;
×
1415

1416
    /* Widget selection logic (like in Qt Designer) */
1417
    if (e->button() == Qt::LeftButton)
3✔
1418
    {
1419
        if (e->modifiers() & Qt::ShiftModifier)
3✔
1420
        {
1421
            /* Toggle selection with LMB when shift is pressed */
1422
            bool selected = vc->isWidgetSelected(this);
×
1423
            vc->setWidgetSelected(this, !selected);
×
1424
        }
1425
        else
1426
        {
1427
            if (vc->isWidgetSelected(this) == false)
3✔
1428
            {
1429
                /* Select only this */
1430
                vc->clearWidgetSelection();
3✔
1431
                vc->setWidgetSelected(this, true);
3✔
1432
            }
1433
        }
1434
    }
1435
    else if (e->button() == Qt::RightButton)
×
1436
    {
1437
        if (vc->isWidgetSelected(this) == false)
×
1438
        {
1439
            /* Select only this */
1440
            vc->clearWidgetSelection();
×
1441
            vc->setWidgetSelected(this, true);
×
1442
        }
1443
    }
1444
}
1445

1446
void VCWidget::mouseReleaseEvent(QMouseEvent* e)
1✔
1447
{
1448
    if (mode() == Doc::Design)
1✔
1449
    {
1450
        unsetCursor();
1✔
1451
        m_resizeMode = false;
1✔
1452
        setMouseTracking(false);
1✔
1453
    }
1454
    else
1455
    {
1456
        QWidget::mouseReleaseEvent(e);
×
1457
    }
1458
}
1✔
1459

1460
void VCWidget::mouseDoubleClickEvent(QMouseEvent* e)
×
1461
{
1462
    if (mode() == Doc::Design)
×
1463
        editProperties();
×
1464
    else
1465
        QWidget::mouseDoubleClickEvent(e);
×
1466
}
×
1467

1468
void VCWidget::mouseMoveEvent(QMouseEvent* e)
2✔
1469
{
1470
    if (mode() == Doc::Design)
2✔
1471
    {
1472
        if (m_resizeMode == true)
2✔
1473
        {
1474
            QPoint p = mapToParent(e->pos());
×
1475
            resize(QSize(p.x() - x(), p.y() - y()));
×
1476
            m_doc->setModified();
×
1477
        }
1478
        else if (e->buttons() & Qt::LeftButton || e->buttons() & Qt::MiddleButton)
2✔
1479
        {
1480
            QPoint p = mapToParent(e->pos());
2✔
1481
            p.setX(p.x() - m_mousePressPoint.x());
2✔
1482
            p.setY(p.y() - m_mousePressPoint.y());
2✔
1483

1484
            move(p);
2✔
1485
            m_doc->setModified();
2✔
1486
        }
1487
    }
1488
    else
1489
    {
1490
        QWidget::mouseMoveEvent(e);
×
1491
    }
1492
}
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