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

mcallegari / qlcplus / 8103290030

29 Feb 2024 10:11PM UTC coverage: 32.036% (+0.05%) from 31.988%
8103290030

push

github

mcallegari
qmlui: fix to build with latest changes

15332 of 47859 relevant lines covered (32.04%)

23585.55 hits per line

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

73.6
/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)
58
    , m_id(invalidId())
354✔
59
    , m_disableState(false)
60
    , m_page(0)
61
    , m_allowChildren(false)
62
    , m_allowResize(true)
63
    , m_intensityOverrideId(Function::invalidAttributeId())
354✔
64
    , m_intensity(1.0)
65
    , m_liveEdit(VirtualConsole::instance()->liveEdit())
177✔
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()
186✔
119
{
120
    return UINT_MAX;
186✔
121
}
122

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

245
    m_frameStyle = widget->m_frameStyle;
8✔
246

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

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

253
    QHashIterator <quint8, QSharedPointer<QLCInputSource> > it(widget->m_inputs);
8✔
254
    while (it.hasNext() == true)
11✔
255
    {
256
        it.next();
3✔
257
        quint8 id = it.key();
3✔
258
        QSharedPointer<QLCInputSource> src(new QLCInputSource(it.value()->universe(), it.value()->channel()));
6✔
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
    }
267

268
    m_page = widget->m_page;
8✔
269

270
    return true;
8✔
271
}
272

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

277
void VCWidget::setBackgroundImage(const QString& path)
14✔
278
{
279
    QPalette pal = palette();
28✔
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();
22✔
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();
4✔
342
        pal.setColor(QPalette::WindowText, fg);
2✔
343
        setPalette(pal);
2✔
344
    }
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();
14✔
356

357
    m_hasCustomForegroundColor = true;
7✔
358

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

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

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

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

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

379
    m_hasCustomForegroundColor = false;
4✔
380

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

561
    return true;
56✔
562
}
563

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

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

585
    return false;
19✔
586
}
587

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

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

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

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

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

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

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

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

685
void VCWidget::remapInputSources(int pgNum)
×
686
{
687
    foreach (quint8 s, m_inputs.keys())
×
688
    {
689
        QSharedPointer<QLCInputSource> src(m_inputs.value(s));
×
690
        src->setPage(pgNum);
×
691
        setInputSource(src, s);
×
692
    }
693
}
×
694

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

702
void VCWidget::sendFeedback(int value, QSharedPointer<QLCInputSource> src, QVariant extraParams)
70✔
703
{
704
    if (src.isNull() || src->isValid() == false)
70✔
705
        return;
55✔
706

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

713
    if (acceptsInput() == false)
15✔
714
        return;
3✔
715

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

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

723
void VCWidget::slotInputValueChanged(quint32 universe, quint32 channel, uchar value)
1✔
724
{
725
    Q_UNUSED(universe);
726
    Q_UNUSED(channel);
727
    Q_UNUSED(value);
728
}
1✔
729

730
void VCWidget::slotInputProfileChanged(quint32 universe, const QString &profileName)
×
731
{
732
    qDebug() << "[VCWdget] input profile changed" << profileName;
×
733

734
    QLCInputProfile *profile = m_doc->inputOutputMap()->profile(profileName);
×
735

736
    foreach (QSharedPointer<QLCInputSource> const& source, m_inputs.values())
×
737
    {
738
        if (!source.isNull() && source->universe() == universe)
×
739
        {
740
            // if the profile has been unset, reset all the valid
741
            // input sources to work in absolute mode
742
            if (profile == NULL)
×
743
            {
744
                source->setWorkingMode(QLCInputSource::Absolute);
×
745
            }
746
            else
747
            {
748
                QLCInputChannel *ich = profile->channel(source->channel());
×
749
                if (ich != NULL)
×
750
                {
751
                    if (ich->movementType() == QLCInputChannel::Absolute)
×
752
                        source->setWorkingMode(QLCInputSource::Absolute);
×
753
                    else
754
                    {
755
                        source->setWorkingMode(QLCInputSource::Relative);
×
756
                        source->setSensitivity(ich->movementSensitivity());
×
757
                    }
758
                }
759
            }
760
        }
761
    }
762
}
×
763

764
/*****************************************************************************
765
 * Key sequence handler
766
 *****************************************************************************/
767

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

794
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
795
{
796
    emit keyPressed(keySequence);
1✔
797
}
1✔
798

799
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
800
{
801
    emit keyReleased(keySequence);
1✔
802
}
1✔
803

804
/*****************************************************************************
805
 * Load & Save
806
 *****************************************************************************/
807

808
void VCWidget::postLoad()
6✔
809
{
810
    /* NOP */
811
}
6✔
812

813
bool VCWidget::loadXMLCommon(QXmlStreamReader &root)
14✔
814
{
815
    if (root.device() == NULL || root.hasError())
14✔
816
        return false;
×
817

818
    QXmlStreamAttributes attrs = root.attributes();
14✔
819

820
    /* ID */
821
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
822
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
823

824
    /* Caption */
825
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
826
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
3✔
827

828
    /* Page */
829
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
830
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
831

832
    return true;
14✔
833
}
834

835
bool VCWidget::loadXMLAppearance(QXmlStreamReader &root)
9✔
836
{
837
    if (root.device() == NULL || root.hasError())
9✔
838
        return false;
×
839

840
    if (root.name() != KXMLQLCVCWidgetAppearance)
9✔
841
    {
842
        qWarning() << Q_FUNC_INFO << "Appearance node not found!";
1✔
843
        return false;
1✔
844
    }
845

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

890
    return true;
8✔
891
}
892

893
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
894
{
895
    QXmlStreamAttributes attrs = root.attributes();
14✔
896

897
    quint32 uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
7✔
898
    quint32 ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
7✔
899
    uchar min = 0, max = UCHAR_MAX, mon = UCHAR_MAX;
7✔
900

901
    QSharedPointer<QLCInputSource>newSrc = QSharedPointer<QLCInputSource>(new QLCInputSource(uni, ch));
7✔
902
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerValue))
7✔
903
        min = uchar(attrs.value(KXMLQLCVCWidgetInputLowerValue).toString().toUInt());
