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

mcallegari / qlcplus / 14452115210

14 Apr 2025 05:40PM UTC coverage: 31.855% (+0.001%) from 31.854%
14452115210

Pull #1708

github

web-flow
Merge 772292420 into 02d6f8913
Pull Request #1708: simplify work with containers

55 of 80 new or added lines in 19 files covered. (68.75%)

3 existing lines in 3 files now uncovered.

14671 of 46056 relevant lines covered (31.85%)

26461.66 hits per line

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

73.28
/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())
177✔
66
{
67
    Q_ASSERT(parent != NULL);
68
    Q_ASSERT(doc != NULL);
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));
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()
45✔
218
{
219
    return m_page;
45✔
220
}
221

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

226
bool VCWidget::copyFrom(const VCWidget* widget)
9✔
227
{
228
    if (widget == NULL)
9✔
229
        return false;
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
    }
267

268
    m_page = widget->m_page;
8✔
269

270
    return true;
271
}
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)));
28✔
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);
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);
4✔
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);
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);
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);
4✔
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
53✔
437
{
438
    return windowTitle();
53✔
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;
476
    else if (style == "Raised")
3✔
477
        return KVCFrameStyleRaised;
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;
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;
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;
586
}
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
441✔
682
{
683
    return m_inputs.value(id);
441✔
684
}
685

686
void VCWidget::remapInputSources(int pgNum)
×
687
{
NEW
688
    QHash <quint8, QSharedPointer<QLCInputSource> >::iterator it = m_inputs.begin();
×
NEW
689
    for(; it != m_inputs.end(); it++)
×
690
    {
691
        const QSharedPointer<QLCInputSource>& src(it.value());
692
        src->setPage(pgNum);
×
NEW
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);
122✔
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;
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

NEW
738
    QHash <quint8, QSharedPointer<QLCInputSource> >::iterator it = m_inputs.begin();
×
NEW
739
    for(; it != m_inputs.end(); it++)
×
740
    {
741
        QSharedPointer<QLCInputSource> const& source = it.value();
742

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

769
/*****************************************************************************
770
 * Key sequence handler
771
 *****************************************************************************/
772

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

800
void VCWidget::slotKeyPressed(const QKeySequence& keySequence)
1✔
801
{
802
    emit keyPressed(keySequence);
1✔
803
}
1✔
804

805
void VCWidget::slotKeyReleased(const QKeySequence& keySequence)
1✔
806
{
807
    emit keyReleased(keySequence);
1✔
808
}
1✔
809

810
/*****************************************************************************
811
 * Load & Save
812
 *****************************************************************************/
813

814
void VCWidget::postLoad()
6✔
815
{
816
    /* NOP */
817
}
6✔
818

819
bool VCWidget::loadXMLCommon(QXmlStreamReader &root)
14✔
820
{
821
    if (root.device() == NULL || root.hasError())
28✔
822
        return false;
×
823

824
    QXmlStreamAttributes attrs = root.attributes();
14✔
825

826
    /* ID */
827
    if (attrs.hasAttribute(KXMLQLCVCWidgetID))
14✔
828
        setID(attrs.value(KXMLQLCVCWidgetID).toString().toUInt());
×
829

830
    /* Caption */
831
    if (attrs.hasAttribute(KXMLQLCVCCaption))
14✔
832
        setCaption(attrs.value(KXMLQLCVCCaption).toString());
3✔
833

834
    /* Page */
835
    if (attrs.hasAttribute(KXMLQLCVCWidgetPage))
14✔
836
        setPage(attrs.value(KXMLQLCVCWidgetPage).toString().toInt());
×
837

838
    return true;
839
}
840

841
bool VCWidget::loadXMLAppearance(QXmlStreamReader &root)
9✔
842
{
843
    if (root.device() == NULL || root.hasError())
18✔
844
        return false;
×
845

846
    if (root.name() != KXMLQLCVCWidgetAppearance)
18✔
847
    {
848
        qWarning() << Q_FUNC_INFO << "Appearance node not found!";
1✔
849
        return false;
1✔
850
    }
851

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

896
    return true;
897
}
898

899
QSharedPointer<QLCInputSource> VCWidget::getXMLInput(QXmlStreamReader &root)
7✔
900
{
901
    QXmlStreamAttributes attrs = root.attributes();
7✔
902

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

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

915
    newSrc->setFeedbackValue(QLCInputFeedback::LowerValue, min);
7✔
916
    newSrc->setFeedbackValue(QLCInputFeedback::UpperValue, max);
7✔
917
    newSrc->setFeedbackValue(QLCInputFeedback::MonitorValue, mon);
7✔
918

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

927
    return newSrc;
7✔
928
}
929

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

935
    if (root.name() != KXMLQLCVCWidgetInput)
16✔
936
        return false;
937

938
    QSharedPointer<QLCInputSource>newSrc = getXMLInput(root);
7✔
939

940
    setInputSource(newSrc, id);
7✔
941

942
    root.skipCurrentElement();
7✔
943

944
    return true;
945
}
946

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

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

984
    return true;
×
985
}
986

