• 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

6.44
/ui/src/clickandgowidget.cpp
1
/*
2
  Q Light Controller Plus
3
  clickandgowidget.cpp
4

5
  Copyright (c) Massimo Callegari
6

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

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

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

20
#include <QApplication>
21
#include <QMouseEvent>
22
#include <QPainter>
23
#include <QScreen>
24
#include <qmath.h>
25
#include <QDebug>
26
#include <QImage>
27

28
#include "clickandgowidget.h"
29
#include "qlccapability.h"
30
#include "qlcmacros.h"
31
#include "gradient.h"
32

33
#define CELL_W  150
34
#define CELL_H  45
35
#define TITLE_H  18
36

37
ClickAndGoWidget::ClickAndGoWidget(QWidget *parent) :
1✔
38
    QWidget(parent)
1✔
39
{
40
    // This makes the application crash when a clickAndGoWidget
41
    // is created in a QDialog.
42
    //    setAttribute(Qt::WA_StaticContents);
43

44
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
1✔
45
    setMouseTracking(true);
46

47
    m_type = None;
1✔
48
    m_linearColor = false;
1✔
49
    m_width = 10;
1✔
50
    m_height = 10;
1✔
51
    m_cols = 0;
1✔
52
    m_rows = 0;
1✔
53
    m_cellWidth = CELL_W;
1✔
54
    m_hoverCellIdx = -1;
1✔
55
    m_cellBarXpos = 1;
1✔
56
    m_cellBarYpos = 1;
1✔
57
    m_cellBarWidth = 0;
1✔
58
    m_levelLowLimit = 0;
1✔
59
    m_levelHighLimit = 255;
1✔
60
}
1✔
61

62
void ClickAndGoWidget::setupGradient(QColor begin, QColor end)
×
63
{
64
    QLinearGradient linearGrad(QPointF(10,0), QPointF(266, 0));
×
65
    linearGrad.setColorAt(0, begin);
×
66
    linearGrad.setColorAt(1, end);
×
67

68
    // create image and fill it with gradient
69
    m_width = 276;
×
70
    m_height = 40;
×
71
    m_image = QImage(m_width, m_height, QImage::Format_RGB32);
×
72
    QPainter painter(&m_image);
×
73
    painter.fillRect(m_image.rect(), linearGrad);
×
74

75
    m_linearColor = true;
×
76
}
×
77

78
void ClickAndGoWidget::setupColorPicker()
×
79
{
80
    int cw = 15;
81

82
    m_width = 256 + 30;
×
83
    m_height = 256;
×
84
    m_image = QImage(m_width, m_height, QImage::Format_RGB32);
×
85
    QPainter painter(&m_image);
×
86

87
    // Draw 16 default color squares
88
    painter.fillRect(0, 0, cw, 32, QColor(Qt::white));
×
89
    painter.fillRect(cw, 0, cw, 32, QColor(Qt::black));
×
90
    painter.fillRect(0, 32, cw, 64, QColor(Qt::red));
×
91
    painter.fillRect(cw, 32, cw, 64, QColor(Qt::darkRed));
×
92
    painter.fillRect(0, 64, cw, 96, QColor(Qt::green));
×
93
    painter.fillRect(cw, 64, cw, 96, QColor(Qt::darkGreen));
×
94
    painter.fillRect(0, 96, cw, 128, QColor(Qt::blue));
×
95
    painter.fillRect(cw, 96, cw, 128, QColor(Qt::darkBlue));
×
96
    painter.fillRect(0, 128, cw, 160, QColor(Qt::cyan));
×
97
    painter.fillRect(cw, 128, cw, 160, QColor(Qt::darkCyan));
×
98
    painter.fillRect(0, 160, cw, 192, QColor(Qt::magenta));
×
99
    painter.fillRect(cw, 160, cw, 192, QColor(Qt::darkMagenta));
×
100
    painter.fillRect(0, 192, cw, 224, QColor(Qt::yellow));
×
101
    painter.fillRect(cw, 192, cw, 224, QColor(Qt::darkYellow));
×
102
    painter.fillRect(0, 224, cw, 256, QColor(Qt::gray));
×
103
    painter.fillRect(cw, 224, cw, 256, QColor(Qt::darkGray));
×
104

105
    painter.drawImage(cw * 2, 0, Gradient::getRGBGradient());
×
106
}
×
107

108
void ClickAndGoWidget::setType(int type, const QLCChannel *chan)
×
109
{
110
    m_linearColor = false;
×
111
    //qDebug() << Q_FUNC_INFO << "Type: " << type;
112
    if (type == None)
×
113
    {
114
        m_image = QImage();
×
115
    }
116
    else if (type == Red)
117
        setupGradient(Qt::black, Qt::red);
×
118
    else if (type == Green)
119
        setupGradient(Qt::black, Qt::green);
×
120
    else if (type == Blue)
121
        setupGradient(Qt::black, Qt::blue);
×
122
    else if (type == Cyan)
123
        setupGradient(Qt::white, Qt::cyan);
×
124
    else if (type == Magenta)
125
        setupGradient(Qt::white, Qt::magenta);
×
126
    else if (type == Yellow)
127
        setupGradient(Qt::white, Qt::yellow);
×
128
    else if (type == Amber)
129
        setupGradient(Qt::black, 0xFFFF7E00);
×
130
    else if (type == White)
131
        setupGradient(Qt::black, Qt::white);
×
132
    else if (type == UV)
133
        setupGradient(Qt::black, 0xFF9400D3);
×
134
    else if (type == Lime)
135
        setupGradient(Qt::black, 0xFFADFF2F);
×
136
    else if (type == Indigo)
137
        setupGradient(Qt::black, 0xFF4B0082);
×
138
    else if (type == RGB || type == CMY)
139
    {
140
        setupColorPicker();
×
141
    }
142
    else if (type == Preset)
143
    {
144
        createPresetList(chan);
×
145
        setupPresetPicker();
×
146
    }
147

148
    m_type = type;
×
149
}
×
150

151
void ClickAndGoWidget::setLevelLowLimit(int min)
×
152
{
153
    this->m_levelLowLimit = min;
×
154
}
×
155

156
void ClickAndGoWidget::setLevelHighLimit(int max)
×
157
{
158
    this->m_levelHighLimit = max;
×
159
}
×
160

161
int ClickAndGoWidget::getType()
×
162
{
163
    return m_type;
×
164
}
165

166
QString ClickAndGoWidget::clickAndGoTypeToString(ClickAndGoWidget::ClickAndGo type)
×
167
{
168
    switch (type)
×
169
    {
170
        default:
×
171
        case None: return "None"; break;
×
172
        case Red: return "Red"; break;
×
173
        case Green: return "Green"; break;
×
174
        case Blue: return "Blue"; break;
×
175
        case Cyan: return "Cyan"; break;
×
176
        case Magenta: return "Magenta"; break;
×
177
        case Yellow: return "Yellow"; break;
×
178
        case Amber: return "Amber"; break;
×
179
        case White: return "White"; break;
×
180
        case UV: return "UV"; break;
×
181
        case Lime: return "Lime"; break;
×
182
        case Indigo: return "Indigo"; break;
×
183
        case RGB: return "RGB"; break;
×
184
        case CMY: return "CMY"; break;
×
185
        case Preset: return "Preset"; break;
×
186
    }
187
}
188

189
ClickAndGoWidget::ClickAndGo ClickAndGoWidget::stringToClickAndGoType(QString str)
×
190
{
191
    if (str == "Red") return Red;
×
192
    else if (str == "Green") return Green;
×
193
    else if (str == "Blue") return Blue;
×
194
    else if (str == "Cyan") return Cyan;
×
195
    else if (str == "Magenta") return Magenta;
×
196
    else if (str == "Yellow") return Yellow;
×
197
    else if (str == "Amber") return Amber;
×
198
    else if (str == "White") return White;
×
199
    else if (str == "UV") return UV;
×
200
    else if (str == "Lime") return Lime;
×
201
    else if (str == "Indigo") return Indigo;
×
202
    else if (str == "RGB") return RGB;
×
203
    else if (str == "CMY") return CMY;
×
204
    else if (str == "Preset") return Preset;
×
205

206
    return None;
207
}
208

209
QColor ClickAndGoWidget::getColorAt(uchar pos)
×
210
{
211
    if (m_linearColor == true)
×
212
    {
213
        QRgb col = m_image.pixel(10 + pos, 10);
×
214
        return QColor(col);
×
215
    }
216
    return QColor(0,0,0);
217
}
218

219
QImage ClickAndGoWidget::getImageFromValue(uchar value)
×
220
{
221
    /** If the widget type is a Preset, return directly
222
     *  the pre-loaded resource */
