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