1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtcolorbutton.h"
5#include <QtWidgets/QColorDialog>
6#include <QtGui/QPainter>
7#include <QtCore/QMimeData>
8#include <QtGui/QDragEnterEvent>
9#include <QtGui/QDrag>
10#include <QtWidgets/QApplication>
11
12QT_BEGIN_NAMESPACE
13
14class QtColorButtonPrivate : public QObject
15{
16 Q_OBJECT
17 QtColorButton *q_ptr;
18 Q_DECLARE_PUBLIC(QtColorButton)
19public:
20 QColor m_color;
21#ifndef QT_NO_DRAGANDDROP
22 QColor m_dragColor;
23 QPoint m_dragStart;
24 bool m_dragging;
25#endif
26 bool m_backgroundCheckered;
27
28 void slotEditColor();
29 QColor shownColor() const;
30 QPixmap generatePixmap() const;
31};
32
33void QtColorButtonPrivate::slotEditColor()
34{
35 const QColor newColor = QColorDialog::getColor(initial: m_color, parent: q_ptr, title: QString(), options: QColorDialog::ShowAlphaChannel);
36 if (!newColor.isValid() || newColor == q_ptr->color())
37 return;
38 q_ptr->setColor(newColor);
39 emit q_ptr->colorChanged(color: m_color);
40}
41
42QColor QtColorButtonPrivate::shownColor() const
43{
44#ifndef QT_NO_DRAGANDDROP
45 if (m_dragging)
46 return m_dragColor;
47#endif
48 return m_color;
49}
50
51QPixmap QtColorButtonPrivate::generatePixmap() const
52{
53 QPixmap pix(24, 24);
54
55 int pixSize = 20;
56 QBrush br(shownColor());
57
58 QPixmap pm(2 * pixSize, 2 * pixSize);
59 QPainter pmp(&pm);
60 pmp.fillRect(x: 0, y: 0, w: pixSize, h: pixSize, c: Qt::lightGray);
61 pmp.fillRect(x: pixSize, y: pixSize, w: pixSize, h: pixSize, c: Qt::lightGray);
62 pmp.fillRect(x: 0, y: pixSize, w: pixSize, h: pixSize, c: Qt::darkGray);
63 pmp.fillRect(x: pixSize, y: 0, w: pixSize, h: pixSize, c: Qt::darkGray);
64 pmp.fillRect(x: 0, y: 0, w: 2 * pixSize, h: 2 * pixSize, b: shownColor());
65 br = QBrush(pm);
66
67 QPainter p(&pix);
68 int corr = 1;
69 QRect r = pix.rect().adjusted(xp1: corr, yp1: corr, xp2: -corr, yp2: -corr);
70 p.setBrushOrigin(x: (r.width() % pixSize + pixSize) / 2 + corr, y: (r.height() % pixSize + pixSize) / 2 + corr);
71 p.fillRect(r, br);
72
73 p.fillRect(x: r.width() / 4 + corr, y: r.height() / 4 + corr,
74 w: r.width() / 2, h: r.height() / 2,
75 b: QColor(shownColor().rgb()));
76 p.drawRect(r: pix.rect().adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
77
78 return pix;
79}
80
81///////////////
82
83QtColorButton::QtColorButton(QWidget *parent)
84 : QToolButton(parent), d_ptr(new QtColorButtonPrivate)
85{
86 d_ptr->q_ptr = this;
87 d_ptr->m_dragging = false;
88 d_ptr->m_backgroundCheckered = true;
89
90 setAcceptDrops(true);
91
92 connect(sender: this, signal: &QToolButton::clicked, context: d_ptr.data(), slot: &QtColorButtonPrivate::slotEditColor);
93 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
94}
95
96QtColorButton::~QtColorButton()
97{
98}
99
100void QtColorButton::setColor(const QColor &color)
101{
102 if (d_ptr->m_color == color)
103 return;
104 d_ptr->m_color = color;
105 update();
106}
107
108QColor QtColorButton::color() const
109{
110 return d_ptr->m_color;
111}
112
113void QtColorButton::setBackgroundCheckered(bool checkered)
114{
115 if (d_ptr->m_backgroundCheckered == checkered)
116 return;
117 d_ptr->m_backgroundCheckered = checkered;
118 update();
119}
120
121bool QtColorButton::isBackgroundCheckered() const
122{
123 return d_ptr->m_backgroundCheckered;
124}
125
126void QtColorButton::paintEvent(QPaintEvent *event)
127{
128 QToolButton::paintEvent(event);
129 if (!isEnabled())
130 return;
131
132 const int pixSize = 10;
133 QBrush br(d_ptr->shownColor());
134 if (d_ptr->m_backgroundCheckered) {
135 QPixmap pm(2 * pixSize, 2 * pixSize);
136 QPainter pmp(&pm);
137 pmp.fillRect(x: 0, y: 0, w: pixSize, h: pixSize, c: Qt::white);
138 pmp.fillRect(x: pixSize, y: pixSize, w: pixSize, h: pixSize, c: Qt::white);
139 pmp.fillRect(x: 0, y: pixSize, w: pixSize, h: pixSize, c: Qt::black);
140 pmp.fillRect(x: pixSize, y: 0, w: pixSize, h: pixSize, c: Qt::black);
141 pmp.fillRect(x: 0, y: 0, w: 2 * pixSize, h: 2 * pixSize, b: d_ptr->shownColor());
142 br = QBrush(pm);
143 }
144
145 QPainter p(this);
146 const int corr = 4;
147 QRect r = rect().adjusted(xp1: corr, yp1: corr, xp2: -corr, yp2: -corr);
148 p.setBrushOrigin(x: (r.width() % pixSize + pixSize) / 2 + corr, y: (r.height() % pixSize + pixSize) / 2 + corr);
149 p.fillRect(r, br);
150
151 //const int adjX = qRound(r.width() / 4.0);
152 //const int adjY = qRound(r.height() / 4.0);
153 //p.fillRect(r.adjusted(adjX, adjY, -adjX, -adjY),
154 // QColor(d_ptr->shownColor().rgb()));
155 /*
156 p.fillRect(r.adjusted(0, r.height() * 3 / 4, 0, 0),
157 QColor(d_ptr->shownColor().rgb()));
158 p.fillRect(r.adjusted(0, 0, 0, -r.height() * 3 / 4),
159 QColor(d_ptr->shownColor().rgb()));
160 */
161 /*
162 const QColor frameColor0(0, 0, 0, qRound(0.2 * (0xFF - d_ptr->shownColor().alpha())));
163 p.setPen(frameColor0);
164 p.drawRect(r.adjusted(adjX, adjY, -adjX - 1, -adjY - 1));
165 */
166
167 const QColor frameColor1(0, 0, 0, 26);
168 p.setPen(frameColor1);
169 p.drawRect(r: r.adjusted(xp1: 1, yp1: 1, xp2: -2, yp2: -2));
170 const QColor frameColor2(0, 0, 0, 51);
171 p.setPen(frameColor2);
172 p.drawRect(r: r.adjusted(xp1: 0, yp1: 0, xp2: -1, yp2: -1));
173}
174
175void QtColorButton::mousePressEvent(QMouseEvent *event)
176{
177#ifndef QT_NO_DRAGANDDROP
178 if (event->button() == Qt::LeftButton)
179 d_ptr->m_dragStart = event->pos();
180#endif
181 QToolButton::mousePressEvent(event);
182}
183
184void QtColorButton::mouseMoveEvent(QMouseEvent *event)
185{
186#ifndef QT_NO_DRAGANDDROP
187 if (event->buttons() & Qt::LeftButton &&
188 (d_ptr->m_dragStart - event->pos()).manhattanLength() > QApplication::startDragDistance()) {
189 QMimeData *mime = new QMimeData;
190 mime->setColorData(color());
191 QDrag *drg = new QDrag(this);
192 drg->setMimeData(mime);
193 drg->setPixmap(d_ptr->generatePixmap());
194 setDown(false);
195 event->accept();
196 drg->exec(supportedActions: Qt::CopyAction);
197 return;
198 }
199#endif
200 QToolButton::mouseMoveEvent(e: event);
201}
202
203#ifndef QT_NO_DRAGANDDROP
204void QtColorButton::dragEnterEvent(QDragEnterEvent *event)
205{
206 const QMimeData *mime = event->mimeData();
207 if (!mime->hasColor())
208 return;
209
210 event->accept();
211 d_ptr->m_dragColor = qvariant_cast<QColor>(v: mime->colorData());
212 d_ptr->m_dragging = true;
213 update();
214}
215
216void QtColorButton::dragLeaveEvent(QDragLeaveEvent *event)
217{
218 event->accept();
219 d_ptr->m_dragging = false;
220 update();
221}
222
223void QtColorButton::dropEvent(QDropEvent *event)
224{
225 event->accept();
226 d_ptr->m_dragging = false;
227 if (d_ptr->m_dragColor == color())
228 return;
229 setColor(d_ptr->m_dragColor);
230 emit colorChanged(color: color());
231}
232#endif
233
234QT_END_NAMESPACE
235
236#include "qtcolorbutton.moc"
237

source code of qttools/src/shared/qtgradienteditor/qtcolorbutton.cpp