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

mcallegari / qlcplus / 8613265809

09 Apr 2024 09:13AM UTC coverage: 32.08% (-0.004%) from 32.084%
8613265809

push

github

mcallegari
Fix build with Qt 6.7

9 of 16 new or added lines in 2 files covered. (56.25%)

5 existing lines in 2 files now uncovered.

15389 of 47971 relevant lines covered (32.08%)

22931.4 hits per line

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

73.39
/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 feedback
624
                    if (source->feedbackExtraParams(QLCInputFeedback::LowerValue).toInt() == -1)
×
625
                        source->setFeedbackExtraParams(QLCInputFeedback::LowerValue, profile->channelExtraParams(ich));
×
626
                    if (source->feedbackExtraParams(QLCInputFeedback::UpperValue).toInt() == -1)
×
627
                        source->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 feedback have precedence over input profile custom feedback
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
QString VCWidget::extraParamToString(QVariant param)
30✔
982
{
983
    if (param.isValid() == false)
30✔
984
        return QString();
30✔
985

986
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
NEW
987
    if (param.type() == QVariant::Int && param.toInt() != -1)
×
NEW
988
        return QString::number(param.toInt());
×
989
#else
990
    if (param.metaType().id() == QMetaType::Int && param.toInt() != -1)
991
        return QString::number(param.toInt());
992
#endif
NEW
993
    return QString();
×
994
}
995

996
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc)
7✔
997
{
998
    Q_ASSERT(doc != NULL);
7✔
999

1000
    /* Caption */
1001
    doc->writeAttribute(KXMLQLCVCCaption, caption());
7✔
1002

1003
    /* ID */
1004
    if (id() != VCWidget::invalidId())
7✔
1005
        doc->writeAttribute(KXMLQLCVCWidgetID, QString::number(id()));
×
1006

1007
    /* Page */
1008
    if (page() != 0)
7✔
1009
        doc->writeAttribute(KXMLQLCVCWidgetPage, QString::number(page()));
×
1010

1011
    return true;
7✔
1012
}
1013

1014
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1015
{
1016
    Q_ASSERT(doc != NULL);
9✔
1017

1018
    QString str;
9✔
1019

1020
    /* VC appearance entry */
1021
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
9✔
1022

1023
    /* Frame style */
1024
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
9✔
1025

1026
    /* Foreground color */
1027
    if (hasCustomForegroundColor() == true)
9✔
1028
        str.setNum(foregroundColor().rgb());
1✔
1029
    else
1030
        str = KXMLQLCVCWidgetColorDefault;
8✔
1031
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
9✔
1032

1033
    /* Background color */
1034
    if (hasCustomBackgroundColor() == true)
9✔
1035
        str.setNum(backgroundColor().rgb());
1✔
1036
    else
1037
        str = KXMLQLCVCWidgetColorDefault;
8✔
1038
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
9✔
1039

1040
    /* Background image */
1041
    if (backgroundImage().isEmpty() == false)
9✔
1042
        str = m_doc->normalizeComponentPath(m_backgroundImage);
1✔
1043
    else
1044
        str = KXMLQLCVCWidgetBackgroundImageNone;
8✔
1045
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundImage, str);
9✔
1046

1047
    /* Font */
1048
    if (hasCustomFont() == true)
9✔
1049
        str = font().toString();
1✔
1050
    else
1051
        str = KXMLQLCVCWidgetFontDefault;
8✔
1052
    doc->writeTextElement(KXMLQLCVCWidgetFont, str);
9✔
1053

1054
    /* End the <Appearance> tag */
1055
    doc->writeEndElement();
9✔
1056

1057
    return true;
18✔
1058
}
1059

1060
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1061
{
1062
    return saveXMLInput(doc, inputSource());
4✔
1063
}
1064

1065
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
12✔
1066
                            const QLCInputSource *src)
1067
{
1068
    Q_ASSERT(doc != NULL);
12✔
1069

1070
    if (src == NULL)
12✔
1071
        return false;
2✔
1072

1073
    if (src->isValid() == true)
10✔
1074
    {
1075
        doc->writeStartElement(KXMLQLCVCWidgetInput);
10✔
1076
        doc->writeAttribute(KXMLQLCVCWidgetInputUniverse, QString("%1").arg(src->universe()));
10✔
1077
        doc->writeAttribute(KXMLQLCVCWidgetInputChannel, QString("%1").arg(src->channel()));
10✔
1078
        if (src->feedbackValue(QLCInputFeedback::LowerValue) != 0)
10✔
1079
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerValue, QString::number(src->feedbackValue(QLCInputFeedback::LowerValue)));
×
1080
        if (src->feedbackValue(QLCInputFeedback::UpperValue) != UCHAR_MAX)
10✔
1081
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperValue, QString::number(src->feedbackValue(QLCInputFeedback::UpperValue)));
×
1082
        if (src->feedbackValue(QLCInputFeedback::MonitorValue) != UCHAR_MAX)
