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