Qt Utilities  6.4.1
Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models
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 
10 namespace QtUtilities {
11 
16 class ColorButtonPrivate {
17  ColorButton *q_ptr;
18  Q_DECLARE_PUBLIC(ColorButton)
19 public:
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 
33 void 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 
41 QColor 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 
50 QPixmap 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 
82 ColorButton::ColorButton(QWidget *parent)
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 
97 {
98 }
99 
100 void 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 
108 QColor 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 
126 void 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 
159 void 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 
168 void 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
187 void 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 
199 void ColorButton::dragLeaveEvent(QDragLeaveEvent *event)
200 {
201  event->accept();
202  d_ptr->m_dragging = false;
203  update();
204 }
205 
206 void 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)
Definition: colorbutton.cpp:82
void dropEvent(QDropEvent *event) override
void setColor(const QColor &color)
void colorChanged(const QColor &color)