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

mcallegari / qlcplus / 19144422256

06 Nov 2025 05:33PM UTC coverage: 34.256% (-0.1%) from 34.358%
19144422256

push

github

mcallegari
Back to 5.1.0 debug

17718 of 51723 relevant lines covered (34.26%)

19528.23 hits per line

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

73.91
/ui/src/virtualconsole/vcwidget.cpp
1
/*
2
  Q Light Controller Plus
3
  vcwidget.cpp
4

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

8
  Licensed under the Apache License, Version 2.0 (the "License");
9
  you may not use this file except in compliance with the License.
10
  You may obtain a copy of the License at
11

12
      http://www.apache.org/licenses/LICENSE-2.0.txt
13

14
  Unless required by applicable law or agreed to in writing, software
15
  distributed under the License is distributed on an "AS IS" BASIS,
16
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
  See the License for the specific language governing permissions and
18
  limitations under the License.
19
*/
20

21
#include <QStyleOptionFrame>
22
#include <QXmlStreamReader>
23
#include <QXmlStreamWriter>
24
#include <QApplication>
25
#include <QInputDialog>
26
#include <QColorDialog>
27
#include <QFileDialog>
28
#include <QFontDialog>
29
#include <QMessageBox>
30
#include <QMouseEvent>
31
#include <QMetaObject>
32
#include <QPainter>
33
#include <QPalette>
34
#include <QCursor>
35
#include <QPixmap>
36
#include <QDebug>
37
#include <QBrush>
38
#include <QPoint>
39
#include <QStyle>
40
#include <QSize>
41
#include <QMenu>
42
#include <QList>
43

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

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

53
#define GRID_RESOLUTION 5
54

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

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

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

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

82
    m_resizeMode = false;
177✔
83

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

245
    m_frameStyle = widget->m_frameStyle;
8✔
246

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

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

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

268
    m_page = widget->m_page;
8✔
269

270
    return true;
8✔
271
}
8✔
272

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

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

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

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

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

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

295

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

357
    m_hasCustomForegroundColor = true;
7✔
358

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

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

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

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

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

379
    m_hasCustomForegroundColor = false;
4✔
380

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

561
    return true;
56✔
562
}
563

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

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

585
    return false;
19✔
586
}
49✔
587

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

736
    QLCInputProfile *profile = m_doc->inputOutputMap()->profile(profileName);
×
737

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

766
/*****************************************************************************
767
 * Key sequence handler
768
 *****************************************************************************/
769

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

797
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
798
{
799
    emit keyPressed(keySequence);
1✔
800
}
1✔
801

802
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
803
{
804
    emit keyReleased(keySequence);
1✔
805
}
1✔
806

807
/*****************************************************************************
808
 * Load & Save
809
 *****************************************************************************/
810

811
void VCWidget::postLoad()
6✔
812
{
813
    /* NOP */
814
}
6✔
815

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

821
    QXmlStreamAttributes attrs = root.attributes();
14✔
822

823
    /* ID */
824
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
825
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
826

827
    /* Caption */
828
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
829
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
6✔
830

831
    /* Page */
832
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
833
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
834

835
    return true;
14✔
836
}
14✔
837

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

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

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

893
    return true;
8✔
894
}
895

896
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
897
{
898
    QXmlStreamAttributes attrs = root.attributes();
7✔
899

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

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

912
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
913
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
914
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
915

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

924
    return newSrc;
14✔
925
}
7✔
926

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

932
    if (root.name() != KXMLQLCVCWidgetInput)
8✔
933
        return false;
1✔
934

935
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
936

937
    setInputSource(newSrc, id);
7✔
938

939
    root.skipCurrentElement();
7✔
940

941
    return true;
7✔
942
}
7✔
943

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

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

981
    return true;
×
982
}
983

984
QString VCWidget::extraParamToString(QVariant param)
36✔
985
{
986
    if (param.isValid() == false)
36✔
987
        return QString();
×
988

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

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

1003
    /* Caption */
1004
    doc->writeAttribute(KXMLQLCVCCaption, caption());
14✔
1005

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

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

1014
    return true;
7✔
1015
}
1016

1017
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1018
{
1019
    Q_ASSERT(doc != NULL);
9✔
1020

1021
    QString str;
9✔
1022

1023
    /* VC appearance entry */
1024
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
18✔
1025

1026
    /* Frame style */
1027
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
18✔
1028

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

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

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

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

1057
    /* End the <Appearance> tag */
1058
    doc->writeEndElement();
9✔
1059

1060
    return true;
9✔
1061
}
9✔
1062

1063
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1064
{
1065
    return saveXMLInput(doc, inputSource());
4✔
1066
}
1067

1068
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1069
                            const QLCInputSource *src)
1070
{
1071
    Q_ASSERT(doc != NULL);
14✔
1072

1073
    if (src == NULL)
14✔
1074
        return false;
2✔
1075

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

1088
        // save feedback extra params
1089
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
12✔
1090

1091
        if (!extraParams.isEmpty())
12✔
1092
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1093

1094
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
12✔
1095

1096
        if (!extraParams.isEmpty())
12✔
1097
            doc->writeAttribute(KXMLQLCVCWidgetInputUpperParams, extraParams);
×
1098

1099
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
12✔
1100

1101
        if (!extraParams.isEmpty())
12✔
1102
            doc->writeAttribute(KXMLQLCVCWidgetInputMonitorParams, extraParams);
×
1103

1104
        doc->writeEndElement();
12✔
1105
    }