×
904
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperValue))
7✔
905
        max = uchar(attrs.value(KXMLQLCVCWidgetInputUpperValue).toString().toUInt());
×
906
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorValue))
7✔
907
        mon = uchar(attrs.value(KXMLQLCVCWidgetInputMonitorValue).toString().toUInt());
×
908

909
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
910
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
911
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
912

913
    // load feedback extra params
914
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputLowerParams))
7✔
915
        newSrc->setFeedbackExtraParams(QLCInputFeedback::LowerValue, attrs.value(KXMLQLCVCWidgetInputLowerParams).toInt());
×
916
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputUpperParams))
7✔
917
        newSrc->setFeedbackExtraParams(QLCInputFeedback::UpperValue, attrs.value(KXMLQLCVCWidgetInputUpperParams).toInt());
×
918
    if (attrs.hasAttribute(KXMLQLCVCWidgetInputMonitorParams))
7✔
919
        newSrc->setFeedbackExtraParams(QLCInputFeedback::MonitorValue, attrs.value(KXMLQLCVCWidgetInputMonitorParams).toInt());
×
920

921
    return newSrc;
14✔
922
}
923

924
bool VCWidget::loadXMLInput(QXmlStreamReader &root, const quint8 &id)
8✔
925
{
926
    if (root.device() == NULL || root.hasError())
8✔
927
        return false;
×
928

929
    if (root.name() != KXMLQLCVCWidgetInput)
8✔
930
        return false;
1✔
931

932
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
933

934
    setInputSource(newSrc, id);
7✔
935

936
    root.skipCurrentElement();
7✔
937

938
    return true;
7✔
939
}
940

941
QString VCWidget::loadXMLSources(QXmlStreamReader &root, quint8 sourceID)
6✔
942
{
943
    QString keyText;
6✔
944
    while (root.readNextStartElement())
14✔
945
    {
946
        if (root.name() == KXMLQLCVCWidgetInput)
8✔
947
        {
948
            loadXMLInput(root, sourceID);
4✔
949
        }
950
        else if (root.name() == KXMLQLCVCWidgetKey)
4✔
951
        {
952
            keyText = root.readElementText();
4✔
953
        }
954
        else
955
        {
956
            qWarning() << Q_FUNC_INFO << "Unknown source tag" << root.name().toString();
×
957
            root.skipCurrentElement();
×
958
        }
959
    }
960
    return keyText;
6✔
961
}
962