223
    if (m_type == Preset)
×
224
    {
225
        foreach (PresetResource res, m_resources)
×
226
        {
227
            if (value >= res.m_resLowLimit && value <= res.m_resHighLimit)
×
228
                return res.m_thumbnail;
×
229
        }
230
    }
231

232
    QImage img(42, 42, QImage::Format_RGB32);
×
233
    if (m_type == None)
×
234
    {
235
        img.fill(Qt::black);
×
236
    }
237
    else if (m_linearColor == true)
×
238
    {
239
        QRgb col = m_image.pixel(10 + value, 10);
×
240
        img.fill(QColor(col).rgb());
×
241
    }
242

243
    return img;
244
}
×
245

246
void ClickAndGoWidget::createPresetList(const QLCChannel *chan)
×
247
{
248
    int i = 1;
249
    if (chan == NULL)
×
250
        return;
251

252
    m_title = chan->name();
×
253
    m_resources.clear();
×
254

255
    //qDebug() << Q_FUNC_INFO << "cap #" << chan->capabilities().size();
256

257
    foreach (QLCCapability* cap, chan->capabilities())
×
258
    {
259
        if (cap->presetType() == QLCCapability::Picture)
×
260
        {
261
            m_resources.append(PresetResource(cap->resource(0).toString(), cap->name(),
×
262
                                              cap->min(), cap->max()));
×
263
        }
264
        else if (cap->presetType() == QLCCapability::SingleColor)
×
265
        {
266
            QColor col1 = cap->resource(0).value<QColor>();
×
267
            m_resources.append(PresetResource(col1, QColor(), cap->name(), cap->min(), cap->max()));
×
268
        }
269
        else if (cap->presetType() == QLCCapability::DoubleColor)
×
270
        {
271
            QColor col1 = cap->resource(0).value<QColor>();
×
272
            QColor col2 = cap->resource(1).value<QColor>();
×
273
            m_resources.append(PresetResource(col1, col2, cap->name(), cap->min(), cap->max()));
×
274
        }
275
        else
276
        {
277
            m_resources.append(PresetResource(i, cap->name(), cap->min(), cap->max()));
×
278
        }
279
        i++;
×
280
    }
281
}
282