12✔
1106

1107
    return true;
12✔
1108
}
1109

1110
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1111
                      QSharedPointer<QLCInputSource> const& src)
1112
{
1113
    return saveXMLInput(doc, src.data());
14✔
1114
}
1115

1116
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1117
{
1118
    Q_ASSERT(doc != NULL);
8✔
1119

1120
    /* Window state tag */
1121
    doc->writeStartElement(KXMLQLCWindowState);
16✔
1122

1123
    /* Visible status */
1124
    if (isVisible() == true)
8✔
1125
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
6✔
1126
    else
1127
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
18✔
1128

1129
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
16✔
1130
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
16✔
1131
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
16✔
1132
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
16✔
1133

1134
    doc->writeEndElement();
8✔
1135

1136
    return true;
8✔
1137
}
1138

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

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

1154
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
18✔
1155
            *visible = true;
8✔
1156
        else
1157
            *visible = false;
1✔
1158
        tag.skipCurrentElement();
9✔
1159

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

1169
/*****************************************************************************
1170
 * QLC+ Mode change
1171
 *****************************************************************************/
1172

1173
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1174
{
1175
    if (m_doc->mode() == Doc::Design)
25✔
1176
        return;
25✔
1177

1178
    m_liveEdit = liveEdit;
×
1179

1180
    if (m_disableState)
×
1181
        setEnabled(m_liveEdit);
×
1182
    else
1183
        enableWidgetUI(!m_liveEdit);
×
1184

1185
    unsetCursor();
×
1186
    update();
×
1187
}
1188

1189
void VCWidget::cancelLiveEdit()
×
1190
{
1191
    m_liveEdit = false;
×
1192
}
×
1193

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

1200
    /* Reset mouse cursor */
1201
    unsetCursor();
66✔
1202

1203
    /* Force an update to get rid of selection markers */
1204
    update();
66✔
1205
}
66✔
1206

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

1215
/*****************************************************************************
1216
 * Widget menu
1217
 *****************************************************************************/
1218

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

1226
    QMenu* menu = vc->editMenu();
×
1227
    Q_ASSERT(menu != NULL);
×
1228
    menu->exec(point);
×
1229
}
1230

1231
/*****************************************************************************
1232
 * Custom menu
1233
 *****************************************************************************/
1234

1235
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1236
{
1237
    Q_UNUSED(parentMenu);
1238
    return NULL;
3✔
1239
}
1240

1241
/*****************************************************************************
1242
 * Widget move & resize
1243
 *****************************************************************************/
1244

1245
void VCWidget::resize(const QSize& size)
244✔
1246
{
1247
    QSize sz(size);
244✔
1248

1249
    // Force grid settings
1250
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1251
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1252

1253
    // Resize
1254
    QWidget::resize(sz);
244✔
1255
}
244✔
1256

1257
void VCWidget::move(const QPoint& point)
13✔
1258
{
1259
    QPoint pt(point);
13✔
1260

1261
    // Force grid settings
1262
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1263
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1264

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

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

1277
    // Move
1278
    QWidget::move(pt);
13✔
1279

1280
    m_doc->setModified();
13✔
1281
}
13✔
1282

1283
QPoint VCWidget::lastClickPoint() const
2✔
1284
{
1285
    return m_mousePressPoint;
2✔
1286
}
1287

1288
/*****************************************************************************
1289
 * Event handlers
1290
 *****************************************************************************/
1291

1292
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1293
{
1294
    Q_UNUSED(e);
1295

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

1301
    QPainter painter(this);
32✔
1302

1303
    /* Draw frame according to style */
1304
    QStyleOptionFrame option;
32✔
1305
    option.initFrom(this);
32✔
1306

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

1314
    if (mode() == Doc::Design)
32✔
1315
        option.state |= QStyle::State_Enabled;
28✔
1316

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

1321
    QWidget::paintEvent(e);
32✔
1322

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

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

1344
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1345
{
1346
    Q_ASSERT(e != NULL);
2✔
1347

1348
    if (mode() == Doc::Operate)
2✔
1349
    {
1350
        QWidget::mousePressEvent(e);
×
1351
        return;
×
1352
    }
1353

1354
    /* Perform widget de/selection in virtualconsole's selection buffer */
1355
    handleWidgetSelection(e);
2✔
1356

1357
    /* Resize mode */
1358
    if (m_resizeMode == true)
2✔
1359
    {
1360
        setMouseTracking(false);
×
1361
        m_resizeMode = false;
×
1362
    }
1363

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

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

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

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

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

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

1463
            move(p);
2✔
1464
            m_doc->setModified();
2✔
1465
        }
1466
    }
1467
    else
1468
    {
1469
        QWidget::mouseMoveEvent(e);
×
1470
    }
1471
}
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