Qt Utilities 6.14.0
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
Loading...
Searching...
No Matches
colorbutton.cpp
Go to the documentation of this file.
1#include "./colorbutton.h"
2
3#include <QApplication>
4#include <QColorDialog>
5#include <QDrag>
6#include <QDragEnterEvent>
7#include <QMimeData>
8#include <QPainter>
9
10namespace QtUtilities {
11
16class ColorButtonPrivate {
17 ColorButton *q_ptr;
18 Q_DECLARE_PUBLIC(ColorButton)
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 ColorButtonPrivate::slotEditColor()
34{
35 const QColor newColor = QColorDialog::getColor(m_color, q_ptr, QString(), QColorDialog::ShowAlphaChannel);
36 if (!newColor.isValid() || newColor == q_ptr->color())
37 return;
38 q_ptr->setColor(newColor);
39}
40
41QColor ColorButtonPrivate::shownColor() const
42{
43#ifndef QT_NO_DRAGANDDROP
44 if (m_dragging)
45 return m_dragColor;
46#endif
47 return m_color;
48}
49
50QPixmap ColorButtonPrivate::generatePixmap() const
51{
52 QPixmap pix(24, 24);
53
54 int pixSize = 20;
55 QBrush br(shownColor());
56
57 QPixmap pm(2 * pixSize, 2 * pixSize);
58 QPainter pmp(&pm);
59 pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
60 pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
61 pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
62 pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
63 pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, shownColor());
64 br = QBrush(pm);
65
66 QPainter p(&pix);
67 int corr = 1;
68 QRect r = pix.rect().adjusted(corr, corr, -corr, -corr);
69 p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
70 p.fillRect(r, br);
71
72 p.fillRect(r.width() / 4 + corr, r.height() / 4 + corr, r.width() / 2, r.height() / 2, QColor(shownColor().rgb()));
73 p.drawRect(pix.rect().adjusted(0, 0, -1, -1));
74
75 return pix;
76}
77
83 : QToolButton(parent)
84 , d_ptr(new ColorButtonPrivate)
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(this, SIGNAL(clicked()), this, SLOT(slotEditColor()));
93 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
94}
95
99
100void ColorButton::setColor(const QColor &color)
101{
102 if (d_ptr->m_color == color)
103 return;
104 update();
105 emit colorChanged(d_ptr->m_color = color);
106}
107
108QColor ColorButton::color() const
109{
110 return d_ptr->m_color;
111}
112
114{
115 if (d_ptr->m_backgroundCheckered == checkered)
116 return;
117 d_ptr->m_backgroundCheckered = checkered;
118 update();
119}
120
122{
123 return d_ptr->m_backgroundCheckered;
124}
125
126void ColorButton::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(0, 0, pixSize, pixSize, Qt::white);
138 pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
139 pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
140 pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
141 pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, d_ptr->shownColor());
142 br = QBrush(pm);
143 }
144
145 QPainter p(this);
146 const int corr = 4;
147 QRect r = rect().adjusted(corr, corr, -corr, -corr);
148 p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
149 p.fillRect(r, br);
150
151 const QColor frameColor1(0, 0, 0, 26);
152 p.setPen(frameColor1);
153 p.drawRect(r.adjusted(1, 1, -2, -2));
154 const QColor frameColor2(0, 0, 0, 51);
155 p.setPen(frameColor2);
156 p.drawRect(r.adjusted(0, 0, -1, -1));
157}
158
159void ColorButton::mousePressEvent(QMouseEvent *event)
160{
161#ifndef QT_NO_DRAGANDDROP
162 if (event->button() == Qt::LeftButton)
163 d_ptr->m_dragStart = event->pos();
164#endif
165 QToolButton::mousePressEvent(event);
166}
167
168void ColorButton::mouseMoveEvent(QMouseEvent *event)
169{
170#ifndef QT_NO_DRAGANDDROP
171 if (event->buttons() & Qt::LeftButton && (d_ptr->m_dragStart - event->pos()).manhattanLength() > QApplication::startDragDistance()) {
172 auto *const mime = new QMimeData;
173 mime->setColorData(color());
174 auto *const drg = new QDrag(this);
175 drg->setMimeData(mime);
176 drg->setPixmap(d_ptr->generatePixmap());
177 setDown(false);
178 event->accept();
179 drg->exec(Qt::CopyAction);
180 return;
181 }
182#endif
183 QToolButton::mouseMoveEvent(event);
184}
185
186#ifndef QT_NO_DRAGANDDROP
187void ColorButton::dragEnterEvent(QDragEnterEvent *event)
188{
189 const QMimeData *mime = event->mimeData();
190 if (!mime->hasColor())
191 return;
192
193 event->accept();
194 d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
195 d_ptr->m_dragging = true;
196 update();
197}
198
199void ColorButton::dragLeaveEvent(QDragLeaveEvent *event)
200{
201 event->accept();
202 d_ptr->m_dragging = false;
203 update();
204}
205
206void ColorButton::dropEvent(QDropEvent *event)
207{
208 event->accept();
209 d_ptr->m_dragging = false;
210 if (d_ptr->m_dragColor == color())
211 return;
212 setColor(d_ptr->m_dragColor);
213}
214#endif
215} // namespace QtUtilities
216
217#include "moc_colorbutton.cpp"
bool isBackgroundCheckered() const
void dragLeaveEvent(QDragLeaveEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void paintEvent(QPaintEvent *event) override
void setBackgroundCheckered(bool checkered)
void mousePressEvent(QMouseEvent *event) override
void dragEnterEvent(QDragEnterEvent *event) override
ColorButton(QWidget *parent=nullptr)
void dropEvent(QDropEvent *event) override
void setColor(const QColor &color)
void colorChanged(const QColor &color)