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

mcallegari / qlcplus / 19409821768

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

push

github

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

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

2 existing lines in 2 files now uncovered.

17724 of 51774 relevant lines covered (34.23%)

19630.45 hits per line

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

73.71
/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()
21✔
133
{
134
    return m_type;
21✔
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

NEW
510
void VCWidget::notifyFunctionStarting(quint32 fid, qreal intensity, bool excludeMonitored)
×
511
{
512
    Q_UNUSED(fid)
513
    Q_UNUSED(intensity)
514
    Q_UNUSED(excludeMonitored)
NEW
515
}
×
516

517
/*****************************************************************************
518
 * Properties
519
 *****************************************************************************/
520

521
void VCWidget::editProperties()
×
522
{
523
    QMessageBox::information(this, staticMetaObject.className(),
×
524
                             tr("This widget has no properties"));
×
525
}
×
526

527
/*********************************************************************
528
 * Intensity
529
 *********************************************************************/
530

531
void VCWidget::adjustFunctionIntensity(Function *f, qreal value)
11✔
532
{
533
    if (f == NULL)
11✔
534
        return;
×
535

536
    //qDebug() << "adjustFunctionIntensity" << caption() << "value" << value;
537

538
    if (m_intensityOverrideId == Function::invalidAttributeId())
11✔
539
        m_intensityOverrideId = f->requestAttributeOverride(Function::Intensity, value);
11✔
540
    else
541
        f->adjustAttribute(value, m_intensityOverrideId);
×
542
}
543

544
void VCWidget::resetIntensityOverrideAttribute()
12✔
545
{
546
    m_intensityOverrideId = Function::invalidAttributeId();
12✔
547
}
12✔
548

549
void VCWidget::adjustIntensity(qreal val)
×
550
{
551
    m_intensity = val;
×
552
}
×
553

554
qreal VCWidget::intensity() const
31✔
555
{
556
    return m_intensity;
31✔
557
}
558

559
/*****************************************************************************
560
 * External input
561
 *****************************************************************************/
562

563
bool VCWidget::acceptsInput()
63✔
564
{
565
    if (mode() == Doc::Design || isEnabled() == false || isDisabled())
63✔
566
        return false;
7✔
567

568
    return true;
56✔
569
}
570

571
bool VCWidget::checkInputSource(quint32 universe, quint32 channel,
49✔
572
                                uchar value, QObject *sender, quint32 id)
573
{
574
    QSharedPointer<QLCInputSource> const& src = m_inputs.value(id);
49✔
575
    if (src.isNull())
49✔
576
        return false;
8✔
577

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

592
    return false;
19✔
593
}
49✔
594

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

606
    // Clear previous source
607
    if (m_inputs.contains(id))
36✔
608
    {
609
        disconnect(m_inputs.value(id).data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
3✔
610
                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
611
        m_inputs.remove(id);
3✔
612
    }
613

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

639
                    if (ich->movementType() == QLCInputChannel::Relative)
×
640
                    {
641
                        source->setWorkingMode(QLCInputSource::Relative);
×
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::Encoder)
×
647
                    {
648
                        source->setWorkingMode(QLCInputSource::Encoder);
×
649
                        source->setSensitivity(ich->movementSensitivity());
×
650
                        connect(source.data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
651
                                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
652
                    }
653
                    else if (ich->type() == QLCInputChannel::Button)
×
654
                    {
655
                        if (ich->sendExtraPress() == true)
×
656
                        {
657
                            source->setSendExtraPressRelease(true);
×
658
                            connect(source.data(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
×
659
                                    this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
660
                        }
661

662
                        // user custom feedback have precedence over input profile custom feedback
663
                        uchar lower = source->feedbackValue(QLCInputFeedback::LowerValue) != 0 ?
×
664
                                      source->feedbackValue(QLCInputFeedback::LowerValue) :
×
665
                                      ich->lowerValue();
×
666
                        uchar upper = source->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX ?
×
667
                                          source->feedbackValue(QLCInputFeedback::UpperValue) :
×
668
                                          ich->upperValue();
×
669

670
                        source->setFeedbackValue(QLCInputFeedback::LowerValue, lower);
×
671
                        source->setFeedbackValue(QLCInputFeedback::UpperValue, upper);
×
672
                    }
673
                }
674
            }
675
        }
676
    }
677

678
    // Disconnect when there are no more input sources present
679
    if (m_inputs.isEmpty() == true)
36✔
680
    {
681
        disconnect(m_doc->inputOutputMap(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
4✔
682
                   this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
683
        disconnect(m_doc->inputOutputMap(), SIGNAL(profileChanged(quint32,QString)),
4✔
684
                   this, SLOT(slotInputProfileChanged(quint32,QString)));
685
    }
686
}
36✔
687

688
QSharedPointer<QLCInputSource> VCWidget::inputSource(quint8 id) const
438✔
689
{
690
    return m_inputs.value(id);
438✔
691
}
692

693
void VCWidget::remapInputSources(int pgNum)
×
694
{
695
    QHash <quint8, QSharedPointer<QLCInputSource> >::iterator it = m_inputs.begin();
×
696
    for (; it != m_inputs.end(); it++)
×
697
    {
698
        const QSharedPointer<QLCInputSource>& src(it.value());
×
699
        src->setPage(pgNum);
×
700
        setInputSource(src, it.key());
×
701
    }
702
}
×
703

704
void VCWidget::sendFeedback(int value, quint8 id)
61✔
705
{
706
    /* Send input feedback */
707
    QSharedPointer<QLCInputSource> src = inputSource(id);
61✔
708
    sendFeedback(value, src);
61✔
709
}
61✔
710

711
void VCWidget::sendFeedback(int value, QSharedPointer<QLCInputSource> src, QVariant extraParams)
72✔
712
{
713
    if (src.isNull() || src->isValid() == false)
72✔
714
        return;
57✔
715

716
    // if in relative mode, send a "feedback" to this
717
    // input source so it can continue to emit values
718
    // from the right position
719
    if (src->needsUpdate())
15✔
720
        src->updateOuputValue(value);
×
721

722
    if (acceptsInput() == false)
15✔
723
        return;
3✔
724

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

727
    m_doc->inputOutputMap()->sendFeedBack(
24✔
728
        src->universe(), src->channel(), value,
729
        extraParams.isValid() ? extraParams : src->feedbackExtraParams(QLCInputFeedback::UpperValue));
24✔
730
}
731

732
void VCWidget::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
1✔
733
{
734
    Q_UNUSED(universe);
735
    Q_UNUSED(channel);
736
    Q_UNUSED(value);
737
}
1✔
738

739
void VCWidget::slotInputProfileChanged(quint32 universe, const QString &profileName)
×
740
{
741
    qDebug() << "[VCWdget] input profile changed" << profileName;
×
742

743
    QLCInputProfile *profile = m_doc->inputOutputMap()->profile(profileName);
×
744

745
    foreach (QSharedPointer<QLCInputSource> const& source, m_inputs)
×
746
    {
747
        if (!source.isNull() && source->universe() == universe)
×
748
        {
749
            // if the profile has been unset, reset all the valid
750
            // input sources to work in absolute mode
751
            if (profile == NULL)
×
752
            {
753
                source->setWorkingMode(QLCInputSource::Absolute);
×
754
            }
755
            else
756
            {
757
                QLCInputChannel *ich = profile->channel(source->channel());
×
758
                if (ich != NULL)
×
759
                {
760
                    if (ich->movementType() == QLCInputChannel::Absolute)
×
761
                        source->setWorkingMode(QLCInputSource::Absolute);
×
762
                    else
763
                    {
764
                        source->setWorkingMode(QLCInputSource::Relative);
×
765
                        source->setSensitivity(ich->movementSensitivity());
×
766
                    }
767
                }
768
            }
769
        }
770
    }
×
771
}
×
772

773
/*****************************************************************************
774
 * Key sequence handler
775
 *****************************************************************************/
776

777
QKeySequence VCWidget::stripKeySequence(const QKeySequence& seq)
12✔
778
{
779
    /* In QLC 3.2.x it is possible to set shortcuts like CTRL+X, but since
780
       CTRL is now the tap modifier, it must be stripped away. */
781
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
782
    int keys[4] = { 0, 0, 0, 0 };
783
    for (int i = 0; i < (int)seq.count() && i < 4; i++)
784
    {
785
        if ((seq[i] & Qt::ControlModifier) != 0)
786
            keys[i] = seq[i] & (~Qt::ControlModifier);
787
        else
788
            keys[i] = seq[i];
789
    }
790
#else
791
    QKeyCombination keys[4] = { Qt::Key_unknown, QKeyCombination::fromCombined(0),
12✔
792
                               QKeyCombination::fromCombined(0), QKeyCombination::fromCombined(0)};
793
    for (int i = 0; i < (int)seq.count() && i < 4; i++)
24✔
794
    {
795
        if ((seq[i].toCombined() & Qt::ControlModifier) != 0)
12✔
796
            keys[i] = keys[i].fromCombined(seq[i].toCombined() & (~Qt::ControlModifier));
4✔
797
        else
798
            keys[i] = seq[i];
8✔
799
    }
800
#endif
801
    return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
24✔
802
}
803

804
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
805
{
806
    emit keyPressed(keySequence);
1✔
807
}
1✔
808

809
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
810
{
811
    emit keyReleased(keySequence);
1✔
812
}
1✔
813

814
/*****************************************************************************
815
 * Load & Save
816
 *****************************************************************************/
817

818
void VCWidget::postLoad()
6✔
819
{
820
    /* NOP */
821
}
6✔
822

823
bool VCWidget::loadXMLCommon(QXmlStreamReader &root)
14✔
824
{
825
    if (root.device() == NULL || root.hasError())
14✔
826
        return false;
×
827

828
    QXmlStreamAttributes attrs = root.attributes();
14✔
829

830
    /* ID */
831
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
832
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
833

834
    /* Caption */
835
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
836
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
6✔
837

838
    /* Page */
839
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
840
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
841

842
    return true;
14✔
843
}
14✔
844

845
bool VCWidget::loadXMLAppearance(QXmlStreamReader &root)
9✔
846
{
847
    if (root.device() == NULL || root.hasError())
9✔
848
        return false;
×
849

850
    if (root.name() != KXMLQLCVCWidgetAppearance)
9✔
851
    {
852
        qWarning() << Q_FUNC_INFO << "Appearance node not found!";
1✔
853
        return false;
1✔
854
    }
855

856
    /* Children */
857
    while (root.readNextStartElement())
24✔
858
    {
859
        if (root.name() == KXMLQLCVCFrameStyle)
16✔
860
        {
861
            setFrameStyle(stringToFrameStyle(root.readElementText()));
2✔
862
        }
863
        else if (root.name() == KXMLQLCVCWidgetForegroundColor)
14✔
864
        {
865
            QString str = root.readElementText();
2✔
866
            if (str != KXMLQLCVCWidgetColorDefault)
2✔
867
                setForegroundColor(QColor(str.toUInt()));
1✔
868
            else if (hasCustomForegroundColor() == true)
1✔
869
                resetForegroundColor();
1✔
870
        }
2✔
871
        else if (root.name() == KXMLQLCVCWidgetBackgroundColor)
12✔
872
        {
873
            QString str = root.readElementText();
2✔
874
            if (str != KXMLQLCVCWidgetColorDefault)
2✔
875
                setBackgroundColor(QColor(str.toUInt()));
1✔
876
        }
2✔
877
        else if (root.name() == KXMLQLCVCWidgetBackgroundImage)
10✔
878
        {
879
            QString str = root.readElementText();
2✔
880
            if (str != KXMLQLCVCWidgetBackgroundImageNone)
2✔
881
                setBackgroundImage(m_doc->denormalizeComponentPath(str));
1✔
882
        }
2✔
883
        else if (root.name() == KXMLQLCVCWidgetFont)
8✔
884
        {
885
            QString str = root.readElementText();
6✔
886
            if (str != KXMLQLCVCWidgetFontDefault)
6✔
887
            {
888
                QFont font;
6✔
889
                font.fromString(str);
6✔
890
                setFont(font);
6✔
891
            }
6✔
892
        }
6✔
893
        else
894
        {
895
            qWarning() << Q_FUNC_INFO << "Unknown appearance tag:" << root.name();
2✔
896
            root.skipCurrentElement();
2✔
897
        }
898
    }
899

900
    return true;
8✔
901
}
902

903
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
904
{
905
    QXmlStreamAttributes attrs = root.attributes();
7✔
906

907
    quint32 uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
7✔
908
    quint32 ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
7✔
909
    uchar min = 0, max = UCHAR_MAX, mon = UCHAR_MAX;
7✔
910

911
    QSharedPointer<QLCInputSource>newSrc = QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch));
7✔
912
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerValue))
7✔
913
        min = uchar(attrs.value(KXMLQLCVCWidgetInputLowerValue).toString().toUInt());