283
void ClickAndGoWidget::setupPresetPicker()
×
284
{
285
    if (m_resources.size() == 0)
×
286
        return;
×
287

288
    QScreen *scr = QGuiApplication::screens().first();
×
289
    QRect screen = scr->availableGeometry();
×
290

291
    m_cols = 2;
×
292
    m_rows = qCeil((qreal)m_resources.size() / 2);
×
293
    m_width = m_cellWidth * m_cols;
×
294
    m_height = CELL_H * m_rows + TITLE_H;
×
295

296
    // first check if the menu fits vertically
297
    if (m_height > screen.height())
×
298
    {
299
        m_rows = qFloor((qreal)screen.height() / CELL_H);
×
300
        m_cols = qCeil((qreal)m_resources.size() / m_rows);
×
301
        m_width = m_cellWidth * m_cols;
×
302
        m_height = CELL_H * m_rows + TITLE_H;
×
303
    }
304

305
    // then check if it has to be rescaled horizontally
306
    if (m_width > screen.width())
×
307
    {
308
        m_cellWidth = screen.width() / m_cols;
×
309
        m_width = m_cellWidth * m_cols;
×
310
    }
311

312
    int x = 0;
313
    int y = 0;
314
    m_image = QImage(m_width, m_height, QImage::Format_RGB32);
×
315
    QPainter painter(&m_image);
×
316
    painter.setRenderHint(QPainter::Antialiasing);
×
317
    QLinearGradient presetGrad(QPointF(0,0), QPointF(0, m_height));
×
318
    presetGrad.setColorAt(0, QApplication::palette().window().color());
×
319
    presetGrad.setColorAt(1, QColor(173, 171, 179));
×
320
    painter.fillRect(0, 0, m_width, m_height, presetGrad);
×
321

322
    // title
323
    painter.setPen(Qt::black);
×
324
    painter.drawText(x + 3, y, m_width - 3, TITLE_H, Qt::AlignVCenter | Qt::TextSingleLine, m_title);
×
325
    y += TITLE_H;
326

327
    for (int i = 0; i < m_resources.size(); i++)
×
328
    {
329
        PresetResource res = m_resources.at(i);
×
330
        if (res.m_resLowLimit > m_levelHighLimit || res.m_resHighLimit < m_levelLowLimit)
×
331
            continue;
332
        painter.setPen(Qt::black);
×
333
        painter.drawRect(x, y, m_cellWidth, CELL_H);
×
334
        painter.drawImage(x + 1, y + 4, res.m_thumbnail);
×
335
        painter.drawText(x + 43, y + 4, m_cellWidth - 42, CELL_H - 5, Qt::TextWordWrap|Qt::AlignVCenter, res.m_descr);
×
336
        if (i % m_cols == m_cols - 1)
×
337
        {
338
            y += CELL_H;
×
339
            x = 0;
340
        }
341
        else
342
            x += m_cellWidth;
×
343

344
    }
345
}
×
346

