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

mcallegari / qlcplus / 21760395819

06 Feb 2026 05:52PM UTC coverage: 33.994% (-0.08%) from 34.078%
21760395819

push

github

mcallegari
Back to 5.2.1 debug

17635 of 51877 relevant lines covered (33.99%)

19809.79 hits per line

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

73.19
/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() const
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() const
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() const
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
void VCWidget::notifyFunctionStarting(quint32 fid, qreal intensity, bool excludeMonitored)
×
511
{
512
    Q_UNUSED(fid)
513
    Q_UNUSED(intensity)
514
    Q_UNUSED(excludeMonitored)
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() const
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
436✔
689
{
690
    return m_inputs.value(id);
436✔
691
}
692

693
void VCWidget::remapInputSources(int pgNum)
×
694
{
695
    QList<quint8> ids;
×
696
    QList<QSharedPointer<QLCInputSource> > sources;
×
697
    QHash <quint8, QSharedPointer<QLCInputSource> >::const_iterator it = m_inputs.constBegin();
×
698
    for (; it != m_inputs.constEnd(); ++it)
×
699
    {
700
        ids.append(it.key());
×
701
        sources.append(it.value());
×
702
    }
703

704
    for (int i = 0; i < ids.count(); ++i)
×
705
    {
706
        const QSharedPointer<QLCInputSource>& src(sources.at(i));
×
707
        src->setPage(pgNum);
×
708
        setInputSource(src, ids.at(i));
×
709
    }
710
}
×
711

712
void VCWidget::sendFeedback(int value, quint8 id)
61✔
713
{
714
    /* Send input feedback */
715
    QSharedPointer<QLCInputSource> src = inputSource(id);
61✔
716
    sendFeedback(value, src);
61✔
717
}
61✔
718

719
void VCWidget::sendFeedback(int value, QSharedPointer<QLCInputSource> src, QVariant extraParams)
72✔
720
{
721
    if (src.isNull() || src->isValid() == false)
72✔
722
        return;
57✔
723

724
    // if in relative mode, send a "feedback" to this
725
    // input source so it can continue to emit values
726
    // from the right position
727
    if (src->needsUpdate())
15✔
728
        src->updateOuputValue(value);
×
729

730
    if (acceptsInput() == false)
15✔
731
        return;
3✔
732

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

735
    m_doc->inputOutputMap()->sendFeedBack(
24✔
736
        src->universe(), src->channel(), value,
737
        extraParams.isValid() ? extraParams : src->feedbackExtraParams(QLCInputFeedback::UpperValue));
24✔
738
}
739

740
void VCWidget::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
1✔
741
{
742
    Q_UNUSED(universe);
743
    Q_UNUSED(channel);
744
    Q_UNUSED(value);
745
}
1✔
746

747
void VCWidget::slotInputProfileChanged(quint32 universe, const QString &profileName)
×
748
{
749
    qDebug() << "[VCWdget] input profile changed" << profileName;
×
750

751
    QLCInputProfile *profile = m_doc->inputOutputMap()->profile(profileName);
×
752

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

781
/*****************************************************************************
782
 * Key sequence handler
783
 *****************************************************************************/
784

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

812
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
813
{
814
    emit keyPressed(keySequence);
1✔
815
}
1✔
816

817
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
818
{
819
    emit keyReleased(keySequence);
1✔
820
}
1✔
821

822
/*****************************************************************************
823
 * Load & Save
824
 *****************************************************************************/
825

826
void VCWidget::postLoad()
6✔
827
{
828
    /* NOP */
829
}
6✔
830

831
bool VCWidget::loadXMLCommon(QXmlStreamReader &root)
14✔
832
{
833
    if (root.device() == NULL || root.hasError())
14✔
834
        return false;
×
835

836
    QXmlStreamAttributes attrs = root.attributes();
14✔
837

838
    /* ID */
839
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
840
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
841

842
    /* Caption */
843
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
844
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
6✔
845

846
    /* Page */
847
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
848
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
849

850
    return true;
14✔
851
}
14✔
852

853
bool VCWidget::loadXMLAppearance(QXmlStreamReader &root)
9✔
854
{
855
    if (root.device() == NULL || root.hasError())
9✔
856
        return false;
×
857

858
    if (root.name() != KXMLQLCVCWidgetAppearance)
9✔
859
    {
860
        qWarning() << Q_FUNC_INFO << "Appearance node not found!";
1✔
861
        return false;
1✔
862
    }
863

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

908
    return true;
8✔
909
}
910

911
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
912
{
913
    QXmlStreamAttributes attrs = root.attributes();
7✔
914

915
    quint32 uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
7✔
916
    quint32 ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
7✔
917
    uchar min = 0, max = UCHAR_MAX, mon = UCHAR_MAX;
7✔
918

919
    QSharedPointer<QLCInputSource>newSrc = QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch));
7✔
920
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerValue))
7✔
921
        min = uchar(attrs.value(KXMLQLCVCWidgetInputLowerValue).toString().toUInt());