×
914
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperValue))
7✔
915
        max = uchar(attrs.value(KXMLQLCVCWidgetInputUpperValue).toString().toUInt());
×
916
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorValue))
7✔
917
        mon = uchar(attrs.value(KXMLQLCVCWidgetInputMonitorValue).toString().toUInt());
×
918

919
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
920
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
921
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
922

923
    // load feedback extra params
924
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerParams))
7✔
925
        newSrc->setFeedbackExtraParams(QLCInputFeedback::LowerValue, attrs.value(KXMLQLCVCWidgetInputLowerParams).toInt());
×
926
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperParams))
7✔
927
        newSrc->setFeedbackExtraParams(QLCInputFeedback::UpperValue, attrs.value(KXMLQLCVCWidgetInputUpperParams).toInt());
×
928
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorParams))
7✔
929
        newSrc->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, attrs.value(KXMLQLCVCWidgetInputMonitorParams).toInt());
×
930

931
    return newSrc;
14✔
932
}
7✔
933

934
bool VCWidget::loadXMLInput(QXmlStreamReader &root, const quint8 &id)
8✔
935
{
936
    if (root.device() == NULL || root.hasError())
8✔
937
        return false;
×
938

939
    if (root.name() != KXMLQLCVCWidgetInput)
8✔
940
        return false;
1✔
941

942
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
943

944
    setInputSource(newSrc, id);
7✔
945

946
    root.skipCurrentElement();
7✔
947

948
    return true;
7✔
949
}
7✔
950