10✔
1083
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorValue, QString::number(src->feedbackValue(QLCInputFeedback::MonitorValue)));
×
1084

1085
        // save feedback extra params
1086
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
20✔
1087

1088
        if (!extraParams.isEmpty())
10✔
NEW
1089
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1090

1091
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
10✔
1092

1093
        if (!extraParams.isEmpty())
10✔
NEW
1094
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperParams, extraParams);
×
1095

1096
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
10✔
1097

1098
        if (!extraParams.isEmpty())
10✔
NEW
1099
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorParams, extraParams);
×
1100

1101
        doc->writeEndElement();
10✔
1102
    }
1103

1104
    return true;
10✔
1105
}
1106

1107
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
12✔
1108
                      QSharedPointer<QLCInputSource> const& src)
1109
{
1110
    return saveXMLInput(doc, src.data());
12✔
1111
}
1112

1113
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1114
{
1115
    Q_ASSERT(doc != NULL);
8✔
1116

1117
    /* Window state tag */
1118
    doc->writeStartElement(KXMLQLCWindowState);
8✔
1119

1120
    /* Visible status */
1121
    if (isVisible() == true)
8✔
1122
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
2✔
1123
    else
1124
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
6✔
1125

1126
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
8✔
1127
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
8✔
1128
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
8✔
1129
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
8✔
1130

1131
    doc->writeEndElement();
8✔
1132

1133
    return true;
8✔
1134
}
1135

1136
bool VCWidget::loadXMLWindowState(QXmlStreamReader &tag, int* x, int* y,
15✔
1137
                                  int* w, int* h, bool* visible)
1138
{
1139
    if (tag.device() == NULL || x == NULL || y == NULL || w == NULL || h == NULL ||
15✔
1140
            visible == NULL)
1141
        return false;
5✔
1142

1143
    if (tag.name() == KXMLQLCWindowState)
10✔
1144
    {
1145
        QXmlStreamAttributes attrs = tag.attributes();
9✔
1146
        *x = attrs.value(KXMLQLCWindowStateX).toString().toInt();
9✔
1147
        *y = attrs.value(KXMLQLCWindowStateY).toString().toInt();
9✔
1148
        *w = attrs.value(KXMLQLCWindowStateWidth).toString().toInt();
9✔
1149
        *h = attrs.value(KXMLQLCWindowStateHeight).toString().toInt();
9✔
1150

1151
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
9✔
1152
            *visible = true;
8✔
1153
        else
1154
            *visible = false;
1✔
1155
        tag.skipCurrentElement();
9✔
1156

1157
        return true;
9✔
1158
    }
1159
    else
1160
    {
1161
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1162
        return false;
1✔
1163
    }
1164
}
1165

1166
/*****************************************************************************
1167
 * QLC+ Mode change
1168
 *****************************************************************************/
1169

1170
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1171
{
1172
    if (m_doc->mode() == Doc::Design)
25✔
1173
        return;
25✔
1174

1175
    m_liveEdit = liveEdit;
×
1176

1177
    if (m_disableState)
×
1178
        setEnabled(m_liveEdit);
×
1179
    else
1180
        enableWidgetUI(!m_liveEdit);
×
1181

1182
    unsetCursor();
×
1183
    update();
×
1184
}
1185

1186
void VCWidget::cancelLiveEdit()
×
1187
{
1188
    m_liveEdit = false;
×
1189
}
×
1190

1191
void VCWidget::slotModeChanged(Doc::Mode mode)
66✔
1192
{
1193
    // make sure to exit from a 'deep' disable state
1194
    if (mode == Doc::Design)
66✔
1195
        setEnabled(true);
34✔
1196

1197
    /* Reset mouse cursor */
1198
    unsetCursor();
66✔
1199

1200
    /* Force an update to get rid of selection markers */
1201
    update();
66✔
1202
}
66✔
1203

1204
Doc::Mode VCWidget::mode() const
191✔
1205
{
1206
    Q_ASSERT(m_doc != NULL);
191✔
1207
    if (m_liveEdit)
191✔
1208
        return Doc::Design;
×
1209
    return m_doc->mode();
191✔
1210
}
1211

