1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcolordialog.h"
41
42#include "qapplication.h"
43#include "qdrawutil.h"
44#include "qevent.h"
45#include "qimage.h"
46#if QT_CONFIG(draganddrop)
47#include <qdrag.h>
48#endif
49#include "qlabel.h"
50#include "qlayout.h"
51#include "qlineedit.h"
52#if QT_CONFIG(menu)
53#include "qmenu.h"
54#endif
55#include "qpainter.h"
56#include "qpixmap.h"
57#include "qpushbutton.h"
58#if QT_CONFIG(regularexpression)
59#include <qregularexpression.h>
60#endif
61#if QT_CONFIG(settings)
62#include "qsettings.h"
63#endif
64#include "qsharedpointer.h"
65#include "qstyle.h"
66#include "qstyleoption.h"
67#include "qvalidator.h"
68#include "qmimedata.h"
69#include "qspinbox.h"
70#include "qdialogbuttonbox.h"
71#include "qscreen.h"
72#include "qcursor.h"
73#include "qtimer.h"
74#include "qwindow.h"
75
76#include "private/qdialog_p.h"
77
78#include <algorithm>
79
80QT_BEGIN_NAMESPACE
81
82namespace {
83class QColorLuminancePicker;
84class QColorPicker;
85class QColorShower;
86class QWellArray;
87class QColorPickingEventFilter;
88} // unnamed namespace
89
90class QColorDialogPrivate : public QDialogPrivate
91{
92 Q_DECLARE_PUBLIC(QColorDialog)
93
94public:
95 enum SetColorMode {
96 ShowColor = 0x1,
97 SelectColor = 0x2,
98 SetColorAll = ShowColor | SelectColor
99 };
100
101 QColorDialogPrivate() : options(QColorDialogOptions::create())
102#ifdef Q_OS_WIN32
103 , updateTimer(0)
104#endif
105 {}
106
107 QPlatformColorDialogHelper *platformColorDialogHelper() const
108 { return static_cast<QPlatformColorDialogHelper *>(platformHelper()); }
109
110 void init(const QColor &initial);
111 void initWidgets();
112 QRgb currentColor() const;
113 QColor currentQColor() const;
114 void setCurrentColor(const QColor &color, SetColorMode setColorMode = SetColorAll);
115 void setCurrentRgbColor(QRgb rgb);
116 void setCurrentQColor(const QColor &color);
117 bool selectColor(const QColor &color);
118 QColor grabScreenColor(const QPoint &p);
119
120 int currentAlpha() const;
121 void setCurrentAlpha(int a);
122 void showAlpha(bool b);
123 bool isAlphaVisible() const;
124 void retranslateStrings();
125
126 void _q_addCustom();
127 void _q_setCustom(int index, QRgb color);
128
129 void _q_newHsv(int h, int s, int v);
130 void _q_newColorTypedIn(QRgb rgb);
131 void _q_nextCustom(int, int);
132 void _q_newCustom(int, int);
133 void _q_newStandard(int, int);
134 void _q_pickScreenColor();
135 void _q_updateColorPicking();
136 void updateColorLabelText(const QPoint &);
137 void updateColorPicking(const QPoint &pos);
138 void releaseColorPicking();
139 bool handleColorPickingMouseMove(QMouseEvent *e);
140 bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
141 bool handleColorPickingKeyPress(QKeyEvent *e);
142
143 bool canBeNativeDialog() const override;
144
145 QWellArray *custom;
146 QWellArray *standard;
147
148 QDialogButtonBox *buttons;
149 QVBoxLayout *leftLay;
150 QColorPicker *cp;
151 QColorLuminancePicker *lp;
152 QColorShower *cs;
153 QLabel *lblBasicColors;
154 QLabel *lblCustomColors;
155 QLabel *lblScreenColorInfo;
156 QPushButton *ok;
157 QPushButton *cancel;
158 QPushButton *addCusBt;
159 QPushButton *screenColorPickerButton;
160 QColor selectedQColor;
161 int nextCust;
162 bool smallDisplay;
163 bool screenColorPicking;
164 QColorPickingEventFilter *colorPickingEventFilter;
165 QRgb beforeScreenColorPicking;
166 QSharedPointer<QColorDialogOptions> options;
167
168 QPointer<QObject> receiverToDisconnectOnClose;
169 QByteArray memberToDisconnectOnClose;
170#ifdef Q_OS_WIN32
171 QTimer *updateTimer;
172 QWindow dummyTransparentWindow;
173#endif
174
175private:
176 virtual void initHelper(QPlatformDialogHelper *h) override;
177 virtual void helperPrepareShow(QPlatformDialogHelper *h) override;
178};
179
180//////////// QWellArray BEGIN
181
182namespace {
183
184class QWellArray : public QWidget
185{
186 Q_OBJECT
187 Q_PROPERTY(int selectedColumn READ selectedColumn)
188 Q_PROPERTY(int selectedRow READ selectedRow)
189
190public:
191 QWellArray(int rows, int cols, QWidget* parent=nullptr);
192 ~QWellArray() {}
193 QString cellContent(int row, int col) const;
194
195 int selectedColumn() const { return selCol; }
196 int selectedRow() const { return selRow; }
197
198 virtual void setCurrent(int row, int col);
199 virtual void setSelected(int row, int col);
200
201 QSize sizeHint() const override;
202
203 inline int cellWidth() const
204 { return cellw; }
205
206 inline int cellHeight() const
207 { return cellh; }
208
209 inline int rowAt(int y) const
210 { return y / cellh; }
211
212 inline int columnAt(int x) const
213 { if (isRightToLeft()) return ncols - (x / cellw) - 1; return x / cellw; }
214
215 inline int rowY(int row) const
216 { return cellh * row; }
217
218 inline int columnX(int column) const
219 { if (isRightToLeft()) return cellw * (ncols - column - 1); return cellw * column; }
220
221 inline int numRows() const
222 { return nrows; }
223
224 inline int numCols() const
225 {return ncols; }
226
227 inline QRect cellRect() const
228 { return QRect(0, 0, cellw, cellh); }
229
230 inline QSize gridSize() const
231 { return QSize(ncols * cellw, nrows * cellh); }
232
233 QRect cellGeometry(int row, int column)
234 {
235 QRect r;
236 if (row >= 0 && row < nrows && column >= 0 && column < ncols)
237 r.setRect(columnX(column), rowY(row), cellw, cellh);
238 return r;
239 }
240
241 inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }
242
243signals:
244 void selected(int row, int col);
245 void currentChanged(int row, int col);
246 void colorChanged(int index, QRgb color);
247
248protected:
249 virtual void paintCell(QPainter *, int row, int col, const QRect&);
250 virtual void paintCellContents(QPainter *, int row, int col, const QRect&);
251
252 void mousePressEvent(QMouseEvent*) override;
253 void mouseReleaseEvent(QMouseEvent*) override;
254 void keyPressEvent(QKeyEvent*) override;
255 void focusInEvent(QFocusEvent*) override;
256 void focusOutEvent(QFocusEvent*) override;
257 void paintEvent(QPaintEvent *) override;
258
259private:
260 Q_DISABLE_COPY(QWellArray)
261
262 int nrows;
263 int ncols;
264 int cellw;
265 int cellh;
266 int curRow;
267 int curCol;
268 int selRow;
269 int selCol;
270};
271
272void QWellArray::paintEvent(QPaintEvent *e)
273{
274 QRect r = e->rect();
275 int cx = r.x();
276 int cy = r.y();
277 int ch = r.height();
278 int cw = r.width();
279 int colfirst = columnAt(cx);
280 int collast = columnAt(cx + cw);
281 int rowfirst = rowAt(cy);
282 int rowlast = rowAt(cy + ch);
283
284 if (isRightToLeft()) {
285 int t = colfirst;
286 colfirst = collast;
287 collast = t;
288 }
289
290 QPainter painter(this);
291 QPainter *p = &painter;
292 QRect rect(0, 0, cellWidth(), cellHeight());
293
294
295 if (collast < 0 || collast >= ncols)
296 collast = ncols-1;
297 if (rowlast < 0 || rowlast >= nrows)
298 rowlast = nrows-1;
299
300 // Go through the rows
301 for (int r = rowfirst; r <= rowlast; ++r) {
302 // get row position and height
303 int rowp = rowY(r);
304
305 // Go through the columns in the row r
306 // if we know from where to where, go through [colfirst, collast],
307 // else go through all of them
308 for (int c = colfirst; c <= collast; ++c) {
309 // get position and width of column c
310 int colp = columnX(c);
311 // Translate painter and draw the cell
312 rect.translate(colp, rowp);
313 paintCell(p, r, c, rect);
314 rect.translate(-colp, -rowp);
315 }
316 }
317}
318
319QWellArray::QWellArray(int rows, int cols, QWidget *parent)
320 : QWidget(parent)
321 ,nrows(rows), ncols(cols)
322{
323 setFocusPolicy(Qt::StrongFocus);
324 cellw = 28;
325 cellh = 24;
326 curCol = 0;
327 curRow = 0;
328 selCol = -1;
329 selRow = -1;
330}
331
332QSize QWellArray::sizeHint() const
333{
334 ensurePolished();
335 return gridSize().boundedTo(QSize(640, 480));
336}
337
338
339void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)
340{
341 int b = 3; //margin
342
343 const QPalette & g = palette();
344 QStyleOptionFrame opt;
345 opt.initFrom(this);
346 int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt);
347 opt.lineWidth = dfw;
348 opt.midLineWidth = 1;
349 opt.rect = rect.adjusted(b, b, -b, -b);
350 opt.palette = g;
351 opt.state = QStyle::State_Enabled | QStyle::State_Sunken;
352 style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);
353 b += dfw;
354
355 if ((row == curRow) && (col == curCol)) {
356 if (hasFocus()) {
357 QStyleOptionFocusRect opt;
358 opt.palette = g;
359 opt.rect = rect;
360 opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange;
361 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);
362 }
363 }
364 paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw));
365}
366
367/*
368 Reimplement this function to change the contents of the well array.
369 */
370void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r)
371{
372 Q_UNUSED(row);
373 Q_UNUSED(col);
374 p->fillRect(r, Qt::white);
375 p->setPen(Qt::black);
376 p->drawLine(r.topLeft(), r.bottomRight());
377 p->drawLine(r.topRight(), r.bottomLeft());
378}
379
380void QWellArray::mousePressEvent(QMouseEvent *e)
381{
382 // The current cell marker is set to the cell the mouse is pressed in
383 QPoint pos = e->position().toPoint();
384 setCurrent(rowAt(pos.y()), columnAt(pos.x()));
385}
386
387void QWellArray::mouseReleaseEvent(QMouseEvent * /* event */)
388{
389 // The current cell marker is set to the cell the mouse is clicked in
390 setSelected(curRow, curCol);
391}
392
393
394/*
395 Sets the cell currently having the focus. This is not necessarily
396 the same as the currently selected cell.
397*/
398
399void QWellArray::setCurrent(int row, int col)
400{
401 if ((curRow == row) && (curCol == col))
402 return;
403
404 if (row < 0 || col < 0)
405 row = col = -1;
406
407 int oldRow = curRow;
408 int oldCol = curCol;
409
410 curRow = row;
411 curCol = col;
412
413 updateCell(oldRow, oldCol);
414 updateCell(curRow, curCol);
415
416 emit currentChanged(curRow, curCol);
417}
418
419/*
420 Sets the currently selected cell to \a row, \a column. If \a row or
421 \a column are less than zero, the current cell is unselected.
422
423 Does not set the position of the focus indicator.
424*/
425void QWellArray::setSelected(int row, int col)
426{
427 int oldRow = selRow;
428 int oldCol = selCol;
429
430 if (row < 0 || col < 0)
431 row = col = -1;
432
433 selCol = col;
434 selRow = row;
435
436 updateCell(oldRow, oldCol);
437 updateCell(selRow, selCol);
438 if (row >= 0)
439 emit selected(row, col);
440
441#if QT_CONFIG(menu)
442 if (isVisible() && qobject_cast<QMenu*>(parentWidget()))
443 parentWidget()->close();
444#endif
445}
446
447void QWellArray::focusInEvent(QFocusEvent*)
448{
449 updateCell(curRow, curCol);
450 emit currentChanged(curRow, curCol);
451}
452
453
454void QWellArray::focusOutEvent(QFocusEvent*)
455{
456 updateCell(curRow, curCol);
457}
458
459void QWellArray::keyPressEvent(QKeyEvent* e)
460{
461 switch(e->key()) { // Look at the key code
462 case Qt::Key_Left: // If 'left arrow'-key,
463 if(curCol > 0) // and cr't not in leftmost col
464 setCurrent(curRow, curCol - 1); // set cr't to next left column
465 break;
466 case Qt::Key_Right: // Correspondingly...
467 if(curCol < numCols()-1)
468 setCurrent(curRow, curCol + 1);
469 break;
470 case Qt::Key_Up:
471 if(curRow > 0)
472 setCurrent(curRow - 1, curCol);
473 break;
474 case Qt::Key_Down:
475 if(curRow < numRows()-1)
476 setCurrent(curRow + 1, curCol);
477 break;
478#if 0
479 // bad idea that shouldn't have been implemented; very counterintuitive
480 case Qt::Key_Return:
481 case Qt::Key_Enter:
482 /*
483 ignore the key, so that the dialog get it, but still select
484 the current row/col
485 */
486 e->ignore();
487 // fallthrough intended
488#endif
489 case Qt::Key_Space:
490 setSelected(curRow, curCol);
491 break;
492 default: // If not an interesting key,
493 e->ignore(); // we don't accept the event
494 return;
495 }
496
497}
498
499//////////// QWellArray END
500
501// Event filter to be installed on the dialog while in color-picking mode.
502class QColorPickingEventFilter : public QObject {
503public:
504 explicit QColorPickingEventFilter(QColorDialogPrivate *dp, QObject *parent) : QObject(parent), m_dp(dp) {}
505
506 bool eventFilter(QObject *, QEvent *event) override
507 {
508 switch (event->type()) {
509 case QEvent::MouseMove:
510 return m_dp->handleColorPickingMouseMove(static_cast<QMouseEvent *>(event));
511 case QEvent::MouseButtonRelease:
512 return m_dp->handleColorPickingMouseButtonRelease(static_cast<QMouseEvent *>(event));
513 case QEvent::KeyPress:
514 return m_dp->handleColorPickingKeyPress(static_cast<QKeyEvent *>(event));
515 default:
516 break;
517 }
518 return false;
519 }
520
521private:
522 QColorDialogPrivate *m_dp;
523};
524
525} // unnamed namespace
526
527/*!
528 Returns the number of custom colors supported by QColorDialog. All
529 color dialogs share the same custom colors.
530*/
531int QColorDialog::customCount()
532{
533 return QColorDialogOptions::customColorCount();
534}
535
536/*!
537 \since 4.5
538
539 Returns the custom color at the given \a index as a QColor value.
540*/
541QColor QColorDialog::customColor(int index)
542{
543 return QColor(QColorDialogOptions::customColor(index));
544}
545
546/*!
547 Sets the custom color at \a index to the QColor \a color value.
548
549 \note This function does not apply to the Native Color Dialog on the
550 \macos platform. If you still require this function, use the
551 QColorDialog::DontUseNativeDialog option.
552*/
553void QColorDialog::setCustomColor(int index, QColor color)
554{
555 QColorDialogOptions::setCustomColor(index, color.rgba());
556}
557
558/*!
559 \since 5.0
560
561 Returns the standard color at the given \a index as a QColor value.
562*/
563QColor QColorDialog::standardColor(int index)
564{
565 return QColor(QColorDialogOptions::standardColor(index));
566}
567
568/*!
569 Sets the standard color at \a index to the QColor \a color value.
570
571 \note This function does not apply to the Native Color Dialog on the
572 \macos platform. If you still require this function, use the
573 QColorDialog::DontUseNativeDialog option.
574*/
575void QColorDialog::setStandardColor(int index, QColor color)
576{
577 QColorDialogOptions::setStandardColor(index, color.rgba());
578}
579
580static inline void rgb2hsv(QRgb rgb, int &h, int &s, int &v)
581{
582 QColor c;
583 c.setRgb(rgb);
584 c.getHsv(&h, &s, &v);
585}
586
587namespace {
588
589class QColorWell : public QWellArray
590{
591public:
592 QColorWell(QWidget *parent, int r, int c, const QRgb *vals)
593 :QWellArray(r, c, parent), values(vals), mousePressed(false), oldCurrent(-1, -1)
594 { setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); }
595
596protected:
597 void paintCellContents(QPainter *, int row, int col, const QRect&) override;
598 void mousePressEvent(QMouseEvent *e) override;
599 void mouseMoveEvent(QMouseEvent *e) override;
600 void mouseReleaseEvent(QMouseEvent *e) override;
601#if QT_CONFIG(draganddrop)
602 void dragEnterEvent(QDragEnterEvent *e) override;
603 void dragLeaveEvent(QDragLeaveEvent *e) override;
604 void dragMoveEvent(QDragMoveEvent *e) override;
605 void dropEvent(QDropEvent *e) override;
606#endif
607
608private:
609 const QRgb *values;
610 bool mousePressed;
611 QPoint pressPos;
612 QPoint oldCurrent;
613
614};
615
616void QColorWell::paintCellContents(QPainter *p, int row, int col, const QRect &r)
617{
618 int i = row + col*numRows();
619 p->fillRect(r, QColor(values[i]));
620}
621
622void QColorWell::mousePressEvent(QMouseEvent *e)
623{
624 oldCurrent = QPoint(selectedRow(), selectedColumn());
625 QWellArray::mousePressEvent(e);
626 mousePressed = true;
627 pressPos = e->position().toPoint();
628}
629
630void QColorWell::mouseMoveEvent(QMouseEvent *e)
631{
632 QWellArray::mouseMoveEvent(e);
633#if QT_CONFIG(draganddrop)
634 if (!mousePressed)
635 return;
636 if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {
637 setCurrent(oldCurrent.x(), oldCurrent.y());
638 int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows();
639 QColor col(values[i]);
640 QMimeData *mime = new QMimeData;
641 mime->setColorData(col);
642 QPixmap pix(cellWidth(), cellHeight());
643 pix.fill(col);
644 QPainter p(&pix);
645 p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
646 p.end();
647 QDrag *drg = new QDrag(this);
648 drg->setMimeData(mime);
649 drg->setPixmap(pix);
650 mousePressed = false;
651 drg->exec(Qt::CopyAction);
652 }
653#endif
654}
655
656#if QT_CONFIG(draganddrop)
657void QColorWell::dragEnterEvent(QDragEnterEvent *e)
658{
659 if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())
660 e->accept();
661 else
662 e->ignore();
663}
664
665void QColorWell::dragLeaveEvent(QDragLeaveEvent *)
666{
667 if (hasFocus())
668 parentWidget()->setFocus();
669}
670
671void QColorWell::dragMoveEvent(QDragMoveEvent *e)
672{
673 if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid()) {
674 setCurrent(rowAt(e->position().toPoint().y()), columnAt(e->position().toPoint().x()));
675 e->accept();
676 } else {
677 e->ignore();
678 }
679}
680
681void QColorWell::dropEvent(QDropEvent *e)
682{
683 QColor col = qvariant_cast<QColor>(e->mimeData()->colorData());
684 if (col.isValid()) {
685 int i = rowAt(e->position().toPoint().y()) + columnAt(e->position().toPoint().x()) * numRows();
686 emit colorChanged(i, col.rgb());
687 e->accept();
688 } else {
689 e->ignore();
690 }
691}
692
693#endif // QT_CONFIG(draganddrop)
694
695void QColorWell::mouseReleaseEvent(QMouseEvent *e)
696{
697 if (!mousePressed)
698 return;
699 QWellArray::mouseReleaseEvent(e);
700 mousePressed = false;
701}
702
703class QColorPicker : public QFrame
704{
705 Q_OBJECT
706public:
707 QColorPicker(QWidget* parent);
708 ~QColorPicker();
709
710 void setCrossVisible(bool visible);
711public slots:
712 void setCol(int h, int s);
713
714signals:
715 void newCol(int h, int s);
716
717protected:
718 QSize sizeHint() const override;
719 void paintEvent(QPaintEvent*) override;
720 void mouseMoveEvent(QMouseEvent *) override;
721 void mousePressEvent(QMouseEvent *) override;
722 void resizeEvent(QResizeEvent *) override;
723
724private:
725 int hue;
726 int sat;
727
728 QPoint colPt();
729 int huePt(const QPoint &pt);
730 int satPt(const QPoint &pt);
731 void setCol(const QPoint &pt);
732
733 QPixmap pix;
734 bool crossVisible;
735};
736
737static int pWidth = 220;
738static int pHeight = 200;
739
740class QColorLuminancePicker : public QWidget
741{
742 Q_OBJECT
743public:
744 QColorLuminancePicker(QWidget* parent=nullptr);
745 ~QColorLuminancePicker();
746
747public slots:
748 void setCol(int h, int s, int v);
749 void setCol(int h, int s);
750
751signals:
752 void newHsv(int h, int s, int v);
753
754protected:
755 void paintEvent(QPaintEvent*) override;
756 void mouseMoveEvent(QMouseEvent *) override;
757 void mousePressEvent(QMouseEvent *) override;
758
759private:
760 enum { foff = 3, coff = 4 }; //frame and contents offset
761 int val;
762 int hue;
763 int sat;
764
765 int y2val(int y);
766 int val2y(int val);
767 void setVal(int v);
768
769 QPixmap *pix;
770};
771
772
773int QColorLuminancePicker::y2val(int y)
774{
775 int d = height() - 2*coff - 1;
776 return 255 - (y - coff)*255/d;
777}
778
779int QColorLuminancePicker::val2y(int v)
780{
781 int d = height() - 2*coff - 1;
782 return coff + (255-v)*d/255;
783}
784
785QColorLuminancePicker::QColorLuminancePicker(QWidget* parent)
786 :QWidget(parent)
787{
788 hue = 100; val = 100; sat = 100;
789 pix = nullptr;
790 // setAttribute(WA_NoErase, true);
791}
792
793QColorLuminancePicker::~QColorLuminancePicker()
794{
795 delete pix;
796}
797
798void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)
799{
800 setVal(y2val(m->position().toPoint().y()));
801}
802void QColorLuminancePicker::mousePressEvent(QMouseEvent *m)
803{
804 setVal(y2val(m->position().toPoint().y()));
805}
806
807void QColorLuminancePicker::setVal(int v)
808{
809 if (val == v)
810 return;
811 val = qMax(0, qMin(v,255));
812 delete pix; pix=nullptr;
813 repaint();
814 emit newHsv(hue, sat, val);
815}
816
817//receives from a hue,sat chooser and relays.
818void QColorLuminancePicker::setCol(int h, int s)
819{
820 setCol(h, s, val);
821 emit newHsv(h, s, val);
822}
823
824void QColorLuminancePicker::paintEvent(QPaintEvent *)
825{
826 int w = width() - 5;
827
828 QRect r(0, foff, w, height() - 2*foff);
829 int wi = r.width() - 2;
830 int hi = r.height() - 2;
831 if (!pix || pix->height() != hi || pix->width() != wi) {
832 delete pix;
833 QImage img(wi, hi, QImage::Format_RGB32);
834 int y;
835 uint *pixel = (uint *) img.scanLine(0);
836 for (y = 0; y < hi; y++) {
837 uint *end = pixel + wi;
838 std::fill(pixel, end, QColor::fromHsv(hue, sat, y2val(y + coff)).rgb());
839 pixel = end;
840 }
841 pix = new QPixmap(QPixmap::fromImage(img));
842 }
843 QPainter p(this);
844 p.drawPixmap(1, coff, *pix);
845 const QPalette &g = palette();
846 qDrawShadePanel(&p, r, g, true);
847 p.setPen(g.windowText().color());
848 p.setBrush(g.windowText());
849 QPolygon a;
850 int y = val2y(val);
851 a.setPoints(3, w, y, w+5, y+5, w+5, y-5);
852 p.eraseRect(w, 0, 5, height());
853 p.drawPolygon(a);
854}
855
856void QColorLuminancePicker::setCol(int h, int s , int v)
857{
858 val = v;
859 hue = h;
860 sat = s;
861 delete pix; pix=nullptr;
862 repaint();
863}
864
865QPoint QColorPicker::colPt()
866{
867 QRect r = contentsRect();
868 return QPoint((360 - hue) * (r.width() - 1) / 360, (255 - sat) * (r.height() - 1) / 255);
869}
870
871int QColorPicker::huePt(const QPoint &pt)
872{
873 QRect r = contentsRect();
874 return 360 - pt.x() * 360 / (r.width() - 1);
875}
876
877int QColorPicker::satPt(const QPoint &pt)
878{
879 QRect r = contentsRect();
880 return 255 - pt.y() * 255 / (r.height() - 1);
881}
882
883void QColorPicker::setCol(const QPoint &pt)
884{
885 setCol(huePt(pt), satPt(pt));
886}
887
888QColorPicker::QColorPicker(QWidget* parent)
889 : QFrame(parent)
890 , crossVisible(true)
891{
892 hue = 0; sat = 0;
893 setCol(150, 255);
894
895 setAttribute(Qt::WA_NoSystemBackground);
896 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) );
897}
898
899QColorPicker::~QColorPicker()
900{
901}
902
903void QColorPicker::setCrossVisible(bool visible)
904{
905 if (crossVisible != visible) {
906 crossVisible = visible;
907 update();
908 }
909}
910
911QSize QColorPicker::sizeHint() const
912{
913 return QSize(pWidth + 2*frameWidth(), pHeight + 2*frameWidth());
914}
915
916void QColorPicker::setCol(int h, int s)
917{
918 int nhue = qMin(qMax(0,h), 359);
919 int nsat = qMin(qMax(0,s), 255);
920 if (nhue == hue && nsat == sat)
921 return;
922
923 QRect r(colPt(), QSize(20,20));
924 hue = nhue; sat = nsat;
925 r = r.united(QRect(colPt(), QSize(20,20)));
926 r.translate(contentsRect().x()-9, contentsRect().y()-9);
927 // update(r);
928 repaint(r);
929}
930
931void QColorPicker::mouseMoveEvent(QMouseEvent *m)
932{
933 QPoint p = m->position().toPoint() - contentsRect().topLeft();
934 setCol(p);
935 emit newCol(hue, sat);
936}
937
938void QColorPicker::mousePressEvent(QMouseEvent *m)
939{
940 QPoint p = m->position().toPoint() - contentsRect().topLeft();
941 setCol(p);
942 emit newCol(hue, sat);
943}
944
945void QColorPicker::paintEvent(QPaintEvent* )
946{
947 QPainter p(this);
948 drawFrame(&p);
949 QRect r = contentsRect();
950
951 p.drawPixmap(r.topLeft(), pix);
952
953 if (crossVisible) {
954 QPoint pt = colPt() + r.topLeft();
955 p.setPen(Qt::black);
956 p.fillRect(pt.x()-9, pt.y(), 20, 2, Qt::black);
957 p.fillRect(pt.x(), pt.y()-9, 2, 20, Qt::black);
958 }
959}
960
961void QColorPicker::resizeEvent(QResizeEvent *ev)
962{
963 QFrame::resizeEvent(ev);
964
965 int w = width() - frameWidth() * 2;
966 int h = height() - frameWidth() * 2;
967 QImage img(w, h, QImage::Format_RGB32);
968 int x, y;
969 uint *pixel = (uint *) img.scanLine(0);
970 for (y = 0; y < h; y++) {
971 const uint *end = pixel + w;
972 x = 0;
973 while (pixel < end) {
974 QPoint p(x, y);
975 QColor c;
976 c.setHsv(huePt(p), satPt(p), 200);
977 *pixel = c.rgb();
978 ++pixel;
979 ++x;
980 }
981 }
982 pix = QPixmap::fromImage(img);
983}
984
985
986class QColSpinBox : public QSpinBox
987{
988public:
989 QColSpinBox(QWidget *parent)
990 : QSpinBox(parent) { setRange(0, 255); }
991 void setValue(int i) {
992 const QSignalBlocker blocker(this);
993 QSpinBox::setValue(i);
994 }
995};
996
997class QColorShowLabel;
998
999class QColorShower : public QWidget
1000{
1001 Q_OBJECT
1002public:
1003 QColorShower(QColorDialog *parent);
1004
1005 //things that don't emit signals
1006 void setHsv(int h, int s, int v);
1007
1008 int currentAlpha() const
1009 { return (colorDialog->options() & QColorDialog::ShowAlphaChannel) ? alphaEd->value() : 255; }
1010 void setCurrentAlpha(int a) { alphaEd->setValue(a); rgbEd(); }
1011 void showAlpha(bool b);
1012 bool isAlphaVisible() const;
1013
1014 QRgb currentColor() const { return curCol; }
1015 QColor currentQColor() const { return curQColor; }
1016 void retranslateStrings();
1017 void updateQColor();
1018
1019public slots:
1020 void setRgb(QRgb rgb);
1021
1022signals:
1023 void newCol(QRgb rgb);
1024 void currentColorChanged(const QColor &color);
1025
1026private slots:
1027 void rgbEd();
1028 void hsvEd();
1029 void htmlEd();
1030
1031private:
1032 void showCurrentColor();
1033 int hue, sat, val;
1034 QRgb curCol;
1035 QColor curQColor;
1036 QLabel *lblHue;
1037 QLabel *lblSat;
1038 QLabel *lblVal;
1039 QLabel *lblRed;
1040 QLabel *lblGreen;
1041 QLabel *lblBlue;
1042 QLabel *lblHtml;
1043 QColSpinBox *hEd;
1044 QColSpinBox *sEd;
1045 QColSpinBox *vEd;
1046 QColSpinBox *rEd;
1047 QColSpinBox *gEd;
1048 QColSpinBox *bEd;
1049 QColSpinBox *alphaEd;
1050 QLabel *alphaLab;
1051 QLineEdit *htEd;
1052 QColorShowLabel *lab;
1053 bool rgbOriginal;
1054 QColorDialog *colorDialog;
1055 QGridLayout *gl;
1056
1057 friend class QT_PREPEND_NAMESPACE(QColorDialog);
1058 friend class QT_PREPEND_NAMESPACE(QColorDialogPrivate);
1059};
1060
1061class QColorShowLabel : public QFrame
1062{
1063 Q_OBJECT
1064
1065public:
1066 QColorShowLabel(QWidget *parent) : QFrame(parent) {
1067 setFrameStyle(QFrame::Panel|QFrame::Sunken);
1068 setAcceptDrops(true);
1069 mousePressed = false;
1070 }
1071 void setColor(QColor c) { col = c; }
1072
1073signals:
1074 void colorDropped(QRgb);
1075
1076protected:
1077 void paintEvent(QPaintEvent *) override;
1078 void mousePressEvent(QMouseEvent *e) override;
1079 void mouseMoveEvent(QMouseEvent *e) override;
1080 void mouseReleaseEvent(QMouseEvent *e) override;
1081#if QT_CONFIG(draganddrop)
1082 void dragEnterEvent(QDragEnterEvent *e) override;
1083 void dragLeaveEvent(QDragLeaveEvent *e) override;
1084 void dropEvent(QDropEvent *e) override;
1085#endif
1086
1087private:
1088 QColor col;
1089 bool mousePressed;
1090 QPoint pressPos;
1091};
1092
1093void QColorShowLabel::paintEvent(QPaintEvent *e)
1094{
1095 QPainter p(this);
1096 drawFrame(&p);
1097 p.fillRect(contentsRect()&e->rect(), col);
1098}
1099
1100void QColorShower::showAlpha(bool b)
1101{
1102 alphaLab->setVisible(b);
1103 alphaEd->setVisible(b);
1104}
1105
1106inline bool QColorShower::isAlphaVisible() const
1107{
1108 return alphaLab->isVisible();
1109}
1110
1111void QColorShowLabel::mousePressEvent(QMouseEvent *e)
1112{
1113 mousePressed = true;
1114 pressPos = e->position().toPoint();
1115}
1116
1117void QColorShowLabel::mouseMoveEvent(QMouseEvent *e)
1118{
1119#if !QT_CONFIG(draganddrop)
1120 Q_UNUSED(e);
1121#else
1122 if (!mousePressed)
1123 return;
1124 if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {
1125 QMimeData *mime = new QMimeData;
1126 mime->setColorData(col);
1127 QPixmap pix(30, 20);
1128 pix.fill(col);
1129 QPainter p(&pix);
1130 p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
1131 p.end();
1132 QDrag *drg = new QDrag(this);
1133 drg->setMimeData(mime);
1134 drg->setPixmap(pix);
1135 mousePressed = false;
1136 drg->exec(Qt::CopyAction);
1137 }
1138#endif
1139}
1140
1141#if QT_CONFIG(draganddrop)
1142void QColorShowLabel::dragEnterEvent(QDragEnterEvent *e)
1143{
1144 if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())
1145 e->accept();
1146 else
1147 e->ignore();
1148}
1149
1150void QColorShowLabel::dragLeaveEvent(QDragLeaveEvent *)
1151{
1152}
1153
1154void QColorShowLabel::dropEvent(QDropEvent *e)
1155{
1156 QColor color = qvariant_cast<QColor>(e->mimeData()->colorData());
1157 if (color.isValid()) {
1158 col = color;
1159 repaint();
1160 emit colorDropped(col.rgb());
1161 e->accept();
1162 } else {
1163 e->ignore();
1164 }
1165}
1166#endif // QT_CONFIG(draganddrop)
1167
1168void QColorShowLabel::mouseReleaseEvent(QMouseEvent *)
1169{
1170 if (!mousePressed)
1171 return;
1172 mousePressed = false;
1173}
1174
1175QColorShower::QColorShower(QColorDialog *parent)
1176 : QWidget(parent)
1177{
1178 colorDialog = parent;
1179
1180 curCol = qRgb(255, 255, 255);
1181 curQColor = Qt::white;
1182
1183 gl = new QGridLayout(this);
1184 const int s = gl->spacing();
1185 gl->setContentsMargins(s, s, s, s);
1186 lab = new QColorShowLabel(this);
1187
1188#ifdef QT_SMALL_COLORDIALOG
1189 lab->setMinimumHeight(60);
1190#endif
1191 lab->setMinimumWidth(60);
1192
1193// For QVGA screens only the comboboxes and color label are visible.
1194// For nHD screens only color and luminence pickers and color label are visible.
1195#if !defined(QT_SMALL_COLORDIALOG)
1196 gl->addWidget(lab, 0, 0, -1, 1);
1197#else
1198 gl->addWidget(lab, 0, 0, 1, -1);
1199#endif
1200 connect(lab, SIGNAL(colorDropped(QRgb)), this, SIGNAL(newCol(QRgb)));
1201 connect(lab, SIGNAL(colorDropped(QRgb)), this, SLOT(setRgb(QRgb)));
1202
1203 hEd = new QColSpinBox(this);
1204 hEd->setRange(0, 359);
1205 lblHue = new QLabel(this);
1206#ifndef QT_NO_SHORTCUT
1207 lblHue->setBuddy(hEd);
1208#endif
1209 lblHue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1210#if !defined(QT_SMALL_COLORDIALOG)
1211 gl->addWidget(lblHue, 0, 1);
1212 gl->addWidget(hEd, 0, 2);
1213#else
1214 gl->addWidget(lblHue, 1, 0);
1215 gl->addWidget(hEd, 2, 0);
1216#endif
1217
1218 sEd = new QColSpinBox(this);
1219 lblSat = new QLabel(this);
1220#ifndef QT_NO_SHORTCUT
1221 lblSat->setBuddy(sEd);
1222#endif
1223 lblSat->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1224#if !defined(QT_SMALL_COLORDIALOG)
1225 gl->addWidget(lblSat, 1, 1);
1226 gl->addWidget(sEd, 1, 2);
1227#else
1228 gl->addWidget(lblSat, 1, 1);
1229 gl->addWidget(sEd, 2, 1);
1230#endif
1231
1232 vEd = new QColSpinBox(this);
1233 lblVal = new QLabel(this);
1234#ifndef QT_NO_SHORTCUT
1235 lblVal->setBuddy(vEd);
1236#endif
1237 lblVal->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1238#if !defined(QT_SMALL_COLORDIALOG)
1239 gl->addWidget(lblVal, 2, 1);
1240 gl->addWidget(vEd, 2, 2);
1241#else
1242 gl->addWidget(lblVal, 1, 2);
1243 gl->addWidget(vEd, 2, 2);
1244#endif
1245
1246 rEd = new QColSpinBox(this);
1247 lblRed = new QLabel(this);
1248#ifndef QT_NO_SHORTCUT
1249 lblRed->setBuddy(rEd);
1250#endif
1251 lblRed->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1252#if !defined(QT_SMALL_COLORDIALOG)
1253 gl->addWidget(lblRed, 0, 3);
1254 gl->addWidget(rEd, 0, 4);
1255#else
1256 gl->addWidget(lblRed, 3, 0);
1257 gl->addWidget(rEd, 4, 0);
1258#endif
1259
1260 gEd = new QColSpinBox(this);
1261 lblGreen = new QLabel(this);
1262#ifndef QT_NO_SHORTCUT
1263 lblGreen->setBuddy(gEd);
1264#endif
1265 lblGreen->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1266#if !defined(QT_SMALL_COLORDIALOG)
1267 gl->addWidget(lblGreen, 1, 3);
1268 gl->addWidget(gEd, 1, 4);
1269#else
1270 gl->addWidget(lblGreen, 3, 1);
1271 gl->addWidget(gEd, 4, 1);
1272#endif
1273
1274 bEd = new QColSpinBox(this);
1275 lblBlue = new QLabel(this);
1276#ifndef QT_NO_SHORTCUT
1277 lblBlue->setBuddy(bEd);
1278#endif
1279 lblBlue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1280#if !defined(QT_SMALL_COLORDIALOG)
1281 gl->addWidget(lblBlue, 2, 3);
1282 gl->addWidget(bEd, 2, 4);
1283#else
1284 gl->addWidget(lblBlue, 3, 2);
1285 gl->addWidget(bEd, 4, 2);
1286#endif
1287
1288 alphaEd = new QColSpinBox(this);
1289 alphaLab = new QLabel(this);
1290#ifndef QT_NO_SHORTCUT
1291 alphaLab->setBuddy(alphaEd);
1292#endif
1293 alphaLab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1294#if !defined(QT_SMALL_COLORDIALOG)
1295 gl->addWidget(alphaLab, 3, 1, 1, 3);
1296 gl->addWidget(alphaEd, 3, 4);
1297#else
1298 gl->addWidget(alphaLab, 1, 3, 3, 1);
1299 gl->addWidget(alphaEd, 4, 3);
1300#endif
1301 alphaEd->hide();
1302 alphaLab->hide();
1303 lblHtml = new QLabel(this);
1304 htEd = new QLineEdit(this);
1305#ifndef QT_NO_SHORTCUT
1306 lblHtml->setBuddy(htEd);
1307#endif
1308
1309#if QT_CONFIG(regularexpression)
1310 QRegularExpression regExp(QStringLiteral("#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
1311 QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
1312 htEd->setValidator(validator);
1313#else
1314 htEd->setReadOnly(true);
1315#endif
1316 htEd->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
1317
1318 lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
1319#if defined(QT_SMALL_COLORDIALOG)
1320 gl->addWidget(lblHtml, 5, 0);
1321 gl->addWidget(htEd, 5, 1, 1, /*colspan=*/ 2);
1322#else
1323 gl->addWidget(lblHtml, 5, 1);
1324 gl->addWidget(htEd, 5, 2, 1, /*colspan=*/ 3);
1325#endif
1326
1327 connect(hEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
1328 connect(sEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
1329 connect(vEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
1330
1331 connect(rEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
1332 connect(gEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
1333 connect(bEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
1334 connect(alphaEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
1335 connect(htEd, SIGNAL(textEdited(QString)), this, SLOT(htmlEd()));
1336
1337 retranslateStrings();
1338}
1339
1340} // unnamed namespace
1341
1342inline QRgb QColorDialogPrivate::currentColor() const { return cs->currentColor(); }
1343inline int QColorDialogPrivate::currentAlpha() const { return cs->currentAlpha(); }
1344inline void QColorDialogPrivate::setCurrentAlpha(int a) { cs->setCurrentAlpha(a); }
1345inline void QColorDialogPrivate::showAlpha(bool b) { cs->showAlpha(b); }
1346inline bool QColorDialogPrivate::isAlphaVisible() const { return cs->isAlphaVisible(); }
1347
1348QColor QColorDialogPrivate::currentQColor() const
1349{
1350 if (nativeDialogInUse)
1351 return platformColorDialogHelper()->currentColor();
1352 return cs->currentQColor();
1353}
1354
1355void QColorShower::showCurrentColor()
1356{
1357 lab->setColor(currentColor());
1358 lab->repaint();
1359}
1360
1361void QColorShower::rgbEd()
1362{
1363 rgbOriginal = true;
1364 curCol = qRgba(rEd->value(), gEd->value(), bEd->value(), currentAlpha());
1365
1366 rgb2hsv(currentColor(), hue, sat, val);
1367
1368 hEd->setValue(hue);
1369 sEd->setValue(sat);
1370 vEd->setValue(val);
1371
1372 htEd->setText(QColor(curCol).name());
1373
1374 showCurrentColor();
1375 emit newCol(currentColor());
1376 updateQColor();
1377}
1378
1379void QColorShower::hsvEd()
1380{
1381 rgbOriginal = false;
1382 hue = hEd->value();
1383 sat = sEd->value();
1384 val = vEd->value();
1385
1386 QColor c;
1387 c.setHsv(hue, sat, val);
1388 curCol = c.rgb();
1389
1390 rEd->setValue(qRed(currentColor()));
1391 gEd->setValue(qGreen(currentColor()));
1392 bEd->setValue(qBlue(currentColor()));
1393
1394 htEd->setText(c.name());
1395
1396 showCurrentColor();
1397 emit newCol(currentColor());
1398 updateQColor();
1399}
1400
1401void QColorShower::htmlEd()
1402{
1403 QColor c;
1404 QString t = htEd->text();
1405 c.setNamedColor(t);
1406 if (!c.isValid())
1407 return;
1408 curCol = qRgba(c.red(), c.green(), c.blue(), currentAlpha());
1409 rgb2hsv(curCol, hue, sat, val);
1410
1411 hEd->setValue(hue);
1412 sEd->setValue(sat);
1413 vEd->setValue(val);
1414
1415 rEd->setValue(qRed(currentColor()));
1416 gEd->setValue(qGreen(currentColor()));
1417 bEd->setValue(qBlue(currentColor()));
1418
1419 showCurrentColor();
1420 emit newCol(currentColor());
1421 updateQColor();
1422}
1423
1424void QColorShower::setRgb(QRgb rgb)
1425{
1426 rgbOriginal = true;
1427 curCol = rgb;
1428
1429 rgb2hsv(currentColor(), hue, sat, val);
1430
1431 hEd->setValue(hue);
1432 sEd->setValue(sat);
1433 vEd->setValue(val);
1434
1435 rEd->setValue(qRed(currentColor()));
1436 gEd->setValue(qGreen(currentColor()));
1437 bEd->setValue(qBlue(currentColor()));
1438
1439 htEd->setText(QColor(rgb).name());
1440
1441 showCurrentColor();
1442 updateQColor();
1443}
1444
1445void QColorShower::setHsv(int h, int s, int v)
1446{
1447 if (h < -1 || (uint)s > 255 || (uint)v > 255)
1448 return;
1449
1450 rgbOriginal = false;
1451 hue = h; val = v; sat = s;
1452 QColor c;
1453 c.setHsv(hue, sat, val);
1454 curCol = c.rgb();
1455
1456 hEd->setValue(hue);
1457 sEd->setValue(sat);
1458 vEd->setValue(val);
1459
1460 rEd->setValue(qRed(currentColor()));
1461 gEd->setValue(qGreen(currentColor()));
1462 bEd->setValue(qBlue(currentColor()));
1463
1464 htEd->setText(c.name());
1465
1466 showCurrentColor();
1467 updateQColor();
1468}
1469
1470void QColorShower::retranslateStrings()
1471{
1472 lblHue->setText(QColorDialog::tr("Hu&e:"));
1473 lblSat->setText(QColorDialog::tr("&Sat:"));
1474 lblVal->setText(QColorDialog::tr("&Val:"));
1475 lblRed->setText(QColorDialog::tr("&Red:"));
1476 lblGreen->setText(QColorDialog::tr("&Green:"));
1477 lblBlue->setText(QColorDialog::tr("Bl&ue:"));
1478 alphaLab->setText(QColorDialog::tr("A&lpha channel:"));
1479 lblHtml->setText(QColorDialog::tr("&HTML:"));
1480}
1481
1482void QColorShower::updateQColor()
1483{
1484 QColor oldQColor(curQColor);
1485 curQColor.setRgba(qRgba(qRed(curCol), qGreen(curCol), qBlue(curCol), currentAlpha()));
1486 if (curQColor != oldQColor)
1487 emit currentColorChanged(curQColor);
1488}
1489
1490//sets all widgets to display h,s,v
1491void QColorDialogPrivate::_q_newHsv(int h, int s, int v)
1492{
1493 if (!nativeDialogInUse) {
1494 cs->setHsv(h, s, v);
1495 cp->setCol(h, s);
1496 lp->setCol(h, s, v);
1497 }
1498}
1499
1500//sets all widgets to display rgb
1501void QColorDialogPrivate::setCurrentRgbColor(QRgb rgb)
1502{
1503 if (!nativeDialogInUse) {
1504 cs->setRgb(rgb);
1505 _q_newColorTypedIn(rgb);
1506 }
1507}
1508
1509// hack; doesn't keep curCol in sync, so use with care
1510void QColorDialogPrivate::setCurrentQColor(const QColor &color)
1511{
1512 Q_Q(QColorDialog);
1513 if (cs->curQColor != color) {
1514 cs->curQColor = color;
1515 emit q->currentColorChanged(color);
1516 }
1517}
1518
1519// size of standard and custom color selector
1520enum {
1521 colorColumns = 8,
1522 standardColorRows = 6,
1523 customColorRows = 2
1524};
1525
1526bool QColorDialogPrivate::selectColor(const QColor &col)
1527{
1528 QRgb color = col.rgb();
1529 // Check standard colors
1530 if (standard) {
1531 const QRgb *standardColors = QColorDialogOptions::standardColors();
1532 const QRgb *standardColorsEnd = standardColors + standardColorRows * colorColumns;
1533 const QRgb *match = std::find(standardColors, standardColorsEnd, color);
1534 if (match != standardColorsEnd) {
1535 const int index = int(match - standardColors);
1536 const int column = index / standardColorRows;
1537 const int row = index % standardColorRows;
1538 _q_newStandard(row, column);
1539 standard->setCurrent(row, column);
1540 standard->setSelected(row, column);
1541 standard->setFocus();
1542 return true;
1543 }
1544 }
1545 // Check custom colors
1546 if (custom) {
1547 const QRgb *customColors = QColorDialogOptions::customColors();
1548 const QRgb *customColorsEnd = customColors + customColorRows * colorColumns;
1549 const QRgb *match = std::find(customColors, customColorsEnd, color);
1550 if (match != customColorsEnd) {
1551 const int index = int(match - customColors);
1552 const int column = index / customColorRows;
1553 const int row = index % customColorRows;
1554 _q_newCustom(row, column);
1555 custom->setCurrent(row, column);
1556 custom->setSelected(row, column);
1557 custom->setFocus();
1558 return true;
1559 }
1560 }
1561 return false;
1562}
1563
1564QColor QColorDialogPrivate::grabScreenColor(const QPoint &p)
1565{
1566 QScreen *screen = QGuiApplication::screenAt(p);
1567 if (!screen)
1568 screen = QGuiApplication::primaryScreen();
1569 const QPixmap pixmap = screen->grabWindow(0, p.x(), p.y(), 1, 1);
1570 const QImage i = pixmap.toImage();
1571 return i.pixel(0, 0);
1572}
1573
1574//sets all widgets except cs to display rgb
1575void QColorDialogPrivate::_q_newColorTypedIn(QRgb rgb)
1576{
1577 if (!nativeDialogInUse) {
1578 int h, s, v;
1579 rgb2hsv(rgb, h, s, v);
1580 cp->setCol(h, s);
1581 lp->setCol(h, s, v);
1582 }
1583}
1584
1585void QColorDialogPrivate::_q_nextCustom(int r, int c)
1586{
1587 nextCust = r + customColorRows * c;
1588}
1589
1590void QColorDialogPrivate::_q_newCustom(int r, int c)
1591{
1592 const int i = r + customColorRows * c;
1593 setCurrentRgbColor(QColorDialogOptions::customColor(i));
1594 if (standard)
1595 standard->setSelected(-1,-1);
1596}
1597
1598void QColorDialogPrivate::_q_newStandard(int r, int c)
1599{
1600 setCurrentRgbColor(QColorDialogOptions::standardColor(r + c * 6));
1601 if (custom)
1602 custom->setSelected(-1,-1);
1603}
1604
1605void QColorDialogPrivate::_q_pickScreenColor()
1606{
1607 Q_Q(QColorDialog);
1608 if (!colorPickingEventFilter)
1609 colorPickingEventFilter = new QColorPickingEventFilter(this, q);
1610 q->installEventFilter(colorPickingEventFilter);
1611 // If user pushes Escape, the last color before picking will be restored.
1612 beforeScreenColorPicking = cs->currentColor();
1613#ifndef QT_NO_CURSOR
1614 q->grabMouse(Qt::CrossCursor);
1615#else
1616 q->grabMouse();
1617#endif
1618
1619#ifdef Q_OS_WIN32
1620 // On Windows mouse tracking doesn't work over other processes's windows
1621 updateTimer->start(30);
1622
1623 // HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy,
1624 // invisible window to catch the mouse click, otherwise we will click whatever we clicked
1625 // and loose focus.
1626 dummyTransparentWindow.show();
1627#endif
1628 q->grabKeyboard();
1629 /* With setMouseTracking(true) the desired color can be more precisely picked up,
1630 * and continuously pushing the mouse button is not necessary.
1631 */
1632 q->setMouseTracking(true);
1633
1634 addCusBt->setDisabled(true);
1635 buttons->setDisabled(true);
1636 screenColorPickerButton->setDisabled(true);
1637
1638 const QPoint globalPos = QCursor::pos();
1639 q->setCurrentColor(grabScreenColor(globalPos));
1640 updateColorLabelText(globalPos);
1641}
1642
1643void QColorDialogPrivate::updateColorLabelText(const QPoint &globalPos)
1644{
1645 lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2\nPress ESC to cancel")
1646 .arg(globalPos.x())
1647 .arg(globalPos.y()));
1648}
1649
1650void QColorDialogPrivate::releaseColorPicking()
1651{
1652 Q_Q(QColorDialog);
1653 cp->setCrossVisible(true);
1654 q->removeEventFilter(colorPickingEventFilter);
1655 q->releaseMouse();
1656#ifdef Q_OS_WIN32
1657 updateTimer->stop();
1658 dummyTransparentWindow.setVisible(false);
1659#endif
1660 q->releaseKeyboard();
1661 q->setMouseTracking(false);
1662 lblScreenColorInfo->setText(QLatin1String("\n"));
1663 addCusBt->setDisabled(false);
1664 buttons->setDisabled(false);
1665 screenColorPickerButton->setDisabled(false);
1666}
1667
1668void QColorDialogPrivate::init(const QColor &initial)
1669{
1670 Q_Q(QColorDialog);
1671
1672 q->setSizeGripEnabled(false);
1673 q->setWindowTitle(QColorDialog::tr("Select Color"));
1674
1675 // default: use the native dialog if possible. Can be overridden in setOptions()
1676 nativeDialogInUse = (platformColorDialogHelper() != nullptr);
1677 colorPickingEventFilter = nullptr;
1678 nextCust = 0;
1679
1680 if (!nativeDialogInUse)
1681 initWidgets();
1682
1683#ifdef Q_OS_WIN32
1684 dummyTransparentWindow.resize(1, 1);
1685 dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint);
1686#endif
1687
1688 q->setCurrentColor(initial);
1689}
1690
1691void QColorDialogPrivate::initWidgets()
1692{
1693 Q_Q(QColorDialog);
1694 QVBoxLayout *mainLay = new QVBoxLayout(q);
1695 // there's nothing in this dialog that benefits from sizing up
1696 mainLay->setSizeConstraint(QLayout::SetFixedSize);
1697
1698 QHBoxLayout *topLay = new QHBoxLayout();
1699 mainLay->addLayout(topLay);
1700
1701 leftLay = nullptr;
1702
1703#if defined(QT_SMALL_COLORDIALOG)
1704 smallDisplay = true;
1705 const int lumSpace = 20;
1706#else
1707 // small displays (e.g. PDAs) cannot fit the full color dialog,
1708 // so just use the color picker.
1709 smallDisplay = (QGuiApplication::primaryScreen()->virtualGeometry().width() < 480 || QGuiApplication::primaryScreen()->virtualGeometry().height() < 350);
1710 const int lumSpace = topLay->spacing() / 2;
1711#endif
1712
1713 if (!smallDisplay) {
1714 leftLay = new QVBoxLayout;
1715 topLay->addLayout(leftLay);
1716
1717 standard = new QColorWell(q, standardColorRows, colorColumns, QColorDialogOptions::standardColors());
1718 lblBasicColors = new QLabel(q);
1719#ifndef QT_NO_SHORTCUT
1720 lblBasicColors->setBuddy(standard);
1721#endif
1722 q->connect(standard, SIGNAL(selected(int,int)), SLOT(_q_newStandard(int,int)));
1723 leftLay->addWidget(lblBasicColors);
1724 leftLay->addWidget(standard);
1725
1726#if !defined(QT_SMALL_COLORDIALOG)
1727 // The screen color picker button
1728 screenColorPickerButton = new QPushButton();
1729 leftLay->addWidget(screenColorPickerButton);
1730 lblScreenColorInfo = new QLabel(QLatin1String("\n"));
1731 leftLay->addWidget(lblScreenColorInfo);
1732 q->connect(screenColorPickerButton, SIGNAL(clicked()), SLOT(_q_pickScreenColor()));
1733#endif
1734
1735 leftLay->addStretch();
1736
1737 custom = new QColorWell(q, customColorRows, colorColumns, QColorDialogOptions::customColors());
1738 custom->setAcceptDrops(true);
1739
1740 q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int)));
1741 q->connect(custom, SIGNAL(currentChanged(int,int)), SLOT(_q_nextCustom(int,int)));
1742
1743 q->connect(custom, &QWellArray::colorChanged, [this] (int index, QRgb color) {
1744 QColorDialogOptions::setCustomColor(index, color);
1745 if (custom)
1746 custom->update();
1747 });
1748
1749 lblCustomColors = new QLabel(q);
1750#ifndef QT_NO_SHORTCUT
1751 lblCustomColors->setBuddy(custom);
1752#endif
1753 leftLay->addWidget(lblCustomColors);
1754 leftLay->addWidget(custom);
1755
1756 addCusBt = new QPushButton(q);
1757 QObject::connect(addCusBt, SIGNAL(clicked()), q, SLOT(_q_addCustom()));
1758 leftLay->addWidget(addCusBt);
1759 } else {
1760 // better color picker size for small displays
1761#if defined(QT_SMALL_COLORDIALOG)
1762 QSize screenSize = QGuiApplication::screenAt(QCursor::pos())->availableGeometry().size();
1763 pWidth = pHeight = qMin(screenSize.width(), screenSize.height());
1764 pHeight -= 20;
1765 if(screenSize.height() > screenSize.width())
1766 pWidth -= 20;
1767#else
1768 pWidth = 150;
1769 pHeight = 100;
1770#endif
1771 custom = nullptr;
1772 standard = nullptr;
1773 }
1774
1775 QVBoxLayout *rightLay = new QVBoxLayout;
1776 topLay->addLayout(rightLay);
1777
1778 QHBoxLayout *pickLay = new QHBoxLayout;
1779 rightLay->addLayout(pickLay);
1780
1781 QVBoxLayout *cLay = new QVBoxLayout;
1782 pickLay->addLayout(cLay);
1783 cp = new QColorPicker(q);
1784
1785 cp->setFrameStyle(QFrame::Panel + QFrame::Sunken);
1786
1787#if defined(QT_SMALL_COLORDIALOG)
1788 cp->hide();
1789#else
1790 cLay->addSpacing(lumSpace);
1791 cLay->addWidget(cp);
1792#endif
1793 cLay->addSpacing(lumSpace);
1794
1795 lp = new QColorLuminancePicker(q);
1796#if defined(QT_SMALL_COLORDIALOG)
1797 lp->hide();
1798#else
1799 lp->setFixedWidth(20);
1800 pickLay->addSpacing(10);
1801 pickLay->addWidget(lp);
1802 pickLay->addStretch();
1803#endif
1804
1805 QObject::connect(cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)));
1806 QObject::connect(lp, SIGNAL(newHsv(int,int,int)), q, SLOT(_q_newHsv(int,int,int)));
1807
1808 rightLay->addStretch();
1809
1810 cs = new QColorShower(q);
1811 pickLay->setContentsMargins(cs->gl->contentsMargins());
1812 QObject::connect(cs, SIGNAL(newCol(QRgb)), q, SLOT(_q_newColorTypedIn(QRgb)));
1813 QObject::connect(cs, SIGNAL(currentColorChanged(QColor)),
1814 q, SIGNAL(currentColorChanged(QColor)));
1815#if defined(QT_SMALL_COLORDIALOG)
1816 topLay->addWidget(cs);
1817#else
1818 rightLay->addWidget(cs);
1819 if (leftLay)
1820 leftLay->addSpacing(cs->gl->contentsMargins().right());
1821#endif
1822
1823 buttons = new QDialogButtonBox(q);
1824 mainLay->addWidget(buttons);
1825
1826 ok = buttons->addButton(QDialogButtonBox::Ok);
1827 QObject::connect(ok, SIGNAL(clicked()), q, SLOT(accept()));
1828 ok->setDefault(true);
1829 cancel = buttons->addButton(QDialogButtonBox::Cancel);
1830 QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
1831
1832#ifdef Q_OS_WIN32
1833 updateTimer = new QTimer(q);
1834 QObject::connect(updateTimer, SIGNAL(timeout()), q, SLOT(_q_updateColorPicking()));
1835#endif
1836 retranslateStrings();
1837}
1838
1839void QColorDialogPrivate::initHelper(QPlatformDialogHelper *h)
1840{
1841 QColorDialog *d = q_func();
1842 QObject::connect(h, SIGNAL(currentColorChanged(QColor)), d, SIGNAL(currentColorChanged(QColor)));
1843 QObject::connect(h, SIGNAL(colorSelected(QColor)), d, SIGNAL(colorSelected(QColor)));
1844 static_cast<QPlatformColorDialogHelper *>(h)->setOptions(options);
1845}
1846
1847void QColorDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
1848{
1849 options->setWindowTitle(q_func()->windowTitle());
1850}
1851
1852void QColorDialogPrivate::_q_addCustom()
1853{
1854 QColorDialogOptions::setCustomColor(nextCust, cs->currentColor());
1855 if (custom)
1856 custom->update();
1857 nextCust = (nextCust+1) % QColorDialogOptions::customColorCount();
1858}
1859
1860void QColorDialogPrivate::retranslateStrings()
1861{
1862 if (nativeDialogInUse)
1863 return;
1864
1865 if (!smallDisplay) {
1866 lblBasicColors->setText(QColorDialog::tr("&Basic colors"));
1867 lblCustomColors->setText(QColorDialog::tr("&Custom colors"));
1868 addCusBt->setText(QColorDialog::tr("&Add to Custom Colors"));
1869 screenColorPickerButton->setText(QColorDialog::tr("&Pick Screen Color"));
1870 }
1871
1872 cs->retranslateStrings();
1873}
1874
1875bool QColorDialogPrivate::canBeNativeDialog() const
1876{
1877 // Don't use Q_Q here! This function is called from ~QDialog,
1878 // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
1879 const QDialog * const q = static_cast<const QDialog*>(q_ptr);
1880 if (nativeDialogInUse)
1881 return true;
1882 if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
1883 || q->testAttribute(Qt::WA_DontShowOnScreen)
1884 || (options->options() & QColorDialog::DontUseNativeDialog)) {
1885 return false;
1886 }
1887
1888 QLatin1String staticName(QColorDialog::staticMetaObject.className());
1889 QLatin1String dynamicName(q->metaObject()->className());
1890 return (staticName == dynamicName);
1891}
1892
1893static const Qt::WindowFlags DefaultWindowFlags =
1894 Qt::Dialog | Qt::WindowTitleHint
1895 | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1896
1897/*!
1898 \class QColorDialog
1899 \brief The QColorDialog class provides a dialog widget for specifying colors.
1900
1901 \ingroup standard-dialogs
1902 \inmodule QtWidgets
1903
1904 The color dialog's function is to allow users to choose colors.
1905 For example, you might use this in a drawing program to allow the
1906 user to set the brush color.
1907
1908 The static functions provide modal color dialogs.
1909 \omit
1910 If you require a modeless dialog, use the QColorDialog constructor.
1911 \endomit
1912
1913 The static getColor() function shows the dialog, and allows the user to
1914 specify a color. This function can also be used to let users choose a
1915 color with a level of transparency: pass the ShowAlphaChannel option as
1916 an additional argument.
1917
1918 The user can store customCount() different custom colors. The
1919 custom colors are shared by all color dialogs, and remembered
1920 during the execution of the program. Use setCustomColor() to set
1921 the custom colors, and use customColor() to get them.
1922
1923 When pressing the "Pick Screen Color" button, the cursor changes to a haircross
1924 and the colors on the screen are scanned. The user can pick up one by clicking
1925 the mouse or the Enter button. Pressing Escape restores the last color selected
1926 before entering this mode.
1927
1928 The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
1929 how to use QColorDialog as well as other built-in Qt dialogs.
1930
1931 \image fusion-colordialog.png A color dialog in the Fusion widget style.
1932
1933 \sa QColor, QFileDialog, QFontDialog, {Standard Dialogs Example}
1934*/
1935
1936/*!
1937 \since 4.5
1938
1939 Constructs a color dialog with the given \a parent.
1940*/
1941QColorDialog::QColorDialog(QWidget *parent)
1942 : QColorDialog(QColor(Qt::white), parent)
1943{
1944}
1945
1946/*!
1947 \since 4.5
1948
1949 Constructs a color dialog with the given \a parent and specified
1950 \a initial color.
1951*/
1952QColorDialog::QColorDialog(const QColor &initial, QWidget *parent)
1953 : QDialog(*new QColorDialogPrivate, parent, DefaultWindowFlags)
1954{
1955 Q_D(QColorDialog);
1956 d->init(initial);
1957}
1958
1959void QColorDialogPrivate::setCurrentColor(const QColor &color, SetColorMode setColorMode)
1960{
1961 if (nativeDialogInUse) {
1962 platformColorDialogHelper()->setCurrentColor(color);
1963 return;
1964 }
1965
1966 if (setColorMode & ShowColor) {
1967 setCurrentRgbColor(color.rgb());
1968 setCurrentAlpha(color.alpha());
1969 }
1970 if (setColorMode & SelectColor)
1971 selectColor(color);
1972}
1973
1974/*!
1975 \property QColorDialog::currentColor
1976 \brief the currently selected color in the dialog
1977*/
1978
1979void QColorDialog::setCurrentColor(const QColor &color)
1980{
1981 Q_D(QColorDialog);
1982 d->setCurrentColor(color);
1983}
1984
1985QColor QColorDialog::currentColor() const
1986{
1987 Q_D(const QColorDialog);
1988 return d->currentQColor();
1989}
1990
1991/*!
1992 Returns the color that the user selected by clicking the \uicontrol{OK}
1993 or equivalent button.
1994
1995 \note This color is not always the same as the color held by the
1996 \l currentColor property since the user can choose different colors
1997 before finally selecting the one to use.
1998*/
1999QColor QColorDialog::selectedColor() const
2000{
2001 Q_D(const QColorDialog);
2002 return d->selectedQColor;
2003}
2004
2005/*!
2006 Sets the given \a option to be enabled if \a on is true;
2007 otherwise, clears the given \a option.
2008
2009 \sa options, testOption()
2010*/
2011void QColorDialog::setOption(ColorDialogOption option, bool on)
2012{
2013 const QColorDialog::ColorDialogOptions previousOptions = options();
2014 if (!(previousOptions & option) != !on)
2015 setOptions(previousOptions ^ option);
2016}
2017
2018/*!
2019 \since 4.5
2020
2021 Returns \c true if the given \a option is enabled; otherwise, returns
2022 false.
2023
2024 \sa options, setOption()
2025*/
2026bool QColorDialog::testOption(ColorDialogOption option) const
2027{
2028 Q_D(const QColorDialog);
2029 return d->options->testOption(static_cast<QColorDialogOptions::ColorDialogOption>(option));
2030}
2031
2032/*!
2033 \property QColorDialog::options
2034 \brief the various options that affect the look and feel of the dialog
2035
2036 By default, all options are disabled.
2037
2038 Options should be set before showing the dialog. Setting them while the
2039 dialog is visible is not guaranteed to have an immediate effect on the
2040 dialog (depending on the option and on the platform).
2041
2042 \sa setOption(), testOption()
2043*/
2044void QColorDialog::setOptions(ColorDialogOptions options)
2045{
2046 Q_D(QColorDialog);
2047
2048 if (QColorDialog::options() == options)
2049 return;
2050
2051 d->options->setOptions(QColorDialogOptions::ColorDialogOptions(int(options)));
2052 if ((options & DontUseNativeDialog) && d->nativeDialogInUse) {
2053 d->nativeDialogInUse = false;
2054 d->initWidgets();
2055 }
2056 if (!d->nativeDialogInUse) {
2057 d->buttons->setVisible(!(options & NoButtons));
2058 d->showAlpha(options & ShowAlphaChannel);
2059 }
2060}
2061
2062QColorDialog::ColorDialogOptions QColorDialog::options() const
2063{
2064 Q_D(const QColorDialog);
2065 return QColorDialog::ColorDialogOptions(int(d->options->options()));
2066}
2067
2068/*!
2069 \enum QColorDialog::ColorDialogOption
2070
2071 \since 4.5
2072
2073 This enum specifies various options that affect the look and feel
2074 of a color dialog.
2075
2076 \value ShowAlphaChannel Allow the user to select the alpha component of a color.
2077 \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".)
2078 \value DontUseNativeDialog Use Qt's standard color dialog instead of the operating system
2079 native color dialog.
2080
2081 \sa options, setOption(), testOption(), windowModality()
2082*/
2083
2084/*!
2085 \fn void QColorDialog::currentColorChanged(const QColor &color)
2086
2087 This signal is emitted whenever the current color changes in the dialog.
2088 The current color is specified by \a color.
2089
2090 \sa color, colorSelected()
2091*/
2092
2093/*!
2094 \fn void QColorDialog::colorSelected(const QColor &color);
2095
2096 This signal is emitted just after the user has clicked \uicontrol{OK} to
2097 select a color to use. The chosen color is specified by \a color.
2098
2099 \sa color, currentColorChanged()
2100*/
2101
2102/*!
2103 Changes the visibility of the dialog. If \a visible is true, the dialog
2104 is shown; otherwise, it is hidden.
2105*/
2106void QColorDialog::setVisible(bool visible)
2107{
2108 Q_D(QColorDialog);
2109
2110 if (visible){
2111 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
2112 return;
2113 } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
2114 return;
2115
2116 if (visible)
2117 d->selectedQColor = QColor();
2118
2119 if (d->nativeDialogInUse) {
2120 d->setNativeDialogVisible(visible);
2121 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
2122 // updates the state correctly, but skips showing the non-native version:
2123 setAttribute(Qt::WA_DontShowOnScreen);
2124 } else {
2125 setAttribute(Qt::WA_DontShowOnScreen, false);
2126 }
2127
2128 QDialog::setVisible(visible);
2129}
2130
2131/*!
2132 \since 4.5
2133
2134 Opens the dialog and connects its colorSelected() signal to the slot specified
2135 by \a receiver and \a member.
2136
2137 The signal will be disconnected from the slot when the dialog is closed.
2138*/
2139void QColorDialog::open(QObject *receiver, const char *member)
2140{
2141 Q_D(QColorDialog);
2142 connect(this, SIGNAL(colorSelected(QColor)), receiver, member);
2143 d->receiverToDisconnectOnClose = receiver;
2144 d->memberToDisconnectOnClose = member;
2145 QDialog::open();
2146}
2147
2148/*!
2149 \since 4.5
2150
2151 Pops up a modal color dialog with the given window \a title (or "Select Color" if none is
2152 specified), lets the user choose a color, and returns that color. The color is initially set
2153 to \a initial. The dialog is a child of \a parent. It returns an invalid (see
2154 QColor::isValid()) color if the user cancels the dialog.
2155
2156 The \a options argument allows you to customize the dialog.
2157*/
2158QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QString &title,
2159 ColorDialogOptions options)
2160{
2161 QColorDialog dlg(parent);
2162 if (!title.isEmpty())
2163 dlg.setWindowTitle(title);
2164 dlg.setOptions(options);
2165 dlg.setCurrentColor(initial);
2166 dlg.exec();
2167 return dlg.selectedColor();
2168}
2169
2170/*!
2171 Destroys the color dialog.
2172*/
2173
2174QColorDialog::~QColorDialog()
2175{
2176
2177}
2178
2179/*!
2180 \reimp
2181*/
2182void QColorDialog::changeEvent(QEvent *e)
2183{
2184 Q_D(QColorDialog);
2185 if (e->type() == QEvent::LanguageChange)
2186 d->retranslateStrings();
2187 QDialog::changeEvent(e);
2188}
2189
2190void QColorDialogPrivate::_q_updateColorPicking()
2191{
2192#ifndef QT_NO_CURSOR
2193 Q_Q(QColorDialog);
2194 static QPoint lastGlobalPos;
2195 QPoint newGlobalPos = QCursor::pos();
2196 if (lastGlobalPos == newGlobalPos)
2197 return;
2198 lastGlobalPos = newGlobalPos;
2199
2200 if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) { // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called
2201 updateColorPicking(newGlobalPos);
2202#ifdef Q_OS_WIN32
2203 dummyTransparentWindow.setPosition(newGlobalPos);
2204#endif
2205 }
2206#endif // ! QT_NO_CURSOR
2207}
2208
2209void QColorDialogPrivate::updateColorPicking(const QPoint &globalPos)
2210{
2211 const QColor color = grabScreenColor(globalPos);
2212 // QTBUG-39792, do not change standard, custom color selectors while moving as
2213 // otherwise it is not possible to pre-select a custom cell for assignment.
2214 setCurrentColor(color, ShowColor);
2215 updateColorLabelText(globalPos);
2216
2217}
2218
2219bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e)
2220{
2221 // If the cross is visible the grabbed color will be black most of the times
2222 cp->setCrossVisible(!cp->geometry().contains(e->position().toPoint()));
2223
2224 updateColorPicking(e->globalPosition().toPoint());
2225 return true;
2226}
2227
2228bool QColorDialogPrivate::handleColorPickingMouseButtonRelease(QMouseEvent *e)
2229{
2230 setCurrentColor(grabScreenColor(e->globalPosition().toPoint()), SetColorAll);
2231 releaseColorPicking();
2232 return true;
2233}
2234
2235bool QColorDialogPrivate::handleColorPickingKeyPress(QKeyEvent *e)
2236{
2237 Q_Q(QColorDialog);
2238#if QT_CONFIG(shortcut)
2239 if (e->matches(QKeySequence::Cancel)) {
2240 releaseColorPicking();
2241 q->setCurrentColor(beforeScreenColorPicking);
2242 } else
2243#endif
2244 if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
2245 q->setCurrentColor(grabScreenColor(QCursor::pos()));
2246 releaseColorPicking();
2247 }
2248 e->accept();
2249 return true;
2250}
2251
2252/*!
2253 Closes the dialog and sets its result code to \a result. If this dialog
2254 is shown with exec(), done() causes the local event loop to finish,
2255 and exec() to return \a result.
2256
2257 \sa QDialog::done()
2258*/
2259void QColorDialog::done(int result)
2260{
2261 Q_D(QColorDialog);
2262 if (result == Accepted) {
2263 d->selectedQColor = d->currentQColor();
2264 emit colorSelected(d->selectedQColor);
2265 } else {
2266 d->selectedQColor = QColor();
2267 }
2268 QDialog::done(result);
2269 if (d->receiverToDisconnectOnClose) {
2270 disconnect(this, SIGNAL(colorSelected(QColor)),
2271 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
2272 d->receiverToDisconnectOnClose = nullptr;
2273 }
2274 d->memberToDisconnectOnClose.clear();
2275}
2276
2277QT_END_NAMESPACE
2278
2279#include "qcolordialog.moc"
2280#include "moc_qcolordialog.cpp"
2281