KWidgetsAddons

kcolorbutton.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1997 Martin Jones <mjones@kde.org>
4 SPDX-FileCopyrightText: 1999 Cristian Tibirna <ctibirna@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "kcolorbutton.h"
10
11#include <QApplication>
12#include <QClipboard>
13#include <QColorDialog>
14#include <QDrag>
15#include <QMimeData>
16#include <QMouseEvent>
17#include <QPainter>
18#include <QPointer>
19#include <QStyle>
20#include <QStyleOptionButton>
21#include <qdrawutil.h>
22
23class KColorButtonPrivate
24{
25public:
26 KColorButtonPrivate(KColorButton *qq);
27
28 void chooseColor();
29 void colorChosen();
30
31 KColorButton *q;
32 QColor m_defaultColor;
33 bool m_bdefaultColor : 1;
34 bool m_alphaChannel : 1;
35
36 QColor col;
37 QPoint mPos;
38
39 QPointer<QColorDialog> dialogPtr;
40
41 void initStyleOption(QStyleOptionButton *opt) const;
42};
43
44/////////////////////////////////////////////////////////////////////
45// Functions duplicated from KColorMimeData
46// Should be kept in sync
47void populateMimeData(QMimeData *mimeData, const QColor &color)
48{
49 mimeData->setColorData(color);
50 mimeData->setText(color.name());
51}
52
53bool canDecode(const QMimeData *mimeData)
54{
55 if (mimeData->hasColor()) {
56 return true;
57 }
58 if (mimeData->hasText()) {
59 const QString colorName = mimeData->text();
60 if ((colorName.length() >= 4) && (colorName[0] == QLatin1Char('#'))) {
61 return true;
62 }
63 }
64 return false;
65}
66
67QColor fromMimeData(const QMimeData *mimeData)
68{
69 if (mimeData->hasColor()) {
70 return mimeData->colorData().value<QColor>();
71 }
72 if (canDecode(mimeData)) {
73 return QColor(mimeData->text());
74 }
75 return QColor();
76}
77
78QDrag *createDrag(const QColor &color, QObject *dragsource)
79{
80 QDrag *drag = new QDrag(dragsource);
81 QMimeData *mime = new QMimeData;
82 populateMimeData(mime, color);
83 drag->setMimeData(mime);
84 QPixmap colorpix(25, 20);
85 colorpix.fill(color);
86 QPainter p(&colorpix);
87 p.setPen(Qt::black);
88 p.drawRect(0, 0, 24, 19);
89 p.end();
90 drag->setPixmap(colorpix);
91 drag->setHotSpot(QPoint(-5, -7));
92 return drag;
93}
94/////////////////////////////////////////////////////////////////////
95
96KColorButtonPrivate::KColorButtonPrivate(KColorButton *qq)
97 : q(qq)
98{
99 m_bdefaultColor = false;
100 m_alphaChannel = false;
101 q->setAcceptDrops(true);
102
103 QObject::connect(q, &KColorButton::clicked, q, [this]() {
104 chooseColor();
105 });
106}
107
109 : QPushButton(parent)
110 , d(new KColorButtonPrivate(this))
111{
112}
113
115 : QPushButton(parent)
116 , d(new KColorButtonPrivate(this))
117{
118 d->col = c;
119}
120
121KColorButton::KColorButton(const QColor &c, const QColor &defaultColor, QWidget *parent)
122 : QPushButton(parent)
123 , d(new KColorButtonPrivate(this))
124{
125 d->col = c;
126 setDefaultColor(defaultColor);
127}
128
129KColorButton::~KColorButton() = default;
130
131QColor KColorButton::color() const
132{
133 return d->col;
134}
135
137{
138 if (d->col != c) {
139 d->col = c;
140 update();
141 Q_EMIT changed(d->col);
142 }
143}
144
146{
147 d->m_alphaChannel = alpha;
148}
149
151{
152 return d->m_alphaChannel;
153}
154
155QColor KColorButton::defaultColor() const
156{
157 return d->m_defaultColor;
158}
159
161{
162 d->m_bdefaultColor = c.isValid();
163 d->m_defaultColor = c;
164}
165
166void KColorButtonPrivate::initStyleOption(QStyleOptionButton *opt) const
167{
168 opt->initFrom(q);
169 opt->state |= q->isDown() ? QStyle::State_Sunken : QStyle::State_Raised;
170 opt->features = QStyleOptionButton::None;
171 if (q->isDefault()) {
172 opt->features |= QStyleOptionButton::DefaultButton;
173 }
174 opt->text.clear();
175 opt->icon = QIcon();
176}
177
178void KColorButton::paintEvent(QPaintEvent *)
179{
180 QPainter painter(this);
182
183 // First, we need to draw the bevel.
184 QStyleOptionButton butOpt;
185 d->initStyleOption(&butOpt);
186 style->drawControl(QStyle::CE_PushButtonBevel, &butOpt, &painter, this);
187
188 // OK, now we can muck around with drawing out pretty little color box
189 // First, sort out where it goes
190 QRect labelRect = style->subElementRect(QStyle::SE_PushButtonContents, &butOpt, this);
191 int shift = style->pixelMetric(QStyle::PM_ButtonMargin, &butOpt, this) / 2;
192 labelRect.adjust(shift, shift, -shift, -shift);
193 int x;
194 int y;
195 int w;
196 int h;
197 labelRect.getRect(&x, &y, &w, &h);
198
199 if (isChecked() || isDown()) {
202 }
203
204 QColor fillCol = isEnabled() ? d->col : palette().color(backgroundRole());
205 qDrawShadePanel(&painter, x, y, w, h, palette(), true, 1, nullptr);
206 if (fillCol.isValid()) {
207 const QRect rect(x + 1, y + 1, w - 2, h - 2);
208 if (fillCol.alpha() < 255) {
209 QPixmap chessboardPattern(16, 16);
210 QPainter patternPainter(&chessboardPattern);
211 patternPainter.fillRect(0, 0, 8, 8, Qt::black);
212 patternPainter.fillRect(8, 8, 8, 8, Qt::black);
213 patternPainter.fillRect(0, 8, 8, 8, Qt::white);
214 patternPainter.fillRect(8, 0, 8, 8, Qt::white);
215 patternPainter.end();
216 painter.fillRect(rect, QBrush(chessboardPattern));
217 }
218 painter.fillRect(rect, fillCol);
219 }
220
221 if (hasFocus()) {
222 QRect focusRect = style->subElementRect(QStyle::SE_PushButtonFocusRect, &butOpt, this);
223 QStyleOptionFocusRect focusOpt;
224 focusOpt.initFrom(this);
225 focusOpt.rect = focusRect;
226 focusOpt.backgroundColor = palette().window().color();
227 style->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpt, &painter, this);
228 }
229}
230
231QSize KColorButton::sizeHint() const
232{
234 d->initStyleOption(&opt);
235 return style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(40, 15), this);
236}
237
238QSize KColorButton::minimumSizeHint() const
239{
241 d->initStyleOption(&opt);
242 return style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(3, 3), this);
243}
244
245void KColorButton::dragEnterEvent(QDragEnterEvent *event)
246{
247 event->setAccepted(canDecode(event->mimeData()) && isEnabled());
248}
249
250void KColorButton::dropEvent(QDropEvent *event)
251{
252 QColor c = fromMimeData(event->mimeData());
253 if (c.isValid()) {
254 setColor(c);
255 }
256}
257
258void KColorButton::keyPressEvent(QKeyEvent *e)
259{
260 int key = e->key() | e->modifiers();
261
263 QMimeData *mime = new QMimeData;
264 populateMimeData(mime, color());
266 } else if (QKeySequence::keyBindings(QKeySequence::Paste).contains(key)) {
268 setColor(color);
269 } else {
271 }
272}
273
274void KColorButton::mousePressEvent(QMouseEvent *e)
275{
276 d->mPos = e->pos();
278}
279
280void KColorButton::mouseMoveEvent(QMouseEvent *e)
281{
282 if ((e->buttons() & Qt::LeftButton) &&
283 (e->pos() - d->mPos).manhattanLength() > QApplication::startDragDistance()) {
284 createDrag(color(), this)->exec();
285 setDown(false);
286 }
287}
288
289void KColorButtonPrivate::chooseColor()
290{
291 QColorDialog *dialog = dialogPtr.data();
292 if (dialog) {
293 dialog->show();
294 dialog->raise();
295 dialog->activateWindow();
296 return;
297 }
298
299 dialog = new QColorDialog(q);
300 dialog->setCurrentColor(q->color());
301 dialog->setOption(QColorDialog::ShowAlphaChannel, m_alphaChannel);
303 QObject::connect(dialog, &QDialog::accepted, q, [this]() {
304 colorChosen();
305 });
306 dialogPtr = dialog;
307 dialog->show();
308}
309
310void KColorButtonPrivate::colorChosen()
311{
312 QColorDialog *dialog = dialogPtr.data();
313 if (!dialog) {
314 return;
315 }
316
317 if (dialog->selectedColor().isValid()) {
318 q->setColor(dialog->selectedColor());
319 } else if (m_bdefaultColor) {
320 q->setColor(m_defaultColor);
321 }
322}
323
324#include "moc_kcolorbutton.cpp"
A pushbutton to display or allow user selection of a color.
void setDefaultColor(const QColor &c)
Sets the default color to c.
KColorButton(QWidget *parent=nullptr)
Creates a color button.
void changed(const QColor &newColor)
Emitted when the color of the widget is changed, either with setColor() or via user selection.
void setColor(const QColor &c)
Sets the current color to c.
bool isAlphaChannelEnabled() const
Returns true if the user is allowed to change the alpha component.
void setAlphaChannelEnabled(bool alpha)
When set to true, allow the user to change the alpha component of the color.
KCALUTILS_EXPORT bool fromMimeData(const QMimeData *e, const KCalendarCore::Calendar::Ptr &cal)
KCALUTILS_EXPORT bool canDecode(const QMimeData *)
KCALUTILS_EXPORT bool populateMimeData(QMimeData *e, const KCalendarCore::Calendar::Ptr &cal)
KGUIADDONS_EXPORT QDrag * createDrag(const QColor &color, QObject *dragsource)
bool isChecked() const const
void clicked(bool checked)
bool isDown() const const
virtual void mousePressEvent(QMouseEvent *e) override
void setMimeData(QMimeData *src, Mode mode)
int alpha() const const
bool isValid() const const
QString name(NameFormat format) const const
void setCurrentColor(const QColor &color)
QColor selectedColor() const const
void setOption(ColorDialogOption option, bool on)
void accepted()
Qt::DropAction exec(Qt::DropActions supportedActions)
void setHotSpot(const QPoint &hotspot)
void setMimeData(QMimeData *data)
void setPixmap(const QPixmap &pixmap)
QClipboard * clipboard()
int key() const const
Qt::KeyboardModifiers modifiers() const const
QList< QKeySequence > keyBindings(StandardKey key)
QVariant colorData() const const
bool hasColor() const const
bool hasText() const const
void setColorData(const QVariant &color)
void setText(const QString &text)
QString text() const const
QPoint pos() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T * data() const const
bool isDefault() const const
virtual bool event(QEvent *e) override
virtual void keyPressEvent(QKeyEvent *e) override
void adjust(int dx1, int dy1, int dx2, int dy2)
void getRect(int *x, int *y, int *width, int *height) const const
Qt::MouseButtons buttons() const const
qsizetype length() const const
CE_PushButtonBevel
PE_FrameFocusRect
SE_PushButtonContents
virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
virtual QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const=0
virtual QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const const=0
void initFrom(const QWidget *widget)
LeftButton
WA_DeleteOnClose
T value() const const
void activateWindow()
QPalette::ColorRole backgroundRole() const const
bool isEnabled() const const
bool hasFocus() const const
void raise()
void setAttribute(Qt::WidgetAttribute attribute, bool on)
void show()
QStyle * style() const const
void update()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:09:51 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.