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

mcallegari / qlcplus / 13633248611

03 Mar 2025 02:31PM UTC coverage: 31.871% (+0.4%) from 31.5%
13633248611

push

github

web-flow
actions: add chrpath to profile

14689 of 46089 relevant lines covered (31.87%)

26426.11 hits per line

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

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

5
  Copyright (c) Heikki Junnila
6
                Massimo Callegari
7

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

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

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

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

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

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

53
#define GRID_RESOLUTION 5
54

55
VCWidget::VCWidget(QWidget* parent, Doc* doc)
177✔
56
    : QWidget(parent)
57
    , m_doc(doc)
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)
34✔
589
{
590
    // Connect when the first valid input source is set
591
    if (m_inputs.isEmpty() == true && !source.isNull() && source->isValid() == true)
34✔
592
    {
593
        connect(m_doc->inputOutputMap(), SIGNAL(inputValueChanged(quint32,quint32,uchar)),
12✔
594
                this, SLOT(slotInputValueChanged(quint32,quint32,uchar)));
595
        connect(m_doc->inputOutputMap(), SIGNAL(profileChanged(quint32,QString)),
12✔
596
                this, SLOT(slotInputProfileChanged(quint32,QString)));
597
    }
598

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

834
    return true;
835
}
836

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

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

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

892
    return true;
893
}
894

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

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

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

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

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

923
    return newSrc;
7✔
924
}
925

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

931
    if (root.name() != KXMLQLCVCWidgetInput)
16✔
932
        return false;
933

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

936
    setInputSource(newSrc, id);
7✔
937

938
    root.skipCurrentElement();
7✔
939

940
    return true;
941
}
942

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

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

980
    return true;
×
981
}
982

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

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

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

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

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

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

1013
    return true;
7✔
1014
}
1015

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

1020
    QString str;
1021

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

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

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

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

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

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

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

1059
    return true;
9✔
1060
}
9✔
1061

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

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

1072
    if (src == NULL)
12✔
1073
        return false;
1074

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

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

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

1093
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::UpperValue));
10✔
1094

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

1098
        extraParams = extraParamToString(src->feedbackExtraParams(QLCInputFeedback::MonitorValue));
10✔
1099

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

1103
        doc->writeEndElement();
10✔
1104
    }
10✔
1105

1106
    return true;
1107
}
1108

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

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

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

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

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

1133
    doc->writeEndElement();
8✔
1134

1135
    return true;
8✔
1136
}
1137

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

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

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

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

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

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

1177
    m_liveEdit = liveEdit;
×
1178

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

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

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

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

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

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

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

1214
/*****************************************************************************
1215
 * Widget menu
1216
 *****************************************************************************/
1217

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

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

1230
/*****************************************************************************
1231
 * Custom menu
1232
 *****************************************************************************/
1233

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

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

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

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

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

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

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

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

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

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

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

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

1287
/*****************************************************************************
1288
 * Event handlers
1289
 *****************************************************************************/
1290

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

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

1300
    QPainter painter(this);
32✔
1301

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

© 2025 Coveralls, Inc