951
QString VCWidget::loadXMLSources(QXmlStreamReader &root, quint8 sourceID)
6✔
952
{
953
    QString keyText;
6✔
954
    while (root.readNextStartElement())
14✔
955
    {
956
        if (root.name() == KXMLQLCVCWidgetInput)
8✔
957
        {
958
            loadXMLInput(root, sourceID);
4✔
959
        }
960
        else if (root.name() == KXMLQLCVCWidgetKey)
4✔
961
        {
962
            keyText = root.readElementText();
4✔
963
        }
964
        else
965
        {
966
            qWarning() << Q_FUNC_INFO << "Unknown source tag" << root.name().toString();
×
967
            root.skipCurrentElement();
×
968
        }
969
    }
970
    return keyText;
6✔
971
}
×
972

973
bool VCWidget::loadXMLInput(QXmlStreamReader &root, quint32* uni, quint32* ch) const
×
974
{
975
    if (root.name() != KXMLQLCVCWidgetInput)
×
976
    {
977
        qWarning() << Q_FUNC_INFO << "Input node not found!";
×
978
        return false;
×
979
    }
980
    else
981
    {
982
        QXmlStreamAttributes attrs = root.attributes();
×
983
        *uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
×
984
        *ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
×
985
        root.skipCurrentElement();
×
986
    }
×
987

988
    return true;
×
989
}
990

