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 QtGui 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 "qpalette.h"
41 #include "qguiapplication.h"
42 #include "qguiapplication_p.h"
43 #include "qdatastream.h"
44 #include "qvariant.h"
45 #include "qdebug.h"
46 
47 QT_BEGIN_NAMESPACE
48 
49 static int qt_palette_count = 1;
50 
51 class QPalettePrivate {
52 public:
QPalettePrivate()53     QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { }
54     QAtomicInt ref;
55     QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
56     int ser_no;
57     int detach_no;
58 };
59 
qt_mix_colors(QColor a,QColor b)60 static QColor qt_mix_colors(QColor a, QColor b)
61 {
62     return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
63                   (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
64 }
65 
qt_palette_from_color(QPalette & pal,const QColor & button)66 static void qt_palette_from_color(QPalette &pal, const QColor &button)
67 {
68     int h, s, v;
69     button.getHsv(&h, &s, &v);
70     // inactive and active are the same..
71     const QBrush whiteBrush = QBrush(Qt::white);
72     const QBrush blackBrush = QBrush(Qt::black);
73     const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
74     const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
75     const QBrush buttonBrush = QBrush(button);
76     const QBrush buttonBrushDark = QBrush(button.darker());
77     const QBrush buttonBrushDark150 = QBrush(button.darker(150));
78     const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
79     pal.setColorGroup(QPalette::Active, foregroundBrush, buttonBrush, buttonBrushLight150,
80                       buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
81                       baseBrush, buttonBrush);
82     pal.setColorGroup(QPalette::Inactive, foregroundBrush, buttonBrush, buttonBrushLight150,
83                       buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
84                       baseBrush, buttonBrush);
85     pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
86                       buttonBrushDark, buttonBrushDark150, buttonBrushDark,
87                       whiteBrush, buttonBrush, buttonBrush);
88 }
89 
90 /*!
91     \fn QPalette &QPalette::operator=(QPalette &&other)
92 
93     Move-assigns \a other to this QPalette instance.
94 
95     \since 5.2
96 */
97 
98 /*!
99    \fn const QColor &QPalette::color(ColorRole role) const
100 
101    \overload
102 
103     Returns the color that has been set for the given color \a role in
104     the current ColorGroup.
105 
106     \sa brush(), ColorRole
107  */
108 
109 /*!
110     \fn const QBrush &QPalette::brush(ColorRole role) const
111 
112     \overload
113 
114     Returns the brush that has been set for the given color \a role in
115     the current ColorGroup.
116 
117     \sa color(), setBrush(), ColorRole
118 */
119 
120 /*!
121     \fn void QPalette::setColor(ColorRole role, const QColor &color)
122 
123     \overload
124 
125     Sets the color used for the given color \a role, in all color
126     groups, to the specified solid \a color.
127 
128     \sa brush(), setColor(), ColorRole
129 */
130 
131 /*!
132     \fn void QPalette::setBrush(ColorRole role, const QBrush &brush)
133 
134     Sets the brush for the given color \a role to the specified \a
135     brush for all groups in the palette.
136 
137     \sa brush(), setColor(), ColorRole
138 */
139 
140 /*!
141     \fn const QBrush & QPalette::foreground() const
142     \obsolete
143 
144     Use windowText() instead.
145 */
146 
147 /*!
148     \fn const QBrush & QPalette::windowText() const
149 
150     Returns the window text (general foreground) brush of the
151     current color group.
152 
153     \sa ColorRole, brush()
154 */
155 
156 /*!
157     \fn const QBrush & QPalette::button() const
158 
159     Returns the button brush of the current color group.
160 
161     \sa ColorRole, brush()
162 */
163 
164 /*!
165     \fn const QBrush & QPalette::light() const
166 
167     Returns the light brush of the current color group.
168 
169     \sa ColorRole, brush()
170 */
171 
172 /*!
173     \fn const QBrush& QPalette::midlight() const
174 
175     Returns the midlight brush of the current color group.
176 
177     \sa ColorRole, brush()
178 */
179 
180 /*!
181     \fn const QBrush & QPalette::dark() const
182 
183     Returns the dark brush of the current color group.
184 
185     \sa ColorRole, brush()
186 */
187 
188 /*!
189     \fn const QBrush & QPalette::mid() const
190 
191     Returns the mid brush of the current color group.
192 
193     \sa ColorRole, brush()
194 */
195 
196 /*!
197     \fn const QBrush & QPalette::text() const
198 
199     Returns the text foreground brush of the current color group.
200 
201     \sa ColorRole, brush()
202 */
203 
204 /*!
205     \fn const QBrush & QPalette::brightText() const
206 
207     Returns the bright text foreground brush of the current color group.
208 
209     \sa ColorRole, brush()
210 */
211 
212 /*!
213     \fn const QBrush & QPalette::buttonText() const
214 
215     Returns the button text foreground brush of the current color group.
216 
217     \sa ColorRole, brush()
218 */
219 
220 /*!
221     \fn const QBrush & QPalette::base() const
222 
223     Returns the base brush of the current color group.
224 
225     \sa ColorRole, brush()
226 */
227 
228 /*!
229     \fn const QBrush & QPalette::alternateBase() const
230 
231     Returns the alternate base brush of the current color group.
232 
233     \sa ColorRole, brush()
234 */
235 
236 /*!
237     \fn const QBrush & QPalette::toolTipBase() const
238     \since 4.4
239 
240     Returns the tool tip base brush of the current color group. This brush is
241     used by QToolTip and QWhatsThis.
242 
243     \note Tool tips use the Inactive color group of QPalette, because tool
244     tips are not active windows.
245 
246     \sa ColorRole, brush()
247 */
248 
249 /*!
250     \fn const QBrush & QPalette::toolTipText() const
251     \since 4.4
252 
253     Returns the tool tip text brush of the current color group. This brush is
254     used by QToolTip and QWhatsThis.
255 
256     \note Tool tips use the Inactive color group of QPalette, because tool
257     tips are not active windows.
258 
259     \sa ColorRole, brush()
260 */
261 
262 /*!
263     \fn const QBrush & QPalette::background() const
264     \obsolete
265 
266     Use window() instead.
267 */
268 
269 /*!
270     \fn const QBrush & QPalette::window() const
271 
272     Returns the window (general background) brush of the current
273     color group.
274 
275     \sa ColorRole, brush()
276 */
277 
278 /*!
279     \fn const QBrush & QPalette::shadow() const
280 
281     Returns the shadow brush of the current color group.
282 
283     \sa ColorRole, brush()
284 */
285 
286 /*!
287     \fn const QBrush & QPalette::highlight() const
288 
289     Returns the highlight brush of the current color group.
290 
291     \sa ColorRole, brush()
292 */
293 
294 /*!
295     \fn const QBrush & QPalette::highlightedText() const
296 
297     Returns the highlighted text brush of the current color group.
298 
299     \sa ColorRole, brush()
300 */
301 
302 /*!
303     \fn const QBrush & QPalette::link() const
304 
305     Returns the unvisited link text brush of the current color group.
306 
307     \sa ColorRole, brush()
308 */
309 
310 /*!
311     \fn const QBrush & QPalette::linkVisited() const
312 
313     Returns the visited link text brush of the current color group.
314 
315     \sa ColorRole, brush()
316 */
317 
318 /*!
319     \fn const QBrush & QPalette::placeholderText() const
320     \since 5.12
321 
322     Returns the placeholder text brush of the current color group.
323 
324     \note Before Qt 5.12, the placeholder text color was hard-coded in the code as
325     QPalette::text().color() where an alpha of 128 was applied.
326     We continue to support this behavior by default, unless you set your own brush.
327     One can get back the original placeholder color setting the special QBrush default
328     constructor as placeholder brush.
329 
330     \sa ColorRole, brush()
331 */
332 
333 /*!
334     \fn ColorGroup QPalette::currentColorGroup() const
335 
336     Returns the palette's current color group.
337 */
338 
339 /*!
340     \fn void QPalette::setCurrentColorGroup(ColorGroup cg)
341 
342     Set the palette's current color group to \a cg.
343 */
344 
345 /*!
346     \class QPalette
347 
348     \brief The QPalette class contains color groups for each widget state.
349 
350     \inmodule QtGui
351     \ingroup appearance
352     \ingroup shared
353 
354     A palette consists of three color groups: \e Active, \e Disabled,
355     and \e Inactive. All widgets in Qt contain a palette and
356     use their palette to draw themselves. This makes the user
357     interface easily configurable and easier to keep consistent.
358 
359 
360     If you create a new widget we strongly recommend that you use the
361     colors in the palette rather than hard-coding specific colors.
362 
363     The color groups:
364     \list
365     \li The Active group is used for the window that has keyboard focus.
366     \li The Inactive group is used for other windows.
367     \li The Disabled group is used for widgets (not windows) that are
368     disabled for some reason.
369     \endlist
370 
371     Both active and inactive windows can contain disabled widgets.
372     (Disabled widgets are often called \e inaccessible or \e{grayed
373     out}.)
374 
375     In most styles, Active and Inactive look the same.
376 
377     Colors and brushes can be set for particular roles in any of a palette's
378     color groups with setColor() and setBrush().  A color group contains a
379     group of colors used by widgets for drawing themselves. We recommend that
380     widgets use color group roles from the palette such as "foreground" and
381     "base" rather than literal colors like "red" or "turquoise". The color
382     roles are enumerated and defined in the \l ColorRole documentation.
383 
384     We strongly recommend that you use the default palette of the
385     current style (returned by QGuiApplication::palette()) and
386     modify that as necessary. This is done by Qt's widgets when they
387     are drawn.
388 
389     To modify a color group you call the functions
390     setColor() and setBrush(), depending on whether you want a pure
391     color or a pixmap pattern.
392 
393     There are also corresponding color() and brush() getters, and a
394     commonly used convenience function to get the ColorRole for the current ColorGroup:
395     window(), windowText(), base(), etc.
396 
397 
398     You can copy a palette using the copy constructor and test to see
399     if two palettes are \e identical using isCopyOf().
400 
401     QPalette is optimized by the use of \l{implicit sharing},
402     so it is very efficient to pass QPalette objects as arguments.
403 
404     \warning Some styles do not use the palette for all drawing, for
405     instance, if they make use of native theme engines. This is the
406     case for both the Windows Vista and the \macos
407     styles.
408 
409     \sa QApplication::setPalette(), QWidget::setPalette(), QColor
410 */
411 
412 /*!
413     \enum QPalette::ColorGroup
414 
415     \value Disabled
416     \value Active
417     \value Inactive
418     \value Normal synonym for Active
419 
420     \omitvalue All
421     \omitvalue NColorGroups
422     \omitvalue Current
423 */
424 
425 /*!
426     \enum QPalette::ColorRole
427 
428     \image palette.png Color Roles
429 
430     The ColorRole enum defines the different symbolic color roles used
431     in current GUIs.
432 
433     The central roles are:
434 
435     \value Window  A general background color.
436 
437     \value Background  This value is obsolete. Use Window instead.
438 
439     \value WindowText  A general foreground color.
440 
441     \value Foreground  This value is obsolete. Use WindowText instead.
442 
443     \value Base  Used mostly as the background color for text entry widgets,
444                  but can also be used for other painting - such as the
445                  background of combobox drop down lists and toolbar handles.
446                  It is usually white or another light color.
447 
448     \value AlternateBase  Used as the alternate background color in views with
449                           alternating row colors (see
450                           QAbstractItemView::setAlternatingRowColors()).
451 
452     \value ToolTipBase Used as the background color for QToolTip and
453                           QWhatsThis. Tool tips use the Inactive color group
454                           of QPalette, because tool tips are not active
455                           windows.
456 
457     \value ToolTipText Used as the foreground color for QToolTip and
458                           QWhatsThis. Tool tips use the Inactive color group
459                           of QPalette, because tool tips are not active
460                           windows.
461 
462     \value PlaceholderText Used as the placeholder color for various text input widgets.
463            This enum value has been introduced in Qt 5.12
464 
465     \value Text  The foreground color used with \c Base. This is usually
466                  the same as the \c WindowText, in which case it must provide
467                  good contrast with \c Window and \c Base.
468 
469     \value Button The general button background color. This background can be different from
470                   \c Window as some styles require a different background color for buttons.
471 
472     \value ButtonText  A foreground color used with the \c Button color.
473 
474     \value BrightText  A text color that is very different from
475                        \c WindowText, and contrasts well with e.g. \c
476                        Dark. Typically used for text that needs to be
477                        drawn where \c Text or \c WindowText would give
478                        poor contrast, such as on pressed push buttons.
479                        Note that text colors can be used for things
480                        other than just words; text colors are \e
481                        usually used for text, but it's quite common to
482                        use the text color roles for lines, icons, etc.
483 
484 
485     There are some color roles used mostly for 3D bevel and shadow effects.
486     All of these are normally derived from \c Window, and used in ways that
487     depend on that relationship. For example, buttons depend on it to make the
488     bevels look attractive, and Motif scroll bars depend on \c Mid to be
489     slightly different from \c Window.
490 
491     \value Light  Lighter than \c Button color.
492 
493     \value Midlight  Between \c Button and \c Light.
494 
495     \value Dark  Darker than \c Button.
496 
497     \value Mid  Between \c Button and \c Dark.
498 
499     \value Shadow  A very dark color. By default, the shadow color is
500                    Qt::black.
501 
502 
503     Selected (marked) items have two roles:
504 
505     \value Highlight   A color to indicate a selected item or the current
506                        item. By default, the highlight color is
507                        Qt::darkBlue.
508 
509     \value HighlightedText  A text color that contrasts with \c Highlight.
510                             By default, the highlighted text color is Qt::white.
511 
512     There are two color roles related to hyperlinks:
513 
514     \value Link  A text color used for unvisited hyperlinks.
515                  By default, the link color is Qt::blue.
516 
517     \value LinkVisited  A text color used for already visited hyperlinks.
518                         By default, the linkvisited color is Qt::magenta.
519 
520     Note that we do not use the \c Link and \c LinkVisited roles when
521     rendering rich text in Qt, and that we recommend that you use CSS
522     and the QTextDocument::setDefaultStyleSheet() function to alter
523     the appearance of links. For example:
524 
525     \snippet textdocument-css/main.cpp 0
526 
527     \value NoRole No role; this special role is often used to indicate that a
528     role has not been assigned.
529 
530     \omitvalue NColorRoles
531 */
532 
533 /*!
534     Constructs a palette object that uses the application's default palette.
535 
536     \sa QApplication::setPalette(), QApplication::palette()
537 */
QPalette()538 QPalette::QPalette()
539     : d(nullptr)
540 {
541     data.current_group = Active;
542     data.resolve_mask = 0;
543     // Initialize to application palette if present, else default to black.
544     // This makes it possible to instantiate QPalette outside QGuiApplication,
545     // for example in the platform plugins.
546     if (QGuiApplicationPrivate::app_pal) {
547         d = QGuiApplicationPrivate::app_pal->d;
548         d->ref.ref();
549     } else {
550         init();
551         qt_palette_from_color(*this, Qt::black);
552         data.resolve_mask = 0;
553     }
554 }
555 
556 /*!
557   Constructs a palette from the \a button color. The other colors are
558   automatically calculated, based on this color. \c Window will be
559   the button color as well.
560 */
QPalette(const QColor & button)561 QPalette::QPalette(const QColor &button)
562 {
563     init();
564     qt_palette_from_color(*this, button);
565 }
566 
567 /*!
568   Constructs a palette from the \a button color. The other colors are
569   automatically calculated, based on this color. \c Window will be
570   the button color as well.
571 */
QPalette(Qt::GlobalColor button)572 QPalette::QPalette(Qt::GlobalColor button)
573 {
574     init();
575     qt_palette_from_color(*this, button);
576 }
577 
578 /*!
579     Constructs a palette. You can pass either brushes, pixmaps or
580     plain colors for \a windowText, \a button, \a light, \a dark, \a
581     mid, \a text, \a bright_text, \a base and \a window.
582 
583     \sa QBrush
584 */
QPalette(const QBrush & windowText,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & window)585 QPalette::QPalette(const QBrush &windowText, const QBrush &button,
586                    const QBrush &light, const QBrush &dark,
587                    const QBrush &mid, const QBrush &text,
588                    const QBrush &bright_text, const QBrush &base,
589                    const QBrush &window)
590 {
591     init();
592     setColorGroup(All, windowText, button, light, dark, mid, text, bright_text,
593                   base, window);
594 }
595 
596 
597 /*!\obsolete
598 
599   Constructs a palette with the specified \a windowText, \a
600   window, \a light, \a dark, \a mid, \a text, and \a base colors.
601   The button color will be set to the window color.
602 */
QPalette(const QColor & windowText,const QColor & window,const QColor & light,const QColor & dark,const QColor & mid,const QColor & text,const QColor & base)603 QPalette::QPalette(const QColor &windowText, const QColor &window,
604                    const QColor &light, const QColor &dark, const QColor &mid,
605                    const QColor &text, const QColor &base)
606 {
607     init();
608     const QBrush windowBrush(window);
609     const QBrush lightBrush(light);
610     setColorGroup(All, QBrush(windowText), windowBrush, lightBrush,
611                   QBrush(dark), QBrush(mid), QBrush(text), lightBrush,
612                   QBrush(base), windowBrush);
613 }
614 
615 /*!
616     Constructs a palette from a \a button color and a \a window.
617     The other colors are automatically calculated, based on these
618     colors.
619 */
QPalette(const QColor & button,const QColor & window)620 QPalette::QPalette(const QColor &button, const QColor &window)
621 {
622     init();
623     int h, s, v;
624     window.getHsv(&h, &s, &v);
625 
626     const QBrush windowBrush = QBrush(window);
627     const QBrush whiteBrush = QBrush(Qt::white);
628     const QBrush blackBrush = QBrush(Qt::black);
629     const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
630     const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
631     const QBrush disabledForeground = QBrush(Qt::darkGray);
632 
633     const QBrush buttonBrush = QBrush(button);
634     const QBrush buttonBrushDark = QBrush(button.darker());
635     const QBrush buttonBrushDark150 = QBrush(button.darker(150));
636     const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
637 
638     //inactive and active are identical
639     setColorGroup(Inactive, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
640                   buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
641                   windowBrush);
642     setColorGroup(Active, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
643                   buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
644                   windowBrush);
645     setColorGroup(Disabled, disabledForeground, buttonBrush, buttonBrushLight150,
646                   buttonBrushDark, buttonBrushDark150, disabledForeground,
647                   whiteBrush, baseBrush, windowBrush);
648 }
649 
650 /*!
651     Constructs a copy of \a p.
652 
653     This constructor is fast thanks to \l{implicit sharing}.
654 */
QPalette(const QPalette & p)655 QPalette::QPalette(const QPalette &p)
656     : d(p.d), data(p.data)
657 {
658     d->ref.ref();
659 }
660 
661 /*!
662     \fn QPalette::QPalette(QPalette &&other)
663     \since 5.4
664 
665     Move-constructs a QPalette instance, making it point at the same
666     object that \a other was pointing to.
667 
668     After being moved from, you can only assign to or destroy \a other.
669     Any other operation will result in undefined behavior.
670 */
671 
672 /*!
673     Destroys the palette.
674 */
~QPalette()675 QPalette::~QPalette()
676 {
677     if (d && !d->ref.deref())
678         delete d;
679 }
680 
681 /*!\internal*/
init()682 void QPalette::init() {
683     d = new QPalettePrivate;
684     data.resolve_mask = 0;
685     data.current_group = Active; //as a default..
686 }
687 
688 /*!
689     Assigns \a p to this palette and returns a reference to this
690     palette.
691 
692     This operation is fast thanks to \l{implicit sharing}.
693 */
operator =(const QPalette & p)694 QPalette &QPalette::operator=(const QPalette &p)
695 {
696     p.d->ref.ref();
697     data = p.data;
698     if (d && !d->ref.deref())
699         delete d;
700     d = p.d;
701     return *this;
702 }
703 
704 /*!
705     \fn void QPalette::swap(QPalette &other)
706     \since 5.0
707 
708     Swaps this palette instance with \a other. This function is very
709     fast and never fails.
710 */
711 
712 /*!
713    Returns the palette as a QVariant
714 */
operator QVariant() const715 QPalette::operator QVariant() const
716 {
717     return QVariant(QMetaType::QPalette, this);
718 }
719 
720 /*!
721     \fn const QColor &QPalette::color(ColorGroup group, ColorRole role) const
722 
723     Returns the color in the specified color \a group, used for the
724     given color \a role.
725 
726     \sa brush(), setColor(), ColorRole
727 */
728 
729 /*!
730     \fn const QBrush &QPalette::brush(ColorGroup group, ColorRole role) const
731 
732     Returns the brush in the specified color \a group, used for the
733     given color \a role.
734 
735     \sa color(), setBrush(), ColorRole
736 */
brush(ColorGroup gr,ColorRole cr) const737 const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const
738 {
739     Q_ASSERT(cr < NColorRoles);
740     if(gr >= (int)NColorGroups) {
741         if(gr == Current) {
742             gr = (ColorGroup)data.current_group;
743         } else {
744             qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr);
745             gr = Active;
746         }
747     }
748     return d->br[gr][cr];
749 }
750 
751 /*!
752     \fn void QPalette::setColor(ColorGroup group, ColorRole role, const QColor &color)
753 
754     Sets the color in the specified color \a group, used for the given
755     color \a role, to the specified solid \a color.
756 
757     \sa setBrush(), color(), ColorRole
758 */
759 
760 /*!
761     \fn void QPalette::setBrush(ColorGroup group, ColorRole role, const QBrush &brush)
762     \overload
763 
764     Sets the brush in the specified color \a group, used for the given
765     color \a role, to \a brush.
766 
767     \sa brush(), setColor(), ColorRole
768 */
setBrush(ColorGroup cg,ColorRole cr,const QBrush & b)769 void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
770 {
771     Q_ASSERT(cr < NColorRoles);
772 
773     if (cg == All) {
774         for (uint i = 0; i < NColorGroups; i++)
775             setBrush(ColorGroup(i), cr, b);
776         return;
777     }
778 
779     if (cg == Current) {
780         cg = ColorGroup(data.current_group);
781     } else if (cg >= NColorGroups) {
782         qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg);
783         cg = Active;
784     }
785 
786     // For placeholder we want to continue to respect the original behavior, which is
787     // derivating the text color, but only if user has not yet set his own brush.
788     // We then use Qt::NoBrush as an inernal way to know if the brush is customized or not.
789 
790     // ### Qt 6 - remove this special case
791     // Part 1 - Restore initial color to the given color group
792     if (cr == PlaceholderText && b == QBrush()) {
793         QColor col = brush(Text).color();
794         col.setAlpha(128);
795         setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
796         return;
797     }
798 
799     if (d->br[cg][cr] != b) {
800         detach();
801         d->br[cg][cr] = b;
802     }
803     data.resolve_mask |= (1<<cr);
804 
805     // ### Qt 6 - remove this special case
806     // Part 2 - Update initial color to the given color group
807     if (cr == Text && d->br[cg][PlaceholderText].style() == Qt::NoBrush) {
808         QColor col = brush(Text).color();
809         col.setAlpha(128);
810         setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
811     }
812 }
813 
814 /*!
815     \since 4.2
816 
817     Returns \c true if the ColorGroup \a cg and ColorRole \a cr has been
818     set previously on this palette; otherwise returns \c false.
819 
820     \sa setBrush()
821 */
isBrushSet(ColorGroup cg,ColorRole cr) const822 bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
823 {
824     Q_UNUSED(cg);
825     return (data.resolve_mask & (1<<cr));
826 }
827 
828 /*!
829     \internal
830 */
detach()831 void QPalette::detach()
832 {
833     if (d->ref.loadRelaxed() != 1) {
834         QPalettePrivate *x = new QPalettePrivate;
835         for(int grp = 0; grp < (int)NColorGroups; grp++) {
836             for(int role = 0; role < (int)NColorRoles; role++)
837                 x->br[grp][role] = d->br[grp][role];
838         }
839         if(!d->ref.deref())
840             delete d;
841         d = x;
842     }
843     ++d->detach_no;
844 }
845 
846 /*!
847     \fn bool QPalette::operator!=(const QPalette &p) const
848 
849     Returns \c true (slowly) if this palette is different from \a p;
850     otherwise returns \c false (usually quickly).
851 
852     \note The current ColorGroup is not taken into account when
853     comparing palettes
854 
855     \sa operator==()
856 */
857 
858 /*!
859     Returns \c true (usually quickly) if this palette is equal to \a p;
860     otherwise returns \c false (slowly).
861 
862     \note The current ColorGroup is not taken into account when
863     comparing palettes
864 
865     \sa operator!=()
866 */
operator ==(const QPalette & p) const867 bool QPalette::operator==(const QPalette &p) const
868 {
869     if (isCopyOf(p))
870         return true;
871     for(int grp = 0; grp < (int)NColorGroups; grp++) {
872         for(int role = 0; role < (int)NColorRoles; role++) {
873             if(d->br[grp][role] != p.d->br[grp][role])
874                 return false;
875         }
876     }
877     return true;
878 }
879 
880 /*!
881     \fn bool QPalette::isEqual(ColorGroup cg1, ColorGroup cg2) const
882 
883     Returns \c true (usually quickly) if color group \a cg1 is equal to
884     \a cg2; otherwise returns \c false.
885 */
isEqual(QPalette::ColorGroup group1,QPalette::ColorGroup group2) const886 bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) const
887 {
888     if(group1 >= (int)NColorGroups) {
889         if(group1 == Current) {
890             group1 = (ColorGroup)data.current_group;
891         } else {
892             qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1);
893             group1 = Active;
894         }
895     }
896     if(group2 >= (int)NColorGroups) {
897         if(group2 == Current) {
898             group2 = (ColorGroup)data.current_group;
899         } else {
900             qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2);
901             group2 = Active;
902         }
903     }
904     if(group1 == group2)
905         return true;
906     for(int role = 0; role < (int)NColorRoles; role++) {
907         if(d->br[group1][role] != d->br[group2][role])
908                 return false;
909     }
910     return true;
911 }
912 
913 /*! \fn int QPalette::serialNumber() const
914     \obsolete
915 
916     Returns a number that identifies the contents of this QPalette
917     object. Distinct QPalette objects can only have the same serial
918     number if they refer to the same contents (but they don't have
919     to). Also, the serial number of a QPalette may change during the
920     lifetime of the object.
921 
922     Use cacheKey() instead.
923 
924     \warning The serial number doesn't necessarily change when the
925     palette is altered. This means that it may be dangerous to use it
926     as a cache key.
927 
928     \sa operator==()
929 */
930 
931 /*!
932     Returns a number that identifies the contents of this QPalette
933     object. Distinct QPalette objects can have the same key if
934     they refer to the same contents.
935 
936     The cacheKey() will change when the palette is altered.
937 */
cacheKey() const938 qint64 QPalette::cacheKey() const
939 {
940     return (((qint64) d->ser_no) << 32) | ((qint64) (d->detach_no));
941 }
942 
943 /*!
944     Returns a new QPalette that is a union of this instance and \a other.
945     Color roles set in this instance take precedence.
946 */
resolve(const QPalette & other) const947 QPalette QPalette::resolve(const QPalette &other) const
948 {
949     if ((*this == other && data.resolve_mask == other.data.resolve_mask)
950         || data.resolve_mask == 0) {
951         QPalette o = other;
952         o.data.resolve_mask = data.resolve_mask;
953         return o;
954     }
955 
956     QPalette palette(*this);
957     palette.detach();
958 
959     for(int role = 0; role < (int)NColorRoles; role++)
960         if (!(data.resolve_mask & (1<<role)))
961             for(int grp = 0; grp < (int)NColorGroups; grp++)
962                 palette.d->br[grp][role] = other.d->br[grp][role];
963     palette.data.resolve_mask |= other.data.resolve_mask;
964 
965     return palette;
966 }
967 
968 /*!
969     \fn uint QPalette::resolve() const
970     \internal
971 */
972 
973 /*!
974     \fn void QPalette::resolve(uint mask)
975     \internal
976 */
977 
978 
979 /*****************************************************************************
980   QPalette stream functions
981  *****************************************************************************/
982 
983 #ifndef QT_NO_DATASTREAM
984 
985 static const int NumOldRoles = 7;
986 static const int oldRoles[7] = { QPalette::WindowText, QPalette::Window, QPalette::Light,
987                                  QPalette::Dark, QPalette::Mid, QPalette::Text, QPalette::Base };
988 
989 /*!
990     \relates QPalette
991 
992     Writes the palette, \a p to the stream \a s and returns a
993     reference to the stream.
994 
995     \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
996 */
997 
operator <<(QDataStream & s,const QPalette & p)998 QDataStream &operator<<(QDataStream &s, const QPalette &p)
999 {
1000     for (int grp = 0; grp < (int)QPalette::NColorGroups; grp++) {
1001         if (s.version() == 1) {
1002             // Qt 1.x
1003             for (int i = 0; i < NumOldRoles; ++i)
1004                 s << p.d->br[grp][oldRoles[i]].color();
1005         } else {
1006             int max = (int)QPalette::NColorRoles;
1007             if (s.version() <= QDataStream::Qt_2_1)
1008                 max = QPalette::HighlightedText + 1;
1009             else if (s.version() <= QDataStream::Qt_4_3)
1010                 max = QPalette::AlternateBase + 1;
1011             else if (s.version() <= QDataStream::Qt_5_11)
1012                 max = QPalette::ToolTipText + 1;
1013             for (int r = 0; r < max; r++)
1014                 s << p.d->br[grp][r];
1015         }
1016     }
1017     return s;
1018 }
1019 
readV1ColorGroup(QDataStream & s,QPalette & pal,QPalette::ColorGroup grp)1020 static void readV1ColorGroup(QDataStream &s, QPalette &pal, QPalette::ColorGroup grp)
1021 {
1022     for (int i = 0; i < NumOldRoles; ++i) {
1023         QColor col;
1024         s >> col;
1025         pal.setColor(grp, (QPalette::ColorRole)oldRoles[i], col);
1026     }
1027 }
1028 
1029 /*!
1030     \relates QPalette
1031 
1032     Reads a palette from the stream, \a s into the palette \a p, and
1033     returns a reference to the stream.
1034 
1035     \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1036 */
1037 
operator >>(QDataStream & s,QPalette & p)1038 QDataStream &operator>>(QDataStream &s, QPalette &p)
1039 {
1040     if(s.version() == 1) {
1041         p = QPalette();
1042         readV1ColorGroup(s, p, QPalette::Active);
1043         readV1ColorGroup(s, p, QPalette::Disabled);
1044         readV1ColorGroup(s, p, QPalette::Inactive);
1045     } else {
1046         int max = QPalette::NColorRoles;
1047         if (s.version() <= QDataStream::Qt_2_1) {
1048             p = QPalette();
1049             max = QPalette::HighlightedText + 1;
1050         } else if (s.version() <= QDataStream::Qt_4_3) {
1051             p = QPalette();
1052             max = QPalette::AlternateBase + 1;
1053         } else if (s.version() <= QDataStream::Qt_5_11) {
1054             p = QPalette();
1055             max = QPalette::ToolTipText + 1;
1056         }
1057 
1058         QBrush tmp;
1059         for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
1060             for(int role = 0; role < max; ++role) {
1061                 s >> tmp;
1062                 p.setBrush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role, tmp);
1063             }
1064         }
1065     }
1066     return s;
1067 }
1068 #endif //QT_NO_DATASTREAM
1069 
1070 /*!
1071     Returns \c true if this palette and \a p are copies of each other,
1072     i.e. one of them was created as a copy of the other and neither
1073     was subsequently modified; otherwise returns \c false. This is much
1074     stricter than equality.
1075 
1076     \sa operator=(), operator==()
1077 */
1078 
isCopyOf(const QPalette & p) const1079 bool QPalette::isCopyOf(const QPalette &p) const
1080 {
1081     return d == p.d;
1082 }
1083 
1084 /*!
1085 
1086     Sets a the group at \a cg. You can pass either brushes, pixmaps or
1087     plain colors for \a windowText, \a button, \a light, \a dark, \a
1088     mid, \a text, \a bright_text, \a base and \a window.
1089 
1090     \sa QBrush
1091 */
setColorGroup(ColorGroup cg,const QBrush & windowText,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & window)1092 void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBrush &button,
1093                              const QBrush &light, const QBrush &dark, const QBrush &mid,
1094                              const QBrush &text, const QBrush &bright_text, const QBrush &base,
1095                              const QBrush &window)
1096 {
1097     QBrush alt_base = QBrush(qt_mix_colors(base.color(), button.color()));
1098     QBrush mid_light = QBrush(qt_mix_colors(button.color(), light.color()));
1099     QColor toolTipBase(255, 255, 220);
1100     QColor toolTipText(0, 0, 0);
1101 
1102     setColorGroup(cg, windowText, button, light, dark, mid, text, bright_text, base,
1103                   alt_base, window, mid_light, text,
1104                   QBrush(Qt::black), QBrush(Qt::darkBlue), QBrush(Qt::white),
1105                   QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase),
1106                   QBrush(toolTipText));
1107 
1108     data.resolve_mask &= ~(1 << Highlight);
1109     data.resolve_mask &= ~(1 << HighlightedText);
1110     data.resolve_mask &= ~(1 << LinkVisited);
1111     data.resolve_mask &= ~(1 << Link);
1112 }
1113 
1114 
1115 /*!\internal*/
1116 void
setColorGroup(ColorGroup cg,const QBrush & foreground,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & alternate_base,const QBrush & background,const QBrush & midlight,const QBrush & button_text,const QBrush & shadow,const QBrush & highlight,const QBrush & highlighted_text,const QBrush & link,const QBrush & link_visited)1117 QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
1118                         const QBrush &light, const QBrush &dark, const QBrush &mid,
1119                         const QBrush &text, const QBrush &bright_text,
1120                         const QBrush &base, const QBrush &alternate_base,
1121                         const QBrush &background, const QBrush &midlight,
1122                         const QBrush &button_text, const QBrush &shadow,
1123                         const QBrush &highlight, const QBrush &highlighted_text,
1124                         const QBrush &link, const QBrush &link_visited)
1125 {
1126     setColorGroup(cg, foreground, button, light, dark, mid,
1127                   text, bright_text, base, alternate_base, background,
1128                   midlight, button_text, shadow, highlight, highlighted_text,
1129                   link, link_visited, background, foreground);
1130 }
1131 
1132 /*!\internal*/
setColorGroup(ColorGroup cg,const QBrush & foreground,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & alternate_base,const QBrush & background,const QBrush & midlight,const QBrush & button_text,const QBrush & shadow,const QBrush & highlight,const QBrush & highlighted_text,const QBrush & link,const QBrush & link_visited,const QBrush & toolTipBase,const QBrush & toolTipText)1133 void QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
1134                              const QBrush &light, const QBrush &dark, const QBrush &mid,
1135                              const QBrush &text, const QBrush &bright_text,
1136                              const QBrush &base, const QBrush &alternate_base,
1137                              const QBrush &background, const QBrush &midlight,
1138                              const QBrush &button_text, const QBrush &shadow,
1139                              const QBrush &highlight, const QBrush &highlighted_text,
1140                              const QBrush &link, const QBrush &link_visited,
1141                              const QBrush &toolTipBase, const QBrush &toolTipText)
1142 {
1143     setBrush(cg, WindowText, foreground);
1144     setBrush(cg, Button, button);
1145     setBrush(cg, Light, light);
1146     setBrush(cg, Dark, dark);
1147     setBrush(cg, Mid, mid);
1148     setBrush(cg, Text, text);
1149     setBrush(cg, BrightText, bright_text);
1150     setBrush(cg, Base, base);
1151     setBrush(cg, AlternateBase, alternate_base);
1152     setBrush(cg, Window, background);
1153     setBrush(cg, Midlight, midlight);
1154     setBrush(cg, ButtonText, button_text);
1155     setBrush(cg, Shadow, shadow);
1156     setBrush(cg, Highlight, highlight);
1157     setBrush(cg, HighlightedText, highlighted_text);
1158     setBrush(cg, Link, link);
1159     setBrush(cg, LinkVisited, link_visited);
1160     setBrush(cg, ToolTipBase, toolTipBase);
1161     setBrush(cg, ToolTipText, toolTipText);
1162 }
1163 
qt_fusionPalette()1164 Q_GUI_EXPORT QPalette qt_fusionPalette()
1165 {
1166     QColor backGround(239, 239, 239);
1167     QColor light = backGround.lighter(150);
1168     QColor mid(backGround.darker(130));
1169     QColor midLight = mid.lighter(110);
1170     QColor base = Qt::white;
1171     QColor disabledBase(backGround);
1172     QColor dark = backGround.darker(150);
1173     QColor darkDisabled = QColor(209, 209, 209).darker(110);
1174     QColor text = Qt::black;
1175     QColor hightlightedText = Qt::white;
1176     QColor disabledText = QColor(190, 190, 190);
1177     QColor button = backGround;
1178     QColor shadow = dark.darker(135);
1179     QColor disabledShadow = shadow.lighter(150);
1180 
1181     QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base);
1182     fusionPalette.setBrush(QPalette::Midlight, midLight);
1183     fusionPalette.setBrush(QPalette::Button, button);
1184     fusionPalette.setBrush(QPalette::Shadow, shadow);
1185     fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText);
1186 
1187     fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);
1188     fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);
1189     fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);
1190     fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);
1191     fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);
1192     fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);
1193 
1194     fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198));
1195     fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198));
1196     fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145));
1197     return fusionPalette;
1198 }
1199 
1200 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QPalette & p)1201 QDebug operator<<(QDebug dbg, const QPalette &p)
1202 {
1203     const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"};
1204     const char *colorRoleNames[] =
1205         {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text",
1206          "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight",
1207          "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole",
1208          "ToolTipBase","ToolTipText", "PlaceholderText" };
1209     QDebugStateSaver saver(dbg);
1210     QDebug nospace = dbg.nospace();
1211     const uint mask = p.resolve();
1212     nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ',';
1213     for (int role = 0; role < (int)QPalette::NColorRoles; ++role) {
1214         if (mask & (1<<role)) {
1215             if (role)
1216                 nospace << ',';
1217             nospace << colorRoleNames[role] << ":[";
1218             for (int group = 0; group < (int)QPalette::NColorGroups; ++group) {
1219                 if (group)
1220                     nospace << ',';
1221                 const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group),
1222                                            static_cast<QPalette::ColorRole>(role)).rgba();
1223                 nospace << colorGroupNames[group] << ':' << color;
1224             }
1225             nospace << ']';
1226         }
1227     }
1228     nospace << ')' << Qt::noshowbase << Qt::dec;
1229     return dbg;
1230 }
1231 #endif
1232 
1233 QT_END_NAMESPACE
1234