1 // SPDX-License-Identifier: GPL-3.0-or-later
2 // SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
3 
4 #include "colorpicker.h"
5 #include "src/utils/confighandler.h"
6 #include "src/utils/globalvalues.h"
7 #include <QMouseEvent>
8 #include <QPainter>
9 
ColorPicker(QWidget * parent)10 ColorPicker::ColorPicker(QWidget* parent)
11   : QWidget(parent)
12 {
13     ConfigHandler config;
14     m_colorList = config.getUserColors();
15     m_colorAreaSize = GlobalValues::buttonBaseSize() * 0.6;
16     setMouseTracking(true);
17     // save the color values in member variables for faster access
18     m_uiColor = config.uiMainColorValue();
19     m_drawColor = config.drawColorValue();
20     // extraSize represents the extra space needed for the highlight of the
21     // selected color.
22     const int extraSize = 6;
23     double radius = (m_colorList.size() * m_colorAreaSize / 1.3) / 3.141592;
24     resize(radius * 2 + m_colorAreaSize + extraSize,
25            radius * 2 + m_colorAreaSize + extraSize);
26     double degree = 360 / (m_colorList.size());
27     double degreeAcum = degree;
28     // this line is the radius of the circle which will be rotated to add
29     // the color components.
30     QLineF baseLine =
31       QLineF(QPoint(radius + extraSize / 2, radius + extraSize / 2),
32              QPoint(radius * 2, radius));
33 
34     for (int i = 0; i < m_colorList.size(); ++i) {
35         m_colorAreaList.append(QRect(
36           baseLine.x2(), baseLine.y2(), m_colorAreaSize, m_colorAreaSize));
37         baseLine.setAngle(degreeAcum);
38         degreeAcum += degree;
39     }
40 }
41 
show()42 void ColorPicker::show()
43 {
44     grabMouse();
45     QWidget::show();
46 }
47 
hide()48 void ColorPicker::hide()
49 {
50     releaseMouse();
51     QWidget::hide();
52 }
53 
paintEvent(QPaintEvent *)54 void ColorPicker::paintEvent(QPaintEvent*)
55 {
56     QPainter painter(this);
57     painter.setRenderHint(QPainter::Antialiasing);
58 
59     QVector<QRect> rects = handleMask();
60     painter.setPen(QColor(Qt::black));
61     for (int i = 0; i < rects.size(); ++i) {
62         // draw the highlight when we have to draw the selected color
63         if (m_drawColor == QColor(m_colorList.at(i))) {
64             QColor c = QColor(m_uiColor);
65             c.setAlpha(155);
66             painter.setBrush(c);
67             c.setAlpha(100);
68             painter.setPen(c);
69             QRect highlight = rects.at(i);
70             highlight.moveTo(highlight.x() - 3, highlight.y() - 3);
71             highlight.setHeight(highlight.height() + 6);
72             highlight.setWidth(highlight.width() + 6);
73             painter.drawRoundedRect(highlight, 100, 100);
74             painter.setPen(QColor(Qt::black));
75         }
76 
77         // draw available colors
78         if (m_colorList.at(i).isValid()) {
79             // draw preset color
80             painter.setBrush(QColor(m_colorList.at(i)));
81             painter.drawRoundedRect(rects.at(i), 100, 100);
82         } else {
83             // draw rainbow (part) for custom color
84             QRect lastRect = rects.at(i);
85             int nStep = 1;
86             int nSteps = lastRect.height() / nStep;
87             // 0.02 - start rainbow color, 0.33 - end rainbow color from range:
88             // 0.0 - 1.0
89             float h = 0.02;
90             for (int radius = nSteps; radius > 0; radius -= nStep * 2) {
91                 // calculate color
92                 float fHStep = (0.33 - h) / (nSteps / nStep / 2);
93                 QColor color = QColor::fromHslF(h, 0.95, 0.5);
94 
95                 // set color and draw circle
96                 painter.setPen(color);
97                 painter.setBrush(color);
98                 painter.drawRoundedRect(lastRect, 100, 100);
99 
100                 // set next color, circle geometry
101                 h += fHStep;
102                 lastRect.setX(lastRect.x() + nStep);
103                 lastRect.setY(lastRect.y() + nStep);
104                 lastRect.setHeight(lastRect.height() - nStep);
105                 lastRect.setWidth(lastRect.width() - nStep);
106             }
107         }
108     }
109 }
110 
mouseMoveEvent(QMouseEvent * e)111 void ColorPicker::mouseMoveEvent(QMouseEvent* e)
112 {
113     for (int i = 0; i < m_colorList.size(); ++i) {
114         if (m_colorAreaList.at(i).contains(e->pos())) {
115             m_drawColor = m_colorList.at(i);
116             emit colorSelected(m_drawColor);
117             update();
118             break;
119         }
120     }
121 }
122 
handleMask() const123 QVector<QRect> ColorPicker::handleMask() const
124 {
125     QVector<QRect> areas;
126     for (const QRect& rect : m_colorAreaList) {
127         areas.append(rect);
128     }
129     return areas;
130 }
131