987
QString VCWidget::extraParamToString(QVariant param)
36✔
988
{
989
    if (param.isValid() == false)
36✔
990
        return QString();
991

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

1002
bool VCWidget::saveXMLCommon(QXmlStreamWriter *doc)
7✔
1003
{
1004
    Q_ASSERT(doc != NULL);
1005

1006
    /* Caption */
1007
    doc->writeAttribute(KXMLQLCVCCaption, caption());
7✔
1008

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

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

1017
    return true;
7✔
1018
}
1019

1020
bool VCWidget::saveXMLAppearance(QXmlStreamWriter *doc)
9✔
1021
{
1022
    Q_ASSERT(doc != NULL);
1023

1024
    QString str;
1025

1026
    /* VC appearance entry */
1027
    doc->writeStartElement(KXMLQLCVCWidgetAppearance);
9✔
1028

1029
    /* Frame style */
1030
    doc->writeTextElement(KXMLQLCVCFrameStyle, frameStyleToString(frameStyle()));
9✔
1031

1032
    /* Foreground color */
1033
    if (hasCustomForegroundColor() == true)
9✔
1034
        str.setNum(foregroundColor().rgb());
2✔
1035
    else
1036
        str = KXMLQLCVCWidgetColorDefault;
8✔
1037
    doc->writeTextElement(KXMLQLCVCWidgetForegroundColor, str);
9✔
1038

1039
    /* Background color */
1040
    if (hasCustomBackgroundColor() == true)
9✔
1041
        str.setNum(backgroundColor().rgb());
2✔
1042
    else
1043
        str = KXMLQLCVCWidgetColorDefault;
8✔
1044
    doc->writeTextElement(KXMLQLCVCWidgetBackgroundColor, str);
9✔
1045

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

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

1060
    /* End the <Appearance> tag */
1061
    doc->writeEndElement();
9✔
1062

1063
    return true;
9✔
1064
}
9✔
1065

1066
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc)
4✔
1067
{
1068
    return saveXMLInput(doc, inputSource());
8✔
1069
}
1070

1071
bool VCWidget::saveXMLInput(QXmlStreamWriter *doc,
14✔
1072
                            const QLCInputSource *src)
1073
{
1074
    Q_ASSERT(doc != NULL);
1075

1076
    if (src == NULL)
14✔
1077
        return false;
1078

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

1091
        // save feedback extra params
1092
        QString extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::LowerValue));
24✔
1093

1094
        if (!extraParams.isEmpty())
12✔
1095
            doc->writeAttribute(KXMLQLCVCWidgetInputLowerParams, extraParams);
×
1096

1097
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
12✔
1098

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

1102
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
12✔
1103

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

1107
        doc->writeEndElement();
12✔
1108
    }
12✔
1109

1110
    return true;
1111
}
1112

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

1119
bool VCWidget::saveXMLWindowState(QXmlStreamWriter *doc)
8✔
1120
{
1121
    Q_ASSERT(doc != NULL);
1122

1123
    /* Window state tag */
1124
    doc->writeStartElement(KXMLQLCWindowState);
8✔
1125

1126
    /* Visible status */
1127
    if (isVisible() == true)
8✔
1128
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCTrue);
2✔
1129
    else
1130
        doc->writeAttribute(KXMLQLCWindowStateVisible, KXMLQLCFalse);
6✔
1131

1132
    doc->writeAttribute(KXMLQLCWindowStateX, QString::number(x()));
8✔
1133
    doc->writeAttribute(KXMLQLCWindowStateY, QString::number(y()));
8✔
1134
    doc->writeAttribute(KXMLQLCWindowStateWidth, QString::number(width()));
8✔
1135
    doc->writeAttribute(KXMLQLCWindowStateHeight, QString::number(height()));
8✔
1136

1137
    doc->writeEndElement();
8✔
1138

1139
    return true;
8✔
1140
}
1141

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

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

1157
        if (attrs.value(KXMLQLCWindowStateVisible).toString() == KXMLQLCTrue)