347
QSize ClickAndGoWidget::sizeHint() const
×
348
{
349
    return QSize(m_width, m_height);
×
350
}
351

352
void ClickAndGoWidget::mousePressEvent(QMouseEvent *event)
×
353
{
354
    if (m_linearColor == true)
×
355
    {
356
        if (event->pos().x() <= 10)
×
357
            emit levelChanged(0);
×
358
        else if (event->pos().x() > 10 && event->pos().x() < 256)
×
359
            emit levelChanged((uchar)(event->pos().x() - 10));
×
360
        else
361
            emit levelChanged(255);
×
362
    }
363
    else if (m_type == RGB || m_type == CMY)
×
364
    {
365
        emit colorChanged(m_image.pixel(event->pos().x(), event->pos().y()));
×
366
    }
367
    else if (m_type == Preset)
×
368
    {
369
        if (m_hoverCellIdx >= 0 && m_hoverCellIdx < m_resources.length())
×
370
        {
371
            PresetResource res = m_resources.at(m_hoverCellIdx);
×
372
            qDebug() << "Mouse press. cellW: " << m_cellBarWidth << "min: " << res.m_resLowLimit << "max:" << res.m_resHighLimit;
373

374
            float f = SCALE(float(m_cellBarWidth),
×
375
                        float(0),
376
                        float(m_cellWidth),
377
                        float(0), float(res.m_resHighLimit - res.m_resLowLimit));
378
            emit levelAndPresetChanged((uchar)f + res.m_resLowLimit, res.m_thumbnail);
×
379
        }
380
    }
381
    QWidget::mousePressEvent(event);
×
382
}
×
383