×
922
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperValue))
7✔
923
        max = uchar(attrs.value(KXMLQLCVCWidgetInputUpperValue).toString().toUInt());
×
924
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorValue))
7✔
925
        mon = uchar(attrs.value(KXMLQLCVCWidgetInputMonitorValue).toString().toUInt());
×
926

927
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
928
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
929
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
930

931
    // load feedback extra params
932
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerParams))
7✔
933
        newSrc->setFeedbackExtraParams(QLCInputFeedback::LowerValue, attrs.value(KXMLQLCVCWidgetInputLowerParams).toInt());
×
934
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperParams))
7✔
935
        newSrc->setFeedbackExtraParams(QLCInputFeedback::UpperValue, attrs.value(KXMLQLCVCWidgetInputUpperParams).toInt());
×
936
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorParams))
7✔
937
        newSrc->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, attrs.value(KXMLQLCVCWidgetInputMonitorParams).toInt());
×
938

939
    return newSrc;
14✔
940
}
7✔
941

942
bool VCWidget::loadXMLInput(QXmlStreamReader &root, const quint8 &id)
8✔
943
{
944
    if (root.device() == NULL || root.hasError())
8✔
945
        return false;
×
946

947
    if (root.name() != KXMLQLCVCWidgetInput)
8✔
948
        return false;
1✔
949

950
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
951

952
    setInputSource(newSrc, id);
7✔
953

954
    root.skipCurrentElement();
7✔
955

956
    return true;
7✔
957
}
7✔
958

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

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

996
    return true;
×
997
}
998

999
QString VCWidget::extraParamToString(QVariant param)
36✔
1000
{
1001
    if (param.isValid() == false)
36✔
1002
        return QString();
×
1003

1004
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1005
    if (param.type() == QVariant::Int && param.toInt() != -1)
1006
        return QString::number(param.toInt());
1007
#else
1008
    if (param.metaType().id() == QMetaType::Int && param.toInt() != -1)
36✔
1009
        return QString::number(param.toInt());
×
1010
#endif
1011
    return QString();
36✔
1012
}
1013

1014
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc) const
7✔
1015
{
1016
    Q_ASSERT(doc != NULL);
7✔
1017

1018
    /* Caption */
1019
    doc->writeAttribute(KXMLQLCVCCaption, caption());
14✔
1020

1021
    /* ID */
1022
    if (id() != VCWidget::invalidId())
7✔
1023
        doc->writeAttribute(KXMLQLCVCWidgetID, QString::number(id()));
×
1024

1025
    /* Page */
1026
    if (page() != 0)
7✔
1027
        doc->writeAttribute(KXMLQLCVCWidgetPage, QString::number(page()));
×
1028

1029
    return true;
7✔
1030
}
1031