963
bool VCWidget::loadXMLInput(QXmlStreamReader &root, quint32* uni, quint32* ch) const
×
964
{
965
    if (root.name() != KXMLQLCVCWidgetInput)
×
966
    {
967
        qWarning() << Q_FUNC_INFO << "Input node not found!";
×
968
        return false;
×
969
    }
970
    else
971
    {
972
        QXmlStreamAttributes attrs = root.attributes();
×
973
        *uni = attrs.value(KXMLQLCVCWidgetInputUniverse).toString().toUInt();
×
974
        *ch = attrs.value(KXMLQLCVCWidgetInputChannel).toString().toUInt();
×
975
        root.skipCurrentElement();
×
976
    }
977

978
    return true;
×
979
}
980

981
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc)
7✔
982
{
983
    Q_ASSERT(doc != NULL);
7✔
984

985
    /* Caption */
986
    doc->writeAttribute(KXMLQLCVCCaption, caption());
7✔
987

988
    /* ID */
989
    if (id() != VCWidget::invalidId())
7✔
990
        doc->writeAttribute(KXMLQLCVCWidgetID, QString::number(id()));
×
991

992
    /* Page */
993
    if (page() != 0)
7✔
994
        doc->writeAttribute(KXMLQLCVCWidgetPage, QString::number(page()));
×
995

996
    return true;
7✔
997
}
998

999
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1000
{
1001
    Q_ASSERT(doc != NULL);
9✔
1002

1003
    QString str;
9✔
1004

1005
    /* VC appearance entry */
1006
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
9✔
1007

1008
    /* Frame style */
1009
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
9✔
1010

1011
    /* Foreground color */
1012
    if (hasCustomForegroundColor() == true)
9✔
1013
        str.setNum(foregroundColor().rgb());
1✔
1014
    else
1015
        str = KXMLQLCVCWidgetColorDefault;
8✔
1016
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
9✔
1017

1018
    /* Background color */
1019
    if (hasCustomBackgroundColor() == true)
9✔
1020
        str.setNum(backgroundColor().rgb());
1✔
1021
    else
1022
        str = KXMLQLCVCWidgetColorDefault;
8✔
1023
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
9✔
1024

1025
    /* Background image */
1026
    if (backgroundImage().isEmpty() == false)
9✔
1027
        str = m_doc->normalizeComponentPath(m_backgroundImage);
1✔
1028
    else
1029
        str = KXMLQLCVCWidgetBackgroundImageNone;
8✔
1030
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundImage, str);
9✔
1031

1032
    /* Font */
1033
    if (hasCustomFont() == true)
9✔
1034
        str = font().toString();
1✔
1035
    else
1036
        str = KXMLQLCVCWidgetFontDefault;
8✔
1037
    doc->writeTextElement(KXMLQLCVCWidgetFont, str);
9✔
1038

1039
    /* End the <Appearance> tag */
1040
    doc->writeEndElement();
9✔
1041

1042
    return true;
18✔
1043
}
1044

1045
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1046
{
1047
    return saveXMLInput(doc, inputSource());
4✔
1048
}
1049

1050
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
12✔
1051
                            const QLCInputSource *src)
1052
{
1053
    Q_ASSERT(doc != NULL);
12✔
1054

1055
    if (src == NULL)
12✔
1056
        return false;
2✔
1057

1058
    if (src->isValid() == true)
10✔
1059
    {
1060
        doc->writeStartElement(KXMLQLCVCWidgetInput);
10✔
1061
        doc->writeAttribute(KXMLQLCVCWidgetInputUniverse, QString("%1").arg(src->universe()));
10✔
1062
        doc->writeAttribute(KXMLQLCVCWidgetInputChannel, QString("%1").arg(src->channel()));
10✔
1063
        if (src->feedbackValue(QLCInputFeedback::LowerValue) != 0)
10✔
1064
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerValue, QString::number(src->feedbackValue(QLCInputFeedback::LowerValue)));
×
1065
        if (src->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX)
10✔
1066
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperValue, QString::number(src->feedbackValue(QLCInputFeedback::UpperValue)));
×
1067
        if (src->feedbackValue(QLCInputFeedback::MonitorValue) != UCHAR_MAX)
10✔
1068
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorValue, QString::number(src->feedbackValue(QLCInputFeedback::MonitorValue)));
×
1069

1070
        // save feedback extra params
1071
        QVariant extraParams = src->feedbackExtraParams(QLCInputFeedback::LowerValue);
20✔
1072

1073
        if (extraParams.isValid() && extraParams.type() == QVariant::Int && extraParams.toInt() != -1)
10✔
1074
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, QString::number(extraParams.toInt()));
×
1075

1076
        extraParams = src->feedbackExtraParams(QLCInputFeedback::UpperValue);
10✔
1077

1078
        if (extraParams.isValid() && extraParams.type() == QVariant::Int && extraParams.toInt() != -1)
10✔
1079
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperParams, QString::number(extraParams.toInt()));
×
1080

1081
        extraParams = src->feedbackExtraParams(QLCInputFeedback::MonitorValue);
10✔
1082

1083
        if (extraParams.isValid() && extraParams.type() == QVariant::Int && extraParams.toInt() != -1)
10✔
1084
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorParams, QString::number(extraParams.toInt()));
×
1085

1086
        doc->writeEndElement();
10✔
1087
    }
1088

1089
    return true;
10✔
1090
}
1091

1092
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
12✔
1093
                      QSharedPointer<QLCInputSource> const& src)
1094
{
1095
    return saveXMLInput(doc, src.data());
12✔
1096
}
1097

1098
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1099
{
1100
    Q_ASSERT(doc != NULL);
8✔
1101

1102
    /* Window state tag */
1103
    doc->writeStartElement(KXMLQLCWindowState);
8✔
1104

1105
    /* Visible status */
1106
    if (isVisible() == true)
8✔
1107
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
2✔
1108
    else
1109
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
6✔
1110

1111
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
8✔
1112
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
8✔
1113
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
8✔
1114
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
8✔
1115

1116
    doc->writeEndElement();
8✔
1117

1118
    return true;
8✔
1119
}
1120

1121
bool VCWidget::loadXMLWindowState(QXmlStreamReader &tag, int* x, int* y,
15✔
1122
                                  int* w, int* h, bool* visible)
1123
{
1124
    if (tag.device() == NULL || x == NULL || y == NULL || w == NULL || h == NULL ||
15✔
1125
            visible == NULL)
1126
        return false;
5✔
1127

1128
    if (tag.name() == KXMLQLCWindowState)
10✔
1129
    {
1130
        QXmlStreamAttributes attrs = tag.attributes();
9✔
1131
        *x = attrs.value(KXMLQLCWindowStateX).toString().toInt();
9✔
1132
        *y = attrs.value(KXMLQLCWindowStateY).toString().toInt();
9✔
1133
        *w = attrs.value(KXMLQLCWindowStateWidth).toString().toInt();
9✔
1134
        *h = attrs.value(KXMLQLCWindowStateHeight).toString().toInt();
9✔
1135

1136
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
9✔
1137
            *visible = true;
8✔
1138
        else
1139
            *visible = false;
1✔
1140
        tag.skipCurrentElement();
9✔
1141

1142
        return true;
9✔
1143
    }
1144
    else
1145
    {
1146
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1147
        return false;
1✔
1148
    }
1149
}
1150

1151
/*****************************************************************************
1152
 * QLC+ Mode change
1153
 *****************************************************************************/
1154

1155
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1156
{
1157
    if (m_doc->mode() == Doc::Design)
25✔
1158
        return;
25✔
1159

1160
    m_liveEdit = liveEdit;
×
1161

1162
    if (m_disableState)
×
1163
        setEnabled(m_liveEdit);
×
1164
    else
1165
        enableWidgetUI(!m_liveEdit);
×
1166

1167
    unsetCursor();
×
1168
    update();
×
1169
}
1170

1171
void VCWidget::cancelLiveEdit()
×
1172
{
1173
    m_liveEdit = false;
×
1174
}
×
1175

1176
void VCWidget::slotModeChanged(Doc::Mode mode)
66✔
1177
{
1178
    // make sure to exit from a 'deep' disable state
1179
    if (mode == Doc::Design)
66✔
1180
        setEnabled(true);
34✔
1181

1182
    /* Reset mouse cursor */
1183
    unsetCursor();
66✔
1184

1185
    /* Force an update to get rid of selection markers */
1186
    update();
66✔
1187
}
66✔
1188

1189
Doc::Mode VCWidget::mode() const
191✔
1190
{
1191
    Q_ASSERT(m_doc != NULL);
191✔
1192
    if (m_liveEdit)
191✔
1193
        return Doc::Design;
×
1194
    return m_doc->mode();
191✔
1195
}
1196

1197
/*****************************************************************************
1198
 * Widget menu
1199
 *****************************************************************************/
1200

1201
void VCWidget::invokeMenu(const QPoint& point)
×
1202
{
1203
    /* No point coming here if there is no VC instance */
1204
    VirtualConsole* vc = VirtualConsole::instance();
×
1205
    if (vc == NULL)
×
1206
        return;
×
1207

1208
    QMenu* menu = vc->editMenu();
×
1209
    Q_ASSERT(menu != NULL);
×
1210
    menu->exec(point);
×
1211
}
1212

1213
/*****************************************************************************
1214
 * Custom menu
1215
 *****************************************************************************/
1216

1217
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1218
{
1219
    Q_UNUSED(parentMenu);
1220
    return NULL;
3✔
1221
}
1222

1223
/*****************************************************************************
1224
 * Widget move & resize
1225
 *****************************************************************************/
1226

1227
void VCWidget::resize(const QSize& size)
244✔
1228
{
1229
    QSize sz(size);
244✔
1230

1231
    // Force grid settings
1232
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1233
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1234

1235
    // Resize
1236
    QWidget::resize(sz);
244✔
1237
}
244✔
1238

1239
void VCWidget::move(const QPoint& point)
13✔
1240
{
1241
    QPoint pt(point);
13✔
1242

1243
    // Force grid settings
1244
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1245
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1246

1247
    // Don't move beyond left or right
1248
    if (pt.x() < 0)
13✔
1249
        pt.setX(0);
1✔
1250
    else if (pt.x() + rect().width() > parentWidget()->width())
12✔
1251
        pt.setX(parentWidget()->width() - rect().width());
1✔
1252

1253
    // Don't move beyond top or bottom
1254
    if (pt.y() < 0)
13✔
1255
        pt.setY(0);
1✔
1256
    else if (pt.y() + rect().height() > parentWidget()->height())
12✔
1257
        pt.setY(parentWidget()->height() - rect().height());
1✔
1258

1259
    // Move
1260
    QWidget::move(pt);
13✔
1261

1262
    m_doc->setModified();
13✔
1263
}
13✔
1264

1265
QPoint VCWidget::lastClickPoint() const
2✔
1266
{
1267
    return m_mousePressPoint;
2✔
1268
}
1269

1270
/*****************************************************************************
1271
 * Event handlers
1272
 *****************************************************************************/
1273

1274
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1275
{
1276
    Q_UNUSED(e);
1277

1278
    /* No point coming here if there is no VC instance */
1279
    VirtualConsole* vc = VirtualConsole::instance();
32✔
1280
    if (vc == NULL)
32✔
1281
        return;
×
1282

1283
    QPainter painter(this);
64✔
1284

1285
    /* Draw frame according to style */
1286
    QStyleOptionFrame option;
64✔
1287
    option.initFrom(this);
32✔
1288

1289
    if (frameStyle() == KVCFrameStyleSunken)
32✔
1290
        option.state = QStyle::State_Sunken;
3✔
1291
    else if (frameStyle() == KVCFrameStyleRaised)
29✔
1292
        option.state = QStyle::State_Raised;
4✔
1293
    else
1294
        option.state = QStyle::State_None;
25✔
1295

1296
    if (mode() == Doc::Design)
32✔
1297
        option.state |= QStyle::State_Enabled;
28✔
1298

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

1303
    QWidget::paintEvent(e);
32✔
1304

1305
    /* Draw selection frame */
1306
    if (mode() == Doc::Design && vc->isWidgetSelected(this) == true)
32✔
1307
    {
1308
        /* Draw a dotted line around the widget */
1309
        QPen pen(Qt::DashLine);
8✔
1310
        pen.setColor(Qt::blue);
4✔
1311
        pen.setCapStyle(Qt::RoundCap);
4✔
1312
        pen.setWidth(0);
4✔
1313
        painter.setPen(pen);
4✔
1314
        painter.drawRect(0, 0, rect().width() - 1, rect().height() - 1);
4✔
1315

1316
        /* Draw a resize handle */
1317
        if (allowResize() == true)
4✔
1318
        {
1319
            QIcon icon(":/resize.png");
3✔
1320
            painter.drawPixmap(rect().width() - 16, rect().height() - 16,
3✔
1321
                               icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On));
6✔
1322
        }
1323
    }
1324
}
1325

1326
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1327
{
1328
    Q_ASSERT(e != NULL);
2✔
1329

1330
    if (mode() == Doc::Operate)
2✔
1331
    {
1332
        QWidget::mousePressEvent(e);
×
1333
        return;
×
1334
    }
1335

1336
    /* Perform widget de/selection in virtualconsole's selection buffer */
1337
    handleWidgetSelection(e);
2✔
1338

1339
    /* Resize mode */
1340
    if (m_resizeMode == true)
2✔
1341
    {
1342
        setMouseTracking(false);
×
1343
        m_resizeMode = false;
×
1344
    }
1345

1346
    /* Move, resize or context menu invocation */
1347
    if (e->button() & Qt::LeftButton || e->button() & Qt::MiddleButton)
2✔
1348
    {
1349
        /* Start moving or resizing based on where the click landed */
1350
        if (e->pos().x() > rect().width() - 10 && e->pos().y() > rect().height() - 10 && allowResize())
2✔
1351
        {
1352
            m_resizeMode = true;
×
1353
            setMouseTracking(true);
×
1354
            setCursor(QCursor(Qt::SizeFDiagCursor));
×
1355
        }
1356
        else
1357
        {
1358
            m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
2✔
1359
            setCursor(QCursor(Qt::SizeAllCursor));
2✔
1360
        }
1361
    }
1362
    else if (e->button() & Qt::RightButton)
×
1363
    {
1364
        /* Menu invocation */
1365
        m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
×
1366
        invokeMenu(mapToGlobal(e->pos()));
×
1367
    }
1368
}
1369

1370
void VCWidget::handleWidgetSelection(QMouseEvent* e)
3✔
1371
{
1372
    /* No point coming here if there is no VC */
1373
    VirtualConsole* vc = VirtualConsole::instance();
3✔
1374
    if (vc == NULL)
3✔
1375
        return;
×
1376

1377
    /* Widget selection logic (like in Qt Designer) */
1378
    if (e->button() == Qt::LeftButton)
3✔
1379
    {
1380
        if (e->modifiers() & Qt::ShiftModifier)
3✔
1381
        {
1382
            /* Toggle selection with LMB when shift is pressed */
1383
            bool selected = vc->isWidgetSelected(this);
×
1384
            vc->setWidgetSelected(this, !selected);
×
1385
        }
1386
        else
1387
        {
1388
            if (vc->isWidgetSelected(this) == false)
3✔
1389
            {
1390
                /* Select only this */
1391
                vc->clearWidgetSelection();
3✔
1392
                vc->setWidgetSelected(this, true);
3✔
1393
            }
1394
        }
1395
    }
1396
    else if (e->button() == Qt::RightButton)
×
1397
    {
1398
        if (vc->isWidgetSelected(this) == false)
×
1399
        {
1400
            /* Select only this */
1401
            vc->clearWidgetSelection();
×
1402
            vc->setWidgetSelected(this, true);
×
1403
        }
1404
    }
1405
}
1406

1407
void VCWidget::mouseReleaseEvent(QMouseEvent* e)
1✔
1408
{
1409
    if (mode() == Doc::Design)
1✔
1410
    {
1411
        unsetCursor();
1✔
1412
        m_resizeMode = false;
1✔
1413
        setMouseTracking(false);
1✔
1414
    }
1415
    else
1416
    {
1417
        QWidget::mouseReleaseEvent(e);
×
1418
    }
1419
}
1✔
1420

1421
void VCWidget::mouseDoubleClickEvent(QMouseEvent* e)
×
1422
{
1423
    if (mode() == Doc::Design)
×
1424
        editProperties();
×
1425
    else
1426
        QWidget::mouseDoubleClickEvent(e);
×
1427
}
×
1428

1429
void VCWidget::mouseMoveEvent(QMouseEvent* e)
2✔
1430
{
1431
    if (mode() == Doc::Design)
2✔
1432
    {
1433
        if (m_resizeMode == true)
2✔
1434
        {
1435
            QPoint p = mapToParent(e->pos());
×
1436
            resize(QSize(p.x() - x(), p.y() - y()));
×
1437
            m_doc->setModified();
×
1438
        }
1439
        else if (e->buttons() & Qt::LeftButton || e->buttons() & Qt::MiddleButton)
2✔
1440
        {
1441
            QPoint p = mapToParent(e->pos());
2✔
1442
            p.setX(p.x() - m_mousePressPoint.x());
2✔
1443
            p.setY(p.y() - m_mousePressPoint.y());
2✔
1444

1445
            move(p);
2✔
1446
            m_doc->setModified();
2✔
1447
        }
1448
    }
1449
    else
1450
    {
1451
        QWidget::mouseMoveEvent(e);
×
1452
    }
1453
}
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