9✔
1158
            *visible = true;
8✔
1159
        else
1160
            *visible = false;
1✔
1161
        tag.skipCurrentElement();
9✔
1162

1163
        return true;
1164
    }
1165
    else
1166
    {
1167
        qWarning() << Q_FUNC_INFO << "Window state not found";
1✔
1168
        return false;
1✔
1169
    }
1170
}
1171

1172
/*****************************************************************************
1173
 * QLC+ Mode change
1174
 *****************************************************************************/
1175

1176
void VCWidget::setLiveEdit(bool liveEdit)
25✔
1177
{
1178
    if (m_doc->mode() == Doc::Design)
25✔
1179
        return;
1180

1181
    m_liveEdit = liveEdit;
×
1182

1183
    if (m_disableState)
×
1184
        setEnabled(m_liveEdit);
×
1185
    else
1186
        enableWidgetUI(!m_liveEdit);
×
1187

1188
    unsetCursor();
×
1189
    update();
×
1190
}
1191

1192
void VCWidget::cancelLiveEdit()
×
1193
{
1194
    m_liveEdit = false;
×
1195
}
×
1196

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

1203
    /* Reset mouse cursor */
1204
    unsetCursor();
66✔
1205

1206
    /* Force an update to get rid of selection markers */
1207
    update();
66✔
1208
}
66✔
1209

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

1218
/*****************************************************************************
1219
 * Widget menu
1220
 *****************************************************************************/
1221

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

1229
    QMenu* menu = vc->editMenu();
×
1230
    Q_ASSERT(menu != NULL);
1231
    menu->exec(point);
×
1232
}
1233

1234
/*****************************************************************************
1235
 * Custom menu
1236
 *****************************************************************************/
1237

1238
QMenu* VCWidget::customMenu(QMenu* parentMenu)
3✔
1239
{
1240
    Q_UNUSED(parentMenu);
1241
    return NULL;
3✔
1242
}
1243

1244
/*****************************************************************************
1245
 * Widget move & resize
1246
 *****************************************************************************/
1247

1248
void VCWidget::resize(const QSize& size)
244✔
1249
{
1250
    QSize sz(size);
1251

1252
    // Force grid settings
1253
    sz.setWidth(size.width() - (size.width() % GRID_RESOLUTION));
244✔
1254
    sz.setHeight(size.height() - (size.height() % GRID_RESOLUTION));
244✔
1255

1256
    // Resize
1257
    QWidget::resize(sz);
244✔
1258
}
244✔
1259

1260
void VCWidget::move(const QPoint& point)
13✔
1261
{
1262
    QPoint pt(point);
1263

1264
    // Force grid settings
1265
    pt.setX(point.x() - (point.x() % GRID_RESOLUTION));
13✔
1266
    pt.setY(point.y() - (point.y() % GRID_RESOLUTION));
13✔
1267

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

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

1280
    // Move
1281
    QWidget::move(pt);
13✔
1282

1283
    m_doc->setModified();
13✔
1284
}
13✔
1285

1286
QPoint VCWidget::lastClickPoint() const
2✔
1287
{
1288
    return m_mousePressPoint;
2✔
1289
}
1290

1291
/*****************************************************************************
1292
 * Event handlers
1293
 *****************************************************************************/
1294

1295
void VCWidget::paintEvent(QPaintEvent* e)
32✔
1296
{
1297
    Q_UNUSED(e);
1298

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

1304
    QPainter painter(this);
32✔
1305

1306
    /* Draw frame according to style */
1307
    QStyleOptionFrame option;
32✔
1308
    option.initFrom(this);
32✔
1309

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

1317
    if (mode() == Doc::Design)
32✔
1318
        option.state |= QStyle::State_Enabled;
1319

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

1324
    QWidget::paintEvent(e);
32✔
1325

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

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

1347
void VCWidget::mousePressEvent(QMouseEvent* e)
2✔
1348
{
1349
    Q_ASSERT(e != NULL);
1350

1351
    if (mode() == Doc::Operate)
2✔
1352
    {
1353
        QWidget::mousePressEvent(e);
×
1354
        return;
×
1355
    }
1356

1357
    /* Perform widget de/selection in virtualconsole's selection buffer */
1358
    handleWidgetSelection(e);
2✔
1359

1360
    /* Resize mode */
1361
    if (m_resizeMode == true)
2✔
1362
    {
1363
        setMouseTracking(false);
×
1364
        m_resizeMode = false;
×
1365
    }
1366

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

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

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

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

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

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

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