991
QString VCWidget::extraParamToString(QVariant param)
36✔
992
{
993
    if (param.isValid() == false)
36✔
994
        return QString();
×
995

996
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
997
    if (param.type() == QVariant::Int && param.toInt() != -1)
998
        return QString::number(param.toInt());
999
#else
1000
    if (param.metaType().id() == QMetaType::Int && param.toInt() != -1)
36✔
1001
        return QString::number(param.toInt());
×
1002
#endif
1003
    return QString();
36✔
1004
}
1005

1006
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc)
7✔
1007
{
1008
    Q_ASSERT(doc != NULL);
7✔
1009

1010
    /* Caption */
1011
    doc->writeAttribute(KXMLQLCVCCaption, caption());
14✔
1012

1013
    /* ID */
1014
    if (id() != VCWidget::invalidId())
7✔
1015
        doc->writeAttribute(KXMLQLCVCWidgetID, QString::number(id()));
×
1016

1017
    /* Page */
1018
    if (page() != 0)
7✔
1019
        doc->writeAttribute(KXMLQLCVCWidgetPage, QString::number(page()));
×
1020

1021
    return true;
7✔
1022
}
1023

1024
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1025
{
1026
    Q_ASSERT(doc != NULL);
9✔
1027

1028
    QString str;
9✔
1029

1030
    /* VC appearance entry */
1031
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
18✔
1032

1033
    /* Frame style */
1034
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
18✔
1035

1036
    /* Foreground color */
1037
    if (hasCustomForegroundColor() == true)
9✔
1038
        str.setNum(foregroundColor().rgb());
1✔
1039
    else
1040
        str = KXMLQLCVCWidgetColorDefault;
8✔
1041
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
18✔
1042

1043
    /* Background color */
1044
    if (hasCustomBackgroundColor() == true)
9✔
1045
        str.setNum(backgroundColor().rgb());
1✔
1046
    else
1047
        str = KXMLQLCVCWidgetColorDefault;
8✔
1048
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
18✔
1049

1050
    /* Background image */
1051
    if (backgroundImage().isEmpty() == false)
9✔
1052
        str = m_doc->normalizeComponentPath(m_backgroundImage);
1✔
1053
    else
1054
        str = KXMLQLCVCWidgetBackgroundImageNone;
8✔
1055
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundImage, str);
18✔
1056

1057
    /* Font */
1058
    if (hasCustomFont() == true)
9✔
1059
        str = font().toString();
1✔
1060
    else
1061
        str = KXMLQLCVCWidgetFontDefault;
8✔
1062
    doc->writeTextElement(KXMLQLCVCWidgetFont, str);
18✔
1063

1064
    /* End the <Appearance> tag */
1065
    doc->writeEndElement();
9✔
1066

1067
    return true;
9✔
1068
}
9✔
1069

1070
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1071
{
1072
    return saveXMLInput(doc, inputSource());
4✔
1073
}
1074

1075
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1076
                            const QLCInputSource *src)
1077
{
1078
    Q_ASSERT(doc != NULL);
14✔
1079

1080
    if (src == NULL)
14✔
1081
        return false;
2✔
1082

1083
    if (src->isValid() == true)
12✔
1084
    {
1085
        doc->writeStartElement(KXMLQLCVCWidgetInput);
24✔
1086
        doc->writeAttribute(KXMLQLCVCWidgetInputUniverse, QString("%1").arg(src->universe()));
24✔
1087
        doc->writeAttribute(KXMLQLCVCWidgetInputChannel, QString("%1").arg(src->channel()));
24✔
1088
        if (src->feedbackValue(QLCInputFeedback::LowerValue) != 0)
12✔
1089
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerValue, QString::number(src->feedbackValue(QLCInputFeedback::LowerValue)));
×
1090
        if (src->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX)
12✔
1091
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperValue, QString::number(src->feedbackValue(QLCInputFeedback::UpperValue)));
×
1092
        if (src->feedbackValue(QLCInputFeedback::MonitorValue) != UCHAR_MAX)
12✔
1093
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorValue, QString::number(src->feedbackValue(QLCInputFeedback::MonitorValue)));
×
1094

1095
        // save feedback extra params
1096
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
12✔
1097

1098
        if (!extraParams.isEmpty())
12✔
1099
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1100

1101
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
12✔
1102

1103
        if (!extraParams.isEmpty())
12✔
1104
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperParams, extraParams);
×
1105

1106
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
12✔
1107

1108
        if (!extraParams.isEmpty())
12✔
1109
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorParams, extraParams);
×
1110

1111
        doc->writeEndElement();
12✔
1112
    }
12✔
1113

1114
    return true;
12✔
1115
}
1116

1117
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1118
                      QSharedPointer<QLCInputSource> const& src)
1119
{
1120
    return saveXMLInput(doc, src.data());
14✔
1121
}
1122

1123
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1124
{
1125
    Q_ASSERT(doc != NULL);
8✔
1126

1127
    /* Window state tag */
1128
    doc->writeStartElement(KXMLQLCWindowState);
16✔
1129

1130
    /* Visible status */
1131
    if (isVisible() == true)
8✔
1132
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
6✔
1133
    else
1134
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
18✔
1135

1136
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
16✔
1137
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
16✔
1138
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
16✔
1139
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
16✔
1140

1141
    doc->writeEndElement();
8✔
1142

1143
    return true;
8✔
1144
}
1145

1146
bool VCWidget::loadXMLWindowState(QXmlStreamReader &tag, int* x, int* y,
15✔
1147
                                  int* w, int* h, bool* visible)
1148
{
1149
    if (tag.device() == NULL || x == NULL || y == NULL || w == NULL || h == NULL ||
15✔
1150
            visible == NULL)
1151
        return false;
5✔
1152

1153
    if (tag.name() == KXMLQLCWindowState)
10✔
1154
    {
1155
        QXmlStreamAttributes attrs = tag.attributes();
9✔
1156
        *x = attrs.value(KXMLQLCWindowStateX).toString().toInt();
9✔
1157
        *y = attrs.value(KXMLQLCWindowStateY).toString().toInt();
9✔
1158
        *w = attrs.value(KXMLQLCWindowStateWidth).toString().toInt();
9✔
1159
        *h = attrs.value(KXMLQLCWindowStateHeight).toString().toInt();
9✔
1160

1161
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
18✔
1162
            *visible = true;
8✔
1163
        else
1164
            *visible = false;
1✔
1165
        tag.skipCurrentElement();
9✔
1166

1167
        return true;
9✔
1168
    }
9✔
1169
    else
1170
    {
1171
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1172
        return false;
1✔
1173
    }
1174
}
1175

1176
/*****************************************************************************
1177
 * QLC+ Mode change
1178
 *****************************************************************************/
1179

1180
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1181
{
1182
    if (m_doc->mode() == Doc::Design)
25✔
1183
        return;
25✔
1184

1185
    m_liveEdit = liveEdit;
×
1186

1187
    if (m_disableState)
×
1188
        setEnabled(m_liveEdit);
×
1189
    else
1190
        enableWidgetUI(!m_liveEdit);
×
1191

1192
    unsetCursor();
×
1193
    update();
×
1194
}
1195

1196
void VCWidget::cancelLiveEdit()
×
1197
{
1198
    m_liveEdit = false;
×
1199
}
×
1200

1201
void VCWidget::slotModeChanged(Doc::Mode mode)
66✔
1202
{
1203
    // make sure to exit from a 'deep' disable state
1204
    if (mode == Doc::Design)
66✔
1205
        setEnabled(true);
34✔
1206

1207
    /* Reset mouse cursor */
1208
    unsetCursor();
66✔
1209

1210
    /* Force an update to get rid of selection markers */
1211
    update();
66✔
1212
}
66✔
1213

1214
Doc::Mode VCWidget::mode() const
191✔
1215
{
1216
    Q_ASSERT(m_doc != NULL);
191✔
1217
    if (m_liveEdit)
191✔
1218
        return Doc::Design;
×
1219
    return m_doc->mode();
191✔
1220
}
1221

1222
/*****************************************************************************
1223
 * Widget menu
1224
 *****************************************************************************/
1225

1226
void VCWidget::invokeMenu(const QPoint& point)
×
1227
{
1228
    /* No point coming here if there is no VC instance */
1229
    VirtualConsole* vc = VirtualConsole::instance();
×
1230
    if (vc == NULL)
×
1231
        return;
×
1232

1233
    QMenu* menu = vc->editMenu();
×
1234
    Q_ASSERT(menu != NULL);
×
1235
    menu->exec(point);
×
1236
}
1237

1238
/*****************************************************************************
1239
 * Custom menu
1240
 *****************************************************************************/
1241

1242
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1243
{
1244
    Q_UNUSED(parentMenu);
1245
    return NULL;
3✔
1246
}
1247

1248
/*****************************************************************************
1249
 * Widget move & resize
1250
 *****************************************************************************/
1251

1252
void VCWidget::resize(const QSize& size)
244✔
1253
{
1254
    QSize sz(size);
244✔
1255

1256
    // Force grid settings
1257
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1258
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1259

1260
    // Resize
1261
    QWidget::resize(sz);
244✔
1262
}
244✔
1263

1264
void VCWidget::move(const QPoint& point)
13✔
1265
{
1266
    QPoint pt(point);
13✔
1267

1268
    // Force grid settings
1269
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1270
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1271

1272
    // Don't move beyond left or right
1273
    if (pt.x() < 0)
13✔
1274
        pt.setX(0);
1✔
1275
    else if (pt.x() + rect().width() > parentWidget()->width())
12✔
1276
        pt.setX(parentWidget()->width() - rect().width());
1✔
1277

1278
    // Don't move beyond top or bottom
1279
    if (pt.y() < 0)
13✔
1280
        pt.setY(0);
1✔
1281
    else if (pt.y() + rect().height() > parentWidget()->height())
12✔
1282
        pt.setY(parentWidget()->height() - rect().height());
1✔
1283

1284
    // Move
1285
    QWidget::move(pt);
13✔
1286

1287
    m_doc->setModified();
13✔
1288
}
13✔
1289

1290
QPoint VCWidget::lastClickPoint() const
2✔
1291
{
1292
    return m_mousePressPoint;
2✔
1293
}
1294

1295
/*****************************************************************************
1296
 * Event handlers
1297
 *****************************************************************************/
1298

1299
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1300
{
1301
    Q_UNUSED(e);
1302

1303
    /* No point coming here if there is no VC instance */
1304
    VirtualConsole* vc = VirtualConsole::instance();
32✔
1305
    if (vc == NULL)
32✔
1306
        return;
×
1307

1308
    QPainter painter(this);
32✔
1309

1310
    /* Draw frame according to style */
1311
    QStyleOptionFrame option;
32✔
1312
    option.initFrom(this);
32✔
1313

1314
    if (frameStyle() == KVCFrameStyleSunken)
32✔
1315
        option.state = QStyle::State_Sunken;
3✔
1316
    else if (frameStyle() == KVCFrameStyleRaised)
29✔
1317
        option.state = QStyle::State_Raised;
4✔
1318
    else
1319
        option.state = QStyle::State_None;
25✔
1320

1321
    if (mode() == Doc::Design)
32✔
1322
        option.state |= QStyle::State_Enabled;
28✔
1323

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

1328
    QWidget::paintEvent(e);
32✔
1329

1330
    /* Draw selection frame */
1331
    if (mode() == Doc::Design && vc->isWidgetSelected(this) == true)
32✔
1332
    {
1333
        /* Draw a dotted line around the widget */
1334
        QPen pen(Qt::DashLine);
4✔
1335
        pen.setColor(Qt::blue);
4✔
1336
        pen.setCapStyle(Qt::RoundCap);
4✔
1337
        pen.setWidth(0);
4✔
1338
        painter.setPen(pen);
4✔
1339
        painter.drawRect(0, 0, rect().width() - 1, rect().height() - 1);
4✔
1340

1341
        /* Draw a resize handle */
1342
        if (allowResize() == true)
4✔
1343
        {
1344
            QIcon icon(":/resize.png");
3✔
1345
            painter.drawPixmap(rect().width() - 16, rect().height() - 16,
3✔
1346
                               icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On));
6✔
1347
        }
3✔
1348
    }
4✔
1349
}
32✔
1350

1351
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1352
{
1353
    Q_ASSERT(e != NULL);
2✔
1354

1355
    if (mode() == Doc::Operate)
2✔
1356
    {
1357
        QWidget::mousePressEvent(e);
×
1358
        return;
×
1359
    }
1360

1361
    /* Perform widget de/selection in virtualconsole's selection buffer */
1362
    handleWidgetSelection(e);
2✔
1363

1364
    /* Resize mode */
1365
    if (m_resizeMode == true)
2✔
1366
    {
1367
        setMouseTracking(false);
×
1368
        m_resizeMode = false;
×
1369
    }
1370

1371
    /* Move, resize or context menu invocation */
1372
    if (e->button() & Qt::LeftButton || e->button() & Qt::MiddleButton)
2✔
1373
    {
1374
        /* Start moving or resizing based on where the click landed */
1375
        if (e->pos().x() > rect().width() - 10 && e->pos().y() > rect().height() - 10 && allowResize())
2✔
1376
        {
1377
            m_resizeMode = true;
×
1378
            setMouseTracking(true);
×
1379
            setCursor(QCursor(Qt::SizeFDiagCursor));
×
1380
        }
1381
        else
1382
        {
1383
            m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
2✔
1384
            setCursor(QCursor(Qt::SizeAllCursor));
2✔
1385
        }
1386
    }
1387
    else if (e->button() & Qt::RightButton)
×
1388
    {
1389
        /* Menu invocation */
1390
        m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
×
1391
        invokeMenu(mapToGlobal(e->pos()));
×
1392
    }
1393
}
1394

1395
void VCWidget::handleWidgetSelection(QMouseEvent* e)
3✔
1396
{
1397
    /* No point coming here if there is no VC */
1398
    VirtualConsole* vc = VirtualConsole::instance();
3✔
1399
    if (vc == NULL)
3✔
1400
        return;
×
1401

1402
    /* Widget selection logic (like in Qt Designer) */
1403
    if (e->button() == Qt::LeftButton)
3✔
1404
    {
1405
        if (e->modifiers() & Qt::ShiftModifier)
3✔
1406
        {
1407
            /* Toggle selection with LMB when shift is pressed */
1408
            bool selected = vc->isWidgetSelected(this);
×
1409
            vc->setWidgetSelected(this, !selected);
×
1410
        }
1411
        else
1412
        {
1413
            if (vc->isWidgetSelected(this) == false)
3✔
1414
            {
1415
                /* Select only this */
1416
                vc->clearWidgetSelection();
3✔
1417
                vc->setWidgetSelected(this, true);
3✔
1418
            }
1419
        }
1420
    }
1421
    else if (e->button() == Qt::RightButton)
×
1422
    {
1423
        if (vc->isWidgetSelected(this) == false)
×
1424
        {
1425
            /* Select only this */
1426
            vc->clearWidgetSelection();
×
1427
            vc->setWidgetSelected(this, true);
×
1428
        }
1429
    }
1430
}
1431

1432
void VCWidget::mouseReleaseEvent(QMouseEvent* e)
1✔
1433
{
1434
    if (mode() == Doc::Design)
1✔
1435
    {
1436
        unsetCursor();
1✔
1437
        m_resizeMode = false;
1✔
1438
        setMouseTracking(false);
1✔
1439
    }
1440
    else
1441
    {
1442
        QWidget::mouseReleaseEvent(e);
×
1443
    }
1444
}
1✔
1445

1446
void VCWidget::mouseDoubleClickEvent(QMouseEvent* e)
×
1447
{
1448
    if (mode() == Doc::Design)
×
1449
        editProperties();
×
1450
    else
1451
        QWidget::mouseDoubleClickEvent(e);
×
1452
}
×
1453

1454
void VCWidget::mouseMoveEvent(QMouseEvent* e)
2✔
1455
{
1456
    if (mode() == Doc::Design)
2✔
1457
    {
1458
        if (m_resizeMode == true)
2✔
1459
        {
1460
            QPoint p = mapToParent(e->pos());
×
1461
            resize(QSize(p.x() - x(), p.y() - y()));
×
1462
            m_doc->setModified();
×
1463
        }
1464
        else if (e->buttons() & Qt::LeftButton || e->buttons() & Qt::MiddleButton)
2✔
1465
        {
1466
            QPoint p = mapToParent(e->pos());
2✔
1467
            p.setX(p.x() - m_mousePressPoint.x());
2✔
1468
            p.setY(p.y() - m_mousePressPoint.y());
2✔
1469

1470
            move(p);
2✔
1471
            m_doc->setModified();
2✔
1472
        }
1473
    }
1474
    else
1475
    {
1476
        QWidget::mouseMoveEvent(e);
×
1477
    }
1478
}
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