1032
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc) const
9✔
1033
{
1034
    Q_ASSERT(doc != NULL);
9✔
1035

1036
    QString str;
9✔
1037

1038
    /* VC appearance entry */
1039
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
18✔
1040

1041
    /* Frame style */
1042
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
18✔
1043

1044
    /* Foreground color */
1045
    if (hasCustomForegroundColor() == true)
9✔
1046
        str.setNum(foregroundColor().rgb());
1✔
1047
    else
1048
        str = KXMLQLCVCWidgetColorDefault;
8✔
1049
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
18✔
1050

1051
    /* Background color */
1052
    if (hasCustomBackgroundColor() == true)
9✔
1053
        str.setNum(backgroundColor().rgb());
1✔
1054
    else
1055
        str = KXMLQLCVCWidgetColorDefault;
8✔
1056
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
18✔
1057

1058
    /* Background image */
1059
    if (backgroundImage().isEmpty() == false)
9✔
1060
        str = m_doc->normalizeComponentPath(m_backgroundImage);
1✔
1061
    else
1062
        str = KXMLQLCVCWidgetBackgroundImageNone;
8✔
1063
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundImage, str);
18✔
1064

1065
    /* Font */
1066
    if (hasCustomFont() == true)
9✔
1067
        str = font().toString();
1✔
1068
    else
1069
        str = KXMLQLCVCWidgetFontDefault;
8✔
1070
    doc->writeTextElement(KXMLQLCVCWidgetFont, str);
18✔
1071

1072
    /* End the <Appearance> tag */
1073
    doc->writeEndElement();
9✔
1074

1075
    return true;
9✔
1076
}
9✔
1077

1078
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc) const
4✔
1079
{
1080
    return saveXMLInput(doc, inputSource());
4✔
1081
}
1082

1083
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1084
                            const QLCInputSource *src)
1085
{
1086
    Q_ASSERT(doc != NULL);
14✔
1087

1088
    if (src == NULL)
14✔
1089
        return false;
2✔
1090

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

1103
        // save feedback extra params
1104
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
12✔
1105

1106
        if (!extraParams.isEmpty())
12✔
1107
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1108

1109
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
12✔
1110

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

1114
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
12✔
1115

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

1119
        doc->writeEndElement();
12✔
1120
    }
12✔
1121

1122
    return true;
12✔
1123
}
1124

1125
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1126
                      QSharedPointer<QLCInputSource> const& src)
1127
{
1128
    return saveXMLInput(doc, src.data());
14✔
1129
}
1130

1131
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc) const
8✔
1132
{
1133
    Q_ASSERT(doc != NULL);
8✔
1134

1135
    /* Window state tag */
1136
    doc->writeStartElement(KXMLQLCWindowState);
16✔
1137

1138
    /* Visible status */
1139
    if (isVisible() == true)
8✔
1140
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
6✔
1141
    else
1142
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
18✔
1143

1144
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
16✔
1145
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
16✔
1146
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
16✔
1147
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
16✔
1148

1149
    doc->writeEndElement();
8✔
1150

1151
    return true;
8✔
1152
}
1153

1154
bool VCWidget::loadXMLWindowState(QXmlStreamReader &tag, int* x, int* y,
15✔
1155
                                  int* w, int* h, bool* visible)
1156
{
1157
    if (tag.device() == NULL || x == NULL || y == NULL || w == NULL || h == NULL ||
15✔
1158
            visible == NULL)
1159
        return false;
5✔
1160

1161
    if (tag.name() == KXMLQLCWindowState)
10✔
1162
    {
1163
        QXmlStreamAttributes attrs = tag.attributes();
9✔
1164
        *x = attrs.value(KXMLQLCWindowStateX).toString().toInt();
9✔
1165
        *y = attrs.value(KXMLQLCWindowStateY).toString().toInt();
9✔
1166
        *w = attrs.value(KXMLQLCWindowStateWidth).toString().toInt();
9✔
1167
        *h = attrs.value(KXMLQLCWindowStateHeight).toString().toInt();
9✔
1168

1169
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
18✔
1170
            *visible = true;
8✔
1171
        else
1172
            *visible = false;
1✔
1173
        tag.skipCurrentElement();
9✔
1174

1175
        return true;
9✔
1176
    }
9✔
1177
    else
1178
    {
1179
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1180
        return false;
1✔
1181
    }
1182
}
1183

