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