Krita Source Code Documentation
Loading...
Searching...
No Matches
KoDualColorButton.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 SPDX-FileCopyrightText: 1999 Daniel M. Duley <mosfet@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-only
5*/
6
7#include "KoDualColorButton.h"
8#include "KoColor.h"
10#include <kcolormimedata.h>
11#include <kconfiggroup.h>
12#include <ksharedconfig.h>
13
14#include "dcolorarrow.xbm"
15#include "dcolorreset.xpm"
16
17#include <QColorDialog>
19
20#include "kis_signals_blocker.h"
21
22#include <QBrush>
23#include <QDrag>
24#include <QDragEnterEvent>
25#include <QPainter>
26#include <QPointer>
27#include <qdrawutil.h>
28#include <QApplication>
30
31
32class Q_DECL_HIDDEN KoDualColorButton::Private
33{
34public:
35 Private(const KoColor &fgColor, const KoColor &bgColor,
36 QWidget *_dialogParent,
37 const KoColorDisplayRendererInterface *_displayRenderer)
38 : dialogParent(_dialogParent)
39 , dragFlag( false )
40 , miniCtlFlag( false )
41 , foregroundColor(fgColor)
42 , backgroundColor(bgColor)
43
44 , displayRenderer(_displayRenderer)
45 {
46 updateArrows();
47 resetPixmap = QPixmap( (const char **)dcolorreset_xpm );
48
49 popDialog = true;
50 }
51
52 void updateArrows() {
53 arrowBitmap = QPixmap(12,12);
54 arrowBitmap.fill(Qt::transparent);
55
56 QPainter p(&arrowBitmap);
57 p.setPen(dialogParent->palette().windowText().color());
58
59 // arrow pointing left
60 p.drawLine(0, 3, 7, 3);
61 p.drawLine(1, 2, 1, 4);
62 p.drawLine(2, 1, 2, 5);
63 p.drawLine(3, 0, 3, 6);
64
65 // arrow pointing down
66 p.drawLine(8, 4, 8, 11);
67 p.drawLine(5, 8, 11, 8);
68 p.drawLine(6, 9, 10, 9);
69 p.drawLine(7, 10, 9, 10);
70 }
71
72 QWidget* dialogParent;
73
74 QPixmap arrowBitmap;
75 QPixmap resetPixmap;
76 bool dragFlag, miniCtlFlag;
84 std::optional<ColorDialogState> colorDialogState;
85
90
92};
93
94void KoDualColorButton::Private::init(KoDualColorButton *q)
95{
96 if ( q->sizeHint().isValid() )
97 q->setMinimumSize( q->sizeHint() );
98
99 q->setAcceptDrops( true );
100 QString caption = i18n("Select a Color");
102 config.modal = false;
103 colorSelectorDialog = new KisDlgInternalColorSelector(q, foregroundColor, config, caption, displayRenderer);
104 connect(colorSelectorDialog, &KisDlgInternalColorSelector::finished, q, &KoDualColorButton::slotColorDialogClosed);
105}
106
107KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent, QWidget* dialogParent )
108 : QWidget( parent ),
109 d( new Private(foregroundColor, backgroundColor,
110 dialogParent,
112{
113 d->init(this);
114}
115
116KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor,
117 const KoColorDisplayRendererInterface *displayRenderer,
118 QWidget *parent, QWidget* dialogParent)
119 : QWidget( parent ),
120 d( new Private(foregroundColor, backgroundColor,
121 dialogParent,
122 displayRenderer) )
123{
124 d->init(this);
125}
126
131
133{
134 return d->foregroundColor;
135}
136
138{
139 return d->backgroundColor;
140}
141
143{
144 return d->popDialog;
145}
146
148{
149 return QSize(34, 34);
150}
151
153{
154 d->foregroundColor = color;
155 if (d->colorDialogState && d->colorDialogState->selection == Foreground) {
160 KisSignalsBlocker b(d->colorSelectorDialog);
161 d->colorSelectorDialog->slotColorUpdated(color);
162 }
163 update();
164}
165
167{
168 d->backgroundColor = color;
169
170 if (d->colorDialogState && d->colorDialogState->selection == Background) {
175 KisSignalsBlocker b(d->colorSelectorDialog);
176 d->colorSelectorDialog->slotColorUpdated(color);
177 }
178
179 update();
180}
181
183{
184 if (d->displayRenderer && d->displayRenderer != KoDumbColorDisplayRenderer::instance()) {
185 d->displayRenderer->disconnect(this);
186 }
187 if (displayRenderer) {
188 d->displayRenderer = displayRenderer;
189 d->colorSelectorDialog->setDisplayRenderer(displayRenderer);
190 connect(d->displayRenderer, SIGNAL(destroyed()), this, SLOT(setDisplayRenderer()), Qt::UniqueConnection);
191 connect(d->displayRenderer, SIGNAL(displayConfigurationChanged()), this, SLOT(update()));
192 } else {
193 d->displayRenderer = KoDumbColorDisplayRenderer::instance();
194 }
195}
196
198{
199 d->colorSelectorDialog->lockUsedColorSpace(cs);
200}
201
203{
204 QColor col;
205 if (d->displayRenderer) {
206 c.convertTo(d->displayRenderer->getPaintingColorSpace());
207 col = d->displayRenderer->toQColor(c);
208 } else {
209 col = c.toQColor();
210 }
211 return col;
212}
213
215{
216 d->popDialog = popDialog;
217}
218
219void KoDualColorButton::metrics( QRect &foregroundRect, QRect &backgroundRect )
220{
221 foregroundRect = QRect( 0, 0, width() - 14, height() - 14 );
222 backgroundRect = QRect( 14, 14, width() - 14, height() - 14 );
223}
224
226{
227 QRect foregroundRect;
228 QRect backgroundRect;
229
230 QPainter painter( this );
231
232 metrics( foregroundRect, backgroundRect );
233
234 QBrush defBrush = palette().brush( QPalette::Button );
235 QBrush foregroundBrush( getColorFromDisplayRenderer(d->foregroundColor), Qt::SolidPattern );
236 QBrush backgroundBrush( getColorFromDisplayRenderer(d->backgroundColor), Qt::SolidPattern );
237
238 qDrawShadeRect( &painter, backgroundRect, palette(), false, 1, 0,
239 isEnabled() ? &backgroundBrush : &defBrush );
240
241 qDrawShadeRect( &painter, foregroundRect, palette(), false, 1, 0,
242 isEnabled() ? &foregroundBrush : &defBrush );
243
244 painter.setPen( palette().color( QPalette::Shadow ) );
245
246 painter.drawPixmap( foregroundRect.right() + 2, 1, d->arrowBitmap );
247 painter.drawPixmap( 1, foregroundRect.bottom() + 2, d->resetPixmap );
248}
249
250void KoDualColorButton::dragEnterEvent( QDragEnterEvent *event )
251{
252 event->setAccepted( isEnabled() && KColorMimeData::canDecode( event->mimeData() ) );
253}
254
255void KoDualColorButton::dropEvent( QDropEvent *event )
256{
257 Q_UNUSED(event);
258 /* QColor color = KColorMimeData::fromMimeData( event->mimeData() );
259
260 if ( color.isValid() ) {
261 if ( d->selection == Foreground ) {
262 d->foregroundColor = color;
263 Q_EMIT foregroundColorChanged( color );
264 } else {
265 d->backgroundColor = color;
266 Q_EMIT backgroundColorChanged( color );
267 }
268
269 update();
270 }
271*/
272}
273
275{
276 d->foregroundColor = color;
277 update();
278 Q_EMIT foregroundColorChanged(d->foregroundColor);
279}
280
282{
283 d->backgroundColor = color;
284 update();
285 Q_EMIT backgroundColorChanged(d->backgroundColor);
286}
287
289{
290 d->colorDialogState = std::nullopt;
291}
292
294{
295 d->colorDialogState.emplace();
296 d->colorDialogState->selection = Foreground;
297 // TODO: fix cyclic connections in a proper way
298 d->colorDialogState->connections.addUniqueConnection(d->colorSelectorDialog, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotSetForegroundColorFromDialog(KoColor)));
299 d->colorDialogState->connections.addUniqueConnection(this, SIGNAL(foregroundColorChanged(KoColor)), d->colorSelectorDialog, SLOT(slotColorUpdated(KoColor)));
300 d->colorSelectorDialog->slotColorUpdated(d->foregroundColor);
301 d->colorSelectorDialog->setPreviousColor(d->foregroundColor);
302 d->colorSelectorDialog->show();
303 update();
304}
305
307{
308 d->colorDialogState.emplace();
309 d->colorDialogState->selection = Background;
310 // TODO: fix cyclic connections in a proper way
311 d->colorDialogState->connections.addUniqueConnection(d->colorSelectorDialog, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotSetBackgroundColorFromDialog(KoColor)));
312 d->colorDialogState->connections.addUniqueConnection(this, SIGNAL(backgroundColorChanged(KoColor)), d->colorSelectorDialog, SLOT(slotColorUpdated(KoColor)));
313 d->colorSelectorDialog->slotColorUpdated(d->backgroundColor);
314 d->colorSelectorDialog->setPreviousColor(d->backgroundColor);
315 d->colorSelectorDialog->show();
316 update();
317}
318
319void KoDualColorButton::mousePressEvent( QMouseEvent *event )
320{
321 QRect foregroundRect;
322 QRect backgroundRect;
323
324 metrics( foregroundRect, backgroundRect );
325
326 d->dragPosition = event->pos();
327
328 d->dragFlag = false;
329
330 if ( foregroundRect.contains( d->dragPosition ) ) {
331 d->tmpSelection = Foreground;
332 d->miniCtlFlag = false;
333 }
334 else if( backgroundRect.contains( d->dragPosition ) ) {
335 d->tmpSelection = Background;
336 d->miniCtlFlag = false;
337 }
338 else if ( event->pos().x() > foregroundRect.width() ) {
339 // We handle the swap and reset controls as soon as the mouse is
340 // is pressed and ignore further events on this click (mosfet).
341
342 KoColor tmp = d->foregroundColor;
343 d->foregroundColor = d->backgroundColor;
344 d->backgroundColor = tmp;
345
346 Q_EMIT backgroundColorChanged( d->backgroundColor );
347 Q_EMIT foregroundColorChanged( d->foregroundColor );
348
349 d->miniCtlFlag = true;
350 }
351 else if ( event->pos().x() < backgroundRect.x() ) {
352 d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black);
353 d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white);
354
355 Q_EMIT backgroundColorChanged( d->backgroundColor );
356 Q_EMIT foregroundColorChanged( d->foregroundColor );
357
358 d->miniCtlFlag = true;
359 }
360 update();
361}
362
363
364void KoDualColorButton::mouseMoveEvent( QMouseEvent *event )
365{
366 if ( !d->miniCtlFlag ) {
367 int delay = QApplication::startDragDistance();
368
369 if ( event->x() >= d->dragPosition.x() + delay || event->x() <= d->dragPosition.x() - delay ||
370 event->y() >= d->dragPosition.y() + delay || event->y() <= d->dragPosition.y() - delay ) {
371 KColorMimeData::createDrag( d->tmpSelection == Foreground ?
372 getColorFromDisplayRenderer(d->foregroundColor) :
373 getColorFromDisplayRenderer(d->backgroundColor),
374 this )->exec();
375 d->dragFlag = true;
376 }
377 }
378}
379
380void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event )
381{
382 d->dragFlag = false;
383
384 if ( d->miniCtlFlag )
385 return;
386
387 d->miniCtlFlag = false;
388
389 QRect foregroundRect;
390 QRect backgroundRect;
391 metrics( foregroundRect, backgroundRect );
392
393 KConfigGroup cfg = KSharedConfig::openConfig()->group("colorselector");
394 bool usePlatformDialog = cfg.readEntry("UsePlatformColorDialog", false);
395
396 if (foregroundRect.contains( event->pos())) {
397 if (d->tmpSelection == Foreground) {
398 if (d->popDialog) {
399 if (usePlatformDialog) {
400 QColor c = d->foregroundColor.toQColor();
401 c = QColorDialog::getColor(c, this);
402 if (c.isValid()) {
403 d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
404 Q_EMIT foregroundColorChanged(d->foregroundColor);
405 }
406 }
407 else {
409 }
410 }
411 }
412 else {
413 d->foregroundColor = d->backgroundColor;
414 Q_EMIT foregroundColorChanged( d->foregroundColor );
415 }
416 }
417 else if (backgroundRect.contains( event->pos())) {
418 if(d->tmpSelection == Background ) {
419 if( d->popDialog) {
420 if (usePlatformDialog) {
421 QColor c = d->backgroundColor.toQColor();
422 c = QColorDialog::getColor(c, this);
423 if (c.isValid()) {
424 d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
425 Q_EMIT backgroundColorChanged(d->backgroundColor);
426 }
427 }
428 else {
430 }
431 }
432 } else {
433 d->backgroundColor = d->foregroundColor;
434 Q_EMIT backgroundColorChanged( d->backgroundColor );
435 }
436 }
437
438 update();
439}
440
442{
443 QWidget::changeEvent(event);
444
445 switch (event->type()) {
446 case QEvent::StyleChange:
447 case QEvent::PaletteChange:
448 d->updateArrows();
449 default:
450 break;
451 }
452}
453
454bool KoDualColorButton::event(QEvent *event)
455{
456 if (event->type() == QEvent::ToolTip) {
457 QRect foregroundRect;
458 QRect backgroundRect;
459 metrics( foregroundRect, backgroundRect );
460
461 const QHelpEvent *helpEvent = static_cast<QHelpEvent*>(event);
462
463 if (this->mapFromGlobal(helpEvent->globalPos()).x() < backgroundRect.x() ) {
464 if (this->mapFromGlobal(helpEvent->globalPos()).y() < backgroundRect.y()){
465 this->setToolTip(i18n("Foreground color selector"));
466 }
467 else{
468 this->setToolTip(i18n("Set foreground and background colors to black and white"));
469 }
470 }
471 else {
472 if (this->mapFromGlobal(helpEvent->globalPos()).y() < backgroundRect.y() ) {
473 this->setToolTip(i18n("Swap foreground and background colors"));
474 }
475 else{
476 this->setToolTip(i18n("Background color selector"));
477 }
478 }
479 }
480 return QWidget::event(event);
481
482}
const Params2D p
PythonPluginManager * instance
The KisInternalColorSelector class.
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198
A widget for selecting two related colors.
void setForegroundColor(const KoColor &color)
void mouseMoveEvent(QMouseEvent *event) override
void slotSetBackgroundColorFromDialog(const KoColor color)
bool event(QEvent *event) override
std::optional< ColorDialogState > colorDialogState
void paintEvent(QPaintEvent *event) override
void setPopDialog(bool popDialog)
QSize sizeHint() const override
void dragEnterEvent(QDragEnterEvent *event) override
KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent=0, QWidget *dialogParent=0)
Private(const KoColor &fgColor, const KoColor &bgColor, QWidget *_dialogParent, const KoColorDisplayRendererInterface *_displayRenderer)
void init(KoDualColorButton *q)
void foregroundColorChanged(const KoColor &color)
void setColorSpace(const KoColorSpace *cs)
setColorSpace set ColorSpace so we can lock the selector. Right now this'll be changed per view-chang...
void slotSetForegroundColorFromDialog(const KoColor color)
KisDlgInternalColorSelector * colorSelectorDialog
QColor getColorFromDisplayRenderer(KoColor c)
getColorFromDisplayRenderer convenience function to get the right qcolor from the display renderer,...
virtual void metrics(QRect &foregroundRect, QRect &backgroundRect)
void mousePressEvent(QMouseEvent *event) override
void backgroundColorChanged(const KoColor &color)
void mouseReleaseEvent(QMouseEvent *event) override
void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer=KoDumbColorDisplayRenderer::instance())
void setBackgroundColor(const KoColor &color)
QPointer< const KoColorDisplayRendererInterface > displayRenderer
void dropEvent(QDropEvent *event) override
void changeEvent(QEvent *event) override
static KoColorDisplayRendererInterface * instance()
rgba palette[MAX_PALETTE]
Definition palette.c:35
KisSignalAutoConnectionsStore connections