384
void ClickAndGoWidget::mouseMoveEvent(QMouseEvent *event)
×
385
{
386
    if (m_linearColor == true && event->buttons() == Qt::LeftButton)
×
387
    {
388
        if (event->pos().x() <= 10)
×
389
            emit levelChanged(0);
×
390
        else if (event->pos().x() > 10 && event->pos().x() < 256)
×
391
            emit levelChanged((uchar)(event->pos().x() - 10));
×
392
        else
393
            emit levelChanged(255);
×
394
    }
395
    else if ((m_type == RGB || m_type == CMY) && event->buttons() == Qt::LeftButton)
×
396
    {
397
        emit colorChanged(m_image.pixel(event->pos().x(), event->pos().y()));
×
398
    }
399
    else if (m_type == Preset)
×
400
    {
401
        // calculate the index of the resource where the cursor is
402
        int floorX = qFloor(event->pos().x() / m_cellWidth);
×
403
        int floorY = qFloor((event->pos().y() - TITLE_H) / CELL_H);
×
404
        int tmpCellIDx = (floorY * m_cols) + floorX;
×
405
        if (event->pos().y() < TITLE_H || tmpCellIDx < 0 || tmpCellIDx >= m_resources.length())
×
406
        {
407
            m_hoverCellIdx = -1;
×
408
            update();
×
409
            return;
×
410
        }
411
        m_cellBarXpos = floorX * m_cellWidth;
×
412
        m_cellBarYpos = floorY * CELL_H + TITLE_H;
×
413
        m_cellBarWidth = event->pos().x() - m_cellBarXpos;
×
414
        m_hoverCellIdx = tmpCellIDx;
×
415
        update();
×
416
        qDebug() << "Idx:" << m_hoverCellIdx << "X:" << m_cellBarXpos << "mX:" << event->pos().x();
417
    }
418
}
419

420
void ClickAndGoWidget::paintEvent(QPaintEvent *event)
×
421
{
422
    Q_UNUSED(event)
423

424
    QPainter painter(this);
×
425
    painter.drawImage(QPoint(0, 0), m_image);
×
426
    if (m_type == Preset && m_hoverCellIdx >= 0)
×
427
    {
428
        painter.setPen(Qt::NoPen);
×
429
        painter.setBrush(QBrush(QColor(76, 136, 255, 255)));
×
430
        painter.drawRect(m_cellBarXpos, m_cellBarYpos + 1, m_cellBarWidth, 3);
×
431
    }
432
}
×
433

434

435
ClickAndGoWidget::PresetResource::PresetResource(QString path, QString text, uchar min, uchar max)
×
436
{
437
    m_descr = text;
×
438
    m_resLowLimit = min;
×
439
    m_resHighLimit = max;
×
440
    QImage px(path);
×
441
    m_thumbnail = QImage(40, 40, QImage::Format_RGB32);
×
442
    m_thumbnail.fill(Qt::white);
×
443
    QPainter painter(&m_thumbnail);
×
444
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
×
445
    painter.drawImage(QRect(0,0,40,40), px);
×
446
    //qDebug() << "PATH: adding " << path << ", descr: " << text;
447
}
×
448

449
ClickAndGoWidget::PresetResource::PresetResource(QColor color1, QColor color2,
×
450
                                                 QString text, uchar min, uchar max)
×
451
{
452
    m_descr = text;
×
453
    m_resLowLimit = min;
×
454
    m_resHighLimit = max;
×
455
    m_thumbnail = QImage(40, 40, QImage::Format_RGB32);
×
456
    if (color2.isValid() == false)
×
457
        m_thumbnail.fill(color1.rgb());
×
458
    else
459
    {
460
        QPainter painter(&m_thumbnail);
×
461
        painter.fillRect(0, 0, 20, 40, color1);
462
        painter.fillRect(20, 0, 40, 40, color2);
463
    }
×
464
    //qDebug() << "COLOR: adding " << color1.name() << ", descr: " << text;
465
}
×
466

467
ClickAndGoWidget::PresetResource::PresetResource(int index, QString text, uchar min, uchar max)
×
468
{
469
    m_descr = text;
×
470
    m_resLowLimit = min;
×
471
    m_resHighLimit = max;
×
472
    m_thumbnail = QImage(40, 40, QImage::Format_RGB32);
×
473
    m_thumbnail.fill(Qt::white);
×
474
    QFont tfont = QApplication::font();
×
475
    tfont.setBold(true);
476
    tfont.setPixelSize(20);
×
477
    QPainter painter(&m_thumbnail);
×
478
    painter.setFont(tfont);
×
479
    painter.drawText(0, 0, 40, 40, Qt::AlignHCenter|Qt::AlignVCenter, QString("%1").arg(index));
×
480
    //qDebug() << "GENERIC: adding " << index << ", descr: " << text;
481
}
×
482

483

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