1184
/*****************************************************************************
1185
 * QLC+ Mode change
1186
 *****************************************************************************/
1187

1188
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1189
{
1190
    if (m_doc->mode() == Doc::Design)
25✔
1191
        return;
25✔
1192

1193
    m_liveEdit = liveEdit;
×
1194

1195
    if (m_disableState)
×
1196
        setEnabled(m_liveEdit);
×
1197
    else
1198
        enableWidgetUI(!m_liveEdit);
×
1199

1200
    unsetCursor();
×
1201
    update();
×
1202
}
1203

1204
void VCWidget::cancelLiveEdit()
×
1205
{
1206
    m_liveEdit = false;
×
1207
}
×
1208

1209
void VCWidget::slotModeChanged(Doc::Mode mode)
66✔
1210
{
1211
    // make sure to exit from a 'deep' disable state
1212
    if (mode == Doc::Design)
66✔
1213
        setEnabled(true);
34✔
1214

1215
    /* Reset mouse cursor */
1216
    unsetCursor();
66✔
1217

1218
    /* Force an update to get rid of selection markers */
1219
    update();
66✔
1220
}
66✔
1221

1222
Doc::Mode VCWidget::mode() const
191✔
1223
{
1224
    Q_ASSERT(m_doc != NULL);
191✔
1225
    if (m_liveEdit)
191✔
1226
        return Doc::Design;
×
1227
    return m_doc->mode();
191✔
1228
}
1229

1230
/*****************************************************************************
1231
 * Widget menu
1232
 *****************************************************************************/
1233

1234
void VCWidget::invokeMenu(const QPoint& point)
×
1235
{
1236
    /* No point coming here if there is no VC instance */
1237
    VirtualConsole* vc = VirtualConsole::instance();
×
1238
    if (vc == NULL)
×
1239
        return;
×
1240

1241
    QMenu* menu = vc->editMenu();
×
1242
    Q_ASSERT(menu != NULL);
×
1243
    menu->exec(point);
×
1244
}
1245

1246
/*****************************************************************************
1247
 * Custom menu
1248
 *****************************************************************************/
1249

1250
QMenu* VCWidget::customMenu(QMenu* parentMenu) const
3✔
1251
{
1252
    Q_UNUSED(parentMenu);
1253
    return NULL;
3✔
1254
}
1255

1256
/*****************************************************************************
1257
 * Widget move & resize
1258
 *****************************************************************************/
1259

1260
void VCWidget::resize(const QSize& size)
244✔
1261
{
1262
    QSize sz(size);
244✔
1263

1264
    // Force grid settings
1265
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1266
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1267

1268
    // Resize
1269
    QWidget::resize(sz);
244✔
1270
}
244✔
1271

1272
void VCWidget::move(const QPoint& point)
13✔
1273
{
1274
    QPoint pt(point);
13✔
1275

1276
    // Force grid settings
1277
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1278
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1279

1280
    // Don't move beyond left or right
1281
    if (pt.x() < 0)
13✔
1282
        pt.setX(0);
1✔
1283
    else if (pt.x() + rect().width() > parentWidget()->width())
12✔
1284
        pt.setX(parentWidget()->width() - rect().width());
1✔
1285

1286
    // Don't move beyond top or bottom
1287
    if (pt.y() < 0)
13✔
1288
        pt.setY(0);
1✔
1289
    else if (pt.y() + rect().height() > parentWidget()->height())
12✔
1290
        pt.setY(parentWidget()->height() - rect().height());
1✔
1291

1292
    // Move
1293
    QWidget::move(pt);
13✔
1294

1295
    m_doc->setModified();
13✔
1296
}
13✔
1297

1298
QPoint VCWidget::lastClickPoint() const
2✔
1299
{
1300
    return m_mousePressPoint;
2✔
1301
}
1302

1303
/*****************************************************************************
1304
 * Event handlers
1305
 *****************************************************************************/
1306

1307
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1308
{
1309
    Q_UNUSED(e);
1310

1311
    /* No point coming here if there is no VC instance */
1312
    VirtualConsole* vc = VirtualConsole::instance();
32✔
1313
    if (vc == NULL)
32✔
1314
        return;
×
1315

1316
    QPainter painter(this);
32✔
1317

1318
    /* Draw frame according to style */
1319
    QStyleOptionFrame option;
32✔
1320
    option.initFrom(this);
32✔
1321

1322
    if (frameStyle() == KVCFrameStyleSunken)
32✔
1323
        option.state = QStyle::State_Sunken;
3✔
1324
    else if (frameStyle() == KVCFrameStyleRaised)
29✔
1325
        option.state = QStyle::State_Raised;
4✔
1326
    else
1327
        option.state = QStyle::State_None;
25✔
1328

1329
    if (mode() == Doc::Design)
32✔
1330
        option.state |= QStyle::State_Enabled;
28✔
1331

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

1336
    QWidget::paintEvent(e);
32✔
1337

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

1349
        /* Draw a resize handle */
1350
        if (allowResize() == true)
4✔
1351
        {
1352
            QIcon icon(":/resize.png");
3✔
1353
            painter.drawPixmap(rect().width() - 16, rect().height() - 16,
3✔
1354
                               icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On));
6✔
1355
        }
3✔
1356
    }
4✔
1357
}
32✔
1358

1359
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1360
{
1361
    Q_ASSERT(e != NULL);
2✔
1362

1363
    if (mode() == Doc::Operate)
2✔
1364
    {
1365
        QWidget::mousePressEvent(e);
×
1366
        return;
×
1367
    }
1368

1369
    /* Perform widget de/selection in virtualconsole's selection buffer */
1370
    handleWidgetSelection(e);
2✔
1371

1372
    /* Resize mode */
1373
    if (m_resizeMode == true)
2✔
1374
    {
1375
        setMouseTracking(false);
×
1376
        m_resizeMode = false;
×
1377
    }
1378

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

1403
void VCWidget::handleWidgetSelection(QMouseEvent* e)
3✔
1404
{
1405
    /* No point coming here if there is no VC */
1406
    VirtualConsole* vc = VirtualConsole::instance();
3✔
1407
    if (vc == NULL)
3✔
1408
        return;
×
1409

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

1440
void VCWidget::mouseReleaseEvent(QMouseEvent* e)
1✔
1441
{
1442
    if (mode() == Doc::Design)
1✔
1443
    {
1444
        unsetCursor();
1✔
1445
        m_resizeMode = false;
1✔
1446
        setMouseTracking(false);
1✔
1447
    }
1448
    else
1449
    {
1450
        QWidget::mouseReleaseEvent(e);
×
1451
    }
1452
}
1✔
1453

1454
void VCWidget::mouseDoubleClickEvent(QMouseEvent* e)
×
1455
{
1456
    if (mode() == Doc::Design)
×
1457
        editProperties();
×
1458
    else
1459
        QWidget::mouseDoubleClickEvent(e);
×
1460
}
×
1461

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

1478
            move(p);
2✔
1479
            m_doc->setModified();
2✔
1480
        }
1481
    }
1482
    else
1483
    {
1484
        QWidget::mouseMoveEvent(e);
×
1485
    }
1486
}
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