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

source code of qtbase/src/widgets/dialogs/qcolordialog.cpp