1212
/*****************************************************************************
1213
 * Widget menu
1214
 *****************************************************************************/
1215

1216
void VCWidget::invokeMenu(const QPoint& point)
×
1217
{
1218
    /* No point coming here if there is no VC instance */
1219
    VirtualConsole* vc = VirtualConsole::instance();
×
1220
    if (vc == NULL)
×
1221
        return;
×
1222

1223
    QMenu* menu = vc->editMenu();
×
1224
    Q_ASSERT(menu != NULL);
×
1225
    menu->exec(point);
×
1226
}
1227

1228
/*****************************************************************************
1229
 * Custom menu
1230
 *****************************************************************************/
1231

1232
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1233
{
1234
    Q_UNUSED(parentMenu);
1235
    return NULL;
3✔
1236
}
1237

1238
/*****************************************************************************
1239
 * Widget move & resize
1240
 *****************************************************************************/
1241

1242
void VCWidget::resize(const QSize& size)
244✔
1243
{
1244
    QSize sz(size);
244✔
1245

1246
    // Force grid settings
1247
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1248
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1249

1250
    // Resize
1251
    QWidget::resize(sz);
244✔
1252
}
244✔
1253

1254
void VCWidget::move(const QPoint& point)
13✔
1255
{
1256
    QPoint pt(point);
13✔
1257

1258
    // Force grid settings
1259
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1260
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1261

1262
    // Don't move beyond left or right
1263
    if (pt.x() < 0)
13✔
1264
        pt.setX(0);
1✔
1265
    else if (pt.x() + rect().width() > parentWidget()->width())
12✔
1266
        pt.setX(parentWidget()->width() - rect().width());
1✔
1267

1268
    // Don't move beyond top or bottom
1269
    if (pt.y() < 0)
13✔
1270
        pt.setY(0);
1✔
1271
    else if (pt.y() + rect().height() > parentWidget()->height())
12✔
1272
        pt.setY(parentWidget()->height() - rect().height());
1✔
1273

1274
    // Move
1275
    QWidget::move(pt);
13✔
1276

1277
    m_doc->setModified();
13✔
1278
}
13✔
1279

1280
QPoint VCWidget::lastClickPoint() const
2✔
1281
{
1282
    return m_mousePressPoint;
2✔
1283
}
1284

1285
/*****************************************************************************
1286
 * Event handlers
1287
 *****************************************************************************/
1288

1289
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1290
{
1291
    Q_UNUSED(e);
1292

1293
    /* No point coming here if there is no VC instance */
1294
    VirtualConsole* vc = VirtualConsole::instance();
32✔
1295
    if (vc == NULL)
32✔
1296
        return;
×
1297

1298
    QPainter painter(this);
64✔
1299

1300
    /* Draw frame according to style */
1301
    QStyleOptionFrame option;
64✔
1302
    option.initFrom(this);
32✔
1303

1304
    if (frameStyle() == KVCFrameStyleSunken)
32✔
1305
        option.state = QStyle::State_Sunken;
3✔
1306
    else if (frameStyle() == KVCFrameStyleRaised)
29✔
1307
        option.state = QStyle::State_Raised;
4✔
1308
    else
1309
        option.state = QStyle::State_None;
25✔
1310

1311
    if (mode() == Doc::Design)
32✔
1312
        option.state |= QStyle::State_Enabled;
28✔
1313

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

1318
    QWidget::paintEvent(e);
32✔
1319

1320
    /* Draw selection frame */
1321
    if (mode() == Doc::Design && vc->isWidgetSelected(this) == true)
32✔
1322
    {
1323
        /* Draw a dotted line around the widget */
1324
        QPen pen(Qt::DashLine);
8✔
1325
        pen.setColor(Qt::blue);
4✔
1326
        pen.setCapStyle(Qt::RoundCap);
4✔
1327
        pen.setWidth(0);
4✔
1328
        painter.setPen(pen);
4✔
1329
        painter.drawRect(0, 0, rect().width() - 1, rect().height() - 1);
4✔
1330

1331
        /* Draw a resize handle */
1332
        if (allowResize() == true)
4✔
1333
        {
1334
            QIcon icon(":/resize.png");
3✔
1335
            painter.drawPixmap(rect().width() - 16, rect().height() - 16,
3✔
1336
                               icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On));
6✔
1337
        }
1338
    }
1339
}
1340

1341
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1342
{
1343
    Q_ASSERT(e != NULL);
2✔
1344

1345
    if (mode() == Doc::Operate)
2✔
1346
    {
1347
        QWidget::mousePressEvent(e);
×
1348
        return;
×
1349
    }
1350

1351
    /* Perform widget de/selection in virtualconsole's selection buffer */
1352
    handleWidgetSelection(e);
2✔
1353

1354
    /* Resize mode */
1355
    if (m_resizeMode == true)
2✔
1356
    {
1357
        setMouseTracking(false);
×
1358
        m_resizeMode = false;
×
1359
    }
1360

1361
    /* Move, resize or context menu invocation */
1362
    if (e->button() & Qt::LeftButton || e->button() & Qt::MiddleButton)
2✔
1363
    {
1364
        /* Start moving or resizing based on where the click landed */
1365
        if (e->pos().x() > rect().width() - 10 && e->pos().y() > rect().height() - 10 && allowResize())
2✔
1366
        {
1367
            m_resizeMode = true;
×
1368
            setMouseTracking(true);
×
1369
            setCursor(QCursor(Qt::SizeFDiagCursor));
×
1370
        }
1371
        else
1372
        {
1373
            m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
2✔
1374
            setCursor(QCursor(Qt::SizeAllCursor));
2✔
1375
        }
1376
    }
1377
    else if (e->button() & Qt::RightButton)
×
1378
    {
1379
        /* Menu invocation */
1380
        m_mousePressPoint = QPoint(e->pos().x(), e->pos().y());
×
1381
        invokeMenu(mapToGlobal(e->pos()));
×
1382
    }
1383
}
1384

1385
void VCWidget::handleWidgetSelection(QMouseEvent* e)
3✔
1386
{
1387
    /* No point coming here if there is no VC */
1388
    VirtualConsole* vc = VirtualConsole::instance();
3✔
1389
    if (vc == NULL)
3✔
1390
        return;
×
1391

1392
    /* Widget selection logic (like in Qt Designer) */
1393
    if (e->button() == Qt::LeftButton)
3✔
1394
    {
1395
        if (e->modifiers() & Qt::ShiftModifier)
3✔
1396
        {
1397
            /* Toggle selection with LMB when shift is pressed */
1398
            bool selected = vc->isWidgetSelected(this);
×
1399
            vc->setWidgetSelected(this, !selected);
×
1400
        }
1401
        else
1402
        {
1403
            if (vc->isWidgetSelected(this) == false)
3✔
1404
            {
1405
                /* Select only this */
1406
                vc->clearWidgetSelection();
3✔
1407
                vc->setWidgetSelected(this, true);
3✔
1408
            }
1409
        }
1410
    }
1411
    else if (e->button() == Qt::RightButton)
×
1412
    {
1413
        if (vc->isWidgetSelected(this) == false)
×
1414
        {
1415
            /* Select only this */
1416
            vc->clearWidgetSelection();
×
1417
            vc->setWidgetSelected(this, true);
×
1418
        }
1419
    }
1420
}
1421

1422
void VCWidget::mouseReleaseEvent(QMouseEvent* e)
1✔
1423
{
1424
    if (mode() == Doc::Design)
1✔
1425
    {
1426
        unsetCursor();
1✔
1427
        m_resizeMode = false;
1✔
1428
        setMouseTracking(false);
1✔
1429
    }
1430
    else
1431
    {
1432
        QWidget::mouseReleaseEvent(e);
×
1433
    }
1434
}
1✔
1435

1436
void VCWidget::mouseDoubleClickEvent(QMouseEvent* e)
×
1437
{
1438
    if (mode() == Doc::Design)
×
1439
        editProperties();
×
1440
    else
1441
        QWidget::mouseDoubleClickEvent(e);
×
1442
}
×
1443

1444
void VCWidget::mouseMoveEvent(QMouseEvent* e)
2✔
1445
{
1446
    if (mode() == Doc::Design)
2✔
1447
    {
1448
        if (m_resizeMode == true)
2✔
1449
        {
1450
            QPoint p = mapToParent(e->pos());
×
1451
            resize(QSize(p.x() - x(), p.y() - y()));
×
1452
            m_doc->setModified();
×
1453
        }
1454
        else if (e->buttons() & Qt::LeftButton || e->buttons() & Qt::MiddleButton)
2✔
1455
        {
1456
            QPoint p = mapToParent(e->pos());
2✔
1457
            p.setX(p.x() - m_mousePressPoint.x());
2✔
1458
            p.setY(p.y() - m_mousePressPoint.y());
2✔
1459

1460
            move(p);
2✔
1461
            m_doc->setModified();
2✔
1462
        }
1463
    }
1464
    else
1465
    {
1466
        QWidget::mouseMoveEvent(e);
×
1467
    }
1468
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc