Coverage Report

Created: 2026-04-01 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/kernel/qpalette.cpp
Line
Count
Source
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"
6
#include "qguiapplication_p.h"
7
#include "qdatastream.h"
8
#include "qvariant.h"
9
#include "qdebug.h"
10
11
#include <QtCore/qmetaobject.h>
12
13
QT_BEGIN_NAMESPACE
14
15
Q_CONSTINIT QAtomicInt QPalettePrivate::qt_palette_count = Q_BASIC_ATOMIC_INITIALIZER(0);
16
Q_CONSTINIT QAtomicInt QPalettePrivate::qt_palette_private_count = Q_BASIC_ATOMIC_INITIALIZER(0);
17
18
static_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
23
static QColor qt_mix_colors(QColor a, QColor b)
24
0
{
25
0
    return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
26
0
                  (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
27
0
}
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
*/
39
static void qt_placeholder_from_text(QPalette &pal, int alpha = 50)
40
0
{
41
0
    if (alpha < 0 or alpha > 100)
42
0
        return;
43
44
0
    for (int cg = 0; cg < int(QPalette::NColorGroups); ++cg) {
45
0
        const QPalette::ColorGroup group = QPalette::ColorGroup(cg);
46
47
        // skip if the brush has been set already
48
0
        if (!pal.isBrushSet(group, QPalette::PlaceholderText)) {
49
0
            QColor c = pal.color(group, QPalette::Text);
50
0
            const int a = (c.alpha() * alpha) / 100;
51
0
            c.setAlpha(a);
52
0
            pal.setColor(group, QPalette::PlaceholderText, c);
53
0
        }
54
0
    }
55
0
}
56
57
static void qt_ensure_default_accent_color(QPalette &pal)
58
0
{
59
    // have a lighter/darker factor handy, depending on dark/light heuristics
60
0
    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
0
    for (int i = 0; i < QPalette::NColorGroups; ++i) {
64
0
        const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(i);
65
0
        if (!pal.isBrushSet(group, QPalette::Accent)) {
66
            // Default to highlight if available, otherwise use a shade of base
67
0
            const QBrush accentBrush = pal.isBrushSet(group, QPalette::Highlight)
68
0
                                     ? pal.brush(group, QPalette::Highlight)
69
0
                                     : pal.brush(group, QPalette::Base).color().lighter(lighter);
70
0
            pal.setBrush(group, QPalette::Accent, accentBrush);
71
0
        }
72
0
    }
73
0
}
74
75
static void qt_palette_from_color(QPalette &pal, const QColor &button)
76
0
{
77
0
    int h, s, v;
78
0
    button.getHsv(&h, &s, &v);
79
    // inactive and active are the same..
80
0
    const QBrush whiteBrush = QBrush(Qt::white);
81
0
    const QBrush blackBrush = QBrush(Qt::black);
82
0
    const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
83
0
    const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
84
0
    const QBrush buttonBrush = QBrush(button);
85
0
    const QBrush buttonBrushDark = QBrush(button.darker());
86
0
    const QBrush buttonBrushDark150 = QBrush(button.darker(150));
87
0
    const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
88
0
    pal.setColorGroup(QPalette::Active, foregroundBrush, buttonBrush, buttonBrushLight150,
89
0
                      buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
90
0
                      baseBrush, buttonBrush);
91
0
    pal.setColorGroup(QPalette::Inactive, foregroundBrush, buttonBrush, buttonBrushLight150,
92
0
                      buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
93
0
                      baseBrush, buttonBrush);
94
0
    pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
95
0
                      buttonBrushDark, buttonBrushDark150, buttonBrushDark,
96
0
                      whiteBrush, buttonBrush, buttonBrush);
97
98
0
    qt_placeholder_from_text(pal);
99
0
    qt_ensure_default_accent_color(pal);
100
0
}
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
*/
548
QPalette::QPalette()
549
0
    : d(nullptr)
550
0
{
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
0
    if (QGuiApplicationPrivate::app_pal) {
555
0
        d = QGuiApplicationPrivate::app_pal->d;
556
0
        d->ref.ref();
557
0
        setResolveMask(0);
558
0
    } else {
559
0
        init();
560
0
        qt_palette_from_color(*this, Qt::black);
561
0
        d->resolveMask = 0;
562
0
    }
563
0
}
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
*/
570
QPalette::QPalette(const QColor &button)
571
0
{
572
0
    init();
573
0
    qt_palette_from_color(*this, button);
574
0
}
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
*/
581
QPalette::QPalette(Qt::GlobalColor button)
582
0
{
583
0
    init();
584
0
    qt_palette_from_color(*this, button);
585
0
}
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
*/
594
QPalette::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
0
{
600
0
    init();
601
0
    setColorGroup(All, windowText, button, light, dark, mid, text, bright_text,
602
0
                  base, window);
603
604
0
    qt_placeholder_from_text(*this);
605
0
    qt_ensure_default_accent_color(*this);
606
0
}
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
*/
616
QPalette::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
0
{
620
0
    init();
621
0
    const QBrush windowBrush(window);
622
0
    const QBrush lightBrush(light);
623
0
    setColorGroup(All, QBrush(windowText), windowBrush, lightBrush,
624
0
                  QBrush(dark), QBrush(mid), QBrush(text), lightBrush,
625
0
                  QBrush(base), windowBrush);
626
0
}
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
*/
633
QPalette::QPalette(const QColor &button, const QColor &window)
634
0
{
635
0
    init();
636
0
    int h, s, v;
637
0
    window.getHsv(&h, &s, &v);
638
639
0
    const QBrush windowBrush = QBrush(window);
640
0
    const QBrush whiteBrush = QBrush(Qt::white);
641
0
    const QBrush blackBrush = QBrush(Qt::black);
642
0
    const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
643
0
    const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
644
0
    const QBrush disabledForeground = QBrush(Qt::darkGray);
645
646
0
    const QBrush buttonBrush = QBrush(button);
647
0
    const QBrush buttonBrushDark = QBrush(button.darker());
648
0
    const QBrush buttonBrushDark150 = QBrush(button.darker(150));
649
0
    const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
650
651
    //inactive and active are identical
652
0
    setColorGroup(Inactive, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
653
0
                  buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
654
0
                  windowBrush);
655
0
    setColorGroup(Active, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
656
0
                  buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
657
0
                  windowBrush);
658
0
    setColorGroup(Disabled, disabledForeground, buttonBrush, buttonBrushLight150,
659
0
                  buttonBrushDark, buttonBrushDark150, disabledForeground,
660
0
                  whiteBrush, baseBrush, windowBrush);
661
662
0
    qt_placeholder_from_text(*this);
663
0
    qt_ensure_default_accent_color(*this);
664
0
}
665
666
/*!
667
    Constructs a copy of \a p.
668
669
    This constructor is fast thanks to \l{implicit sharing}.
670
*/
671
QPalette::QPalette(const QPalette &p)
672
0
    : d(p.d), currentGroup(p.currentGroup)
673
0
{
674
0
    d->ref.ref();
675
0
}
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
*/
691
QPalette::~QPalette()
692
0
{
693
0
    if (d && !d->ref.deref())
694
0
        delete d;
695
0
}
696
697
/*!\internal*/
698
void QPalette::init()
699
0
{
700
0
    d = new QPalettePrivate;
701
0
}
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
*/
709
QPalette &QPalette::operator=(const QPalette &p)
710
0
{
711
0
    p.d->ref.ref();
712
0
    currentGroup = p.currentGroup;
713
0
    if (d && !d->ref.deref())
714
0
        delete d;
715
0
    d = p.d;
716
0
    return *this;
717
0
}
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
*/
728
QPalette::operator QVariant() const
729
0
{
730
0
    return QVariant::fromValue(*this);
731
0
}
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
*/
750
const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const
751
0
{
752
0
    Q_ASSERT(cr < NColorRoles);
753
0
    if (gr >= (int)NColorGroups) {
754
0
        if (gr == Current) {
755
0
            gr = currentGroup;
756
0
        } else {
757
0
            qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr);
758
0
            gr = Active;
759
0
        }
760
0
    }
761
0
    return d->data->br[gr][cr];
762
0
}
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
*/
782
void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
783
0
{
784
0
    Q_ASSERT(cr < NColorRoles);
785
786
0
    if (cg == All) {
787
0
        for (uint i = 0; i < NColorGroups; i++)
788
0
            setBrush(ColorGroup(i), cr, b);
789
0
        return;
790
0
    }
791
792
0
    if (cg == Current) {
793
0
        cg = currentGroup;
794
0
    } else if (cg >= NColorGroups) {
795
0
        qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg);
796
0
        cg = Active;
797
0
    }
798
799
0
    const auto newResolveMask = d->resolveMask | ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr);
800
0
    const auto valueChanged = d->data->br[cg][cr] != b;
801
802
0
    if (valueChanged) {
803
0
        detach();
804
0
        d->data.detach();
805
0
        d->data->br[cg][cr] = b;
806
0
    } else if (d->resolveMask != newResolveMask) {
807
0
        detach();
808
0
    }
809
810
0
    d->resolveMask = newResolveMask;
811
0
}
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
*/
827
bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
828
0
{
829
    // NoRole has no resolve mask and should never be set anyway
830
0
    if (cr == NoRole)
831
0
        return false;
832
833
0
    if (cg == Current)
834
0
        cg = currentGroup;
835
836
0
    if (cg >= NColorGroups) {
837
0
        qWarning() << "Wrong color group:" << cg;
838
0
        return false;
839
0
    }
840
841
0
    if (cr >= NColorRoles) {
842
0
        qWarning() << "Wrong color role:" << cr;
843
0
        return false;
844
0
    }
845
846
0
    return d->resolveMask & (ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr));
847
0
}
848
849
/*!
850
    \internal
851
*/
852
void QPalette::detach()
853
0
{
854
0
    if (d->ref.loadRelaxed() != 1) {
855
0
        QPalettePrivate *x = new QPalettePrivate(d->data);
856
0
        x->resolveMask = d->resolveMask;
857
0
        if (!d->ref.deref())
858
0
            delete d;
859
0
        d = x;
860
0
    } else {
861
0
        d->detach_no = ++QPalettePrivate::qt_palette_private_count;
862
0
    }
863
0
}
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
*/
889
bool QPalette::operator==(const QPalette &p) const
890
0
{
891
0
    if (isCopyOf(p) || d->data == p.d->data)
892
0
        return true;
893
0
    for(int grp = 0; grp < (int)NColorGroups; grp++) {
894
0
        for(int role = 0; role < (int)NColorRoles; role++) {
895
            // Dont't verify NoRole, because it has no resolve bit
896
0
            if (role == NoRole)
897
0
                continue;
898
0
            if (d->data->br[grp][role] != p.d->data->br[grp][role])
899
0
                return false;
900
0
        }
901
0
    }
902
0
    return true;
903
0
}
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
*/
911
bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) const
912
0
{
913
0
    if (group1 >= (int)NColorGroups) {
914
0
        if (group1 == Current) {
915
0
            group1 = currentGroup;
916
0
        } else {
917
0
            qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1);
918
0
            group1 = Active;
919
0
        }
920
0
    }
921
0
    if (group2 >= (int)NColorGroups) {
922
0
        if (group2 == Current) {
923
0
            group2 = currentGroup;
924
0
        } else {
925
0
            qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2);
926
0
            group2 = Active;
927
0
        }
928
0
    }
929
0
    if (group1 == group2)
930
0
        return true;
931
0
    for(int role = 0; role < (int)NColorRoles; role++) {
932
0
        if (d->data->br[group1][role] != d->data->br[group2][role])
933
0
                return false;
934
0
    }
935
0
    return true;
936
0
}
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
*/
945
qint64 QPalette::cacheKey() const
946
0
{
947
0
    return (((qint64) d->data->ser_no) << 32) | ((qint64) (d->detach_no));
948
0
}
949
950
static constexpr QPalette::ResolveMask allResolveMask()
951
0
{
952
0
    QPalette::ResolveMask mask = {0};
953
0
    for (int role = 0; role < int(QPalette::NColorRoles); ++role) {
954
0
        for (int grp = 0; grp < int(QPalette::NColorGroups); ++grp) {
955
0
            mask |= (QPalette::ResolveMask(1) << QPalettePrivate::bitPosition(QPalette::ColorGroup(grp), QPalette::ColorRole(role)));
956
0
        }
957
0
    }
958
0
    return mask;
959
0
}
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
*/
968
QPalette QPalette::resolve(const QPalette &other) const
969
0
{
970
0
    if ((*this == other && d->resolveMask == other.d->resolveMask)
971
0
        || d->resolveMask == 0) {
972
0
        QPalette o = other;
973
0
        o.setResolveMask(d->resolveMask);
974
0
        return o;
975
0
    }
976
977
0
    if (d->resolveMask == allResolveMask())
978
0
        return *this;
979
980
0
    QPalette palette(*this);
981
0
    palette.detach();
982
983
0
    for (int role = 0; role < int(NColorRoles); ++role) {
984
        // Don't resolve NoRole, its bits are needed for Accent (see bitPosition)
985
0
        if (role == NoRole)
986
0
            continue;
987
988
0
        for (int grp = 0; grp < int(NColorGroups); ++grp) {
989
0
            if (!(d->resolveMask & (ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(grp), ColorRole(role))))) {
990
0
                palette.d->data.detach();
991
0
                palette.d->data->br[grp][role] = other.d->data->br[grp][role];
992
0
            }
993
0
        }
994
0
    }
995
996
0
    palette.d->resolveMask |= other.d->resolveMask;
997
998
0
    return palette;
999
0
}
1000
1001
/*!
1002
    \internal
1003
*/
1004
QPalette::ResolveMask QPalette::resolveMask() const
1005
0
{
1006
0
    return d->resolveMask;
1007
0
}
1008
1009
/*!
1010
    \internal
1011
*/
1012
void QPalette::setResolveMask(QPalette::ResolveMask mask)
1013
0
{
1014
0
    if (mask == d->resolveMask)
1015
0
        return;
1016
1017
0
    detach();
1018
0
    d->resolveMask = mask;
1019
0
}
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
1035
static const int NumOldRoles = 7;
1036
static 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
1048
QDataStream &operator<<(QDataStream &s, const QPalette &p)
1049
0
{
1050
0
    for (int grp = 0; grp < (int)QPalette::NColorGroups; grp++) {
1051
0
        if (s.version() == 1) {
1052
            // Qt 1.x
1053
0
            for (int i = 0; i < NumOldRoles; ++i)
1054
0
                s << p.d->data->br[grp][oldRoles[i]].color();
1055
0
        } else {
1056
0
            int max = (int)QPalette::NColorRoles;
1057
0
            if (s.version() <= QDataStream::Qt_2_1)
1058
0
                max = QPalette::HighlightedText + 1;
1059
0
            else if (s.version() <= QDataStream::Qt_4_3)
1060
0
                max = QPalette::AlternateBase + 1;
1061
0
            else if (s.version() <= QDataStream::Qt_5_11)
1062
0
                max = QPalette::ToolTipText + 1;
1063
0
            else if (s.version() <= QDataStream::Qt_6_5)
1064
0
                max = QPalette::PlaceholderText + 1;
1065
1066
0
            for (int r = 0; r < max; r++)
1067
0
                s << p.d->data->br[grp][r];
1068
0
        }
1069
0
    }
1070
0
    return s;
1071
0
}
1072
1073
static void readV1ColorGroup(QDataStream &s, QPalette &pal, QPalette::ColorGroup grp)
1074
0
{
1075
0
    for (int i = 0; i < NumOldRoles; ++i) {
1076
0
        QColor col;
1077
0
        s >> col;
1078
0
        pal.setColor(grp, (QPalette::ColorRole)oldRoles[i], col);
1079
0
    }
1080
0
}
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
1091
QDataStream &operator>>(QDataStream &s, QPalette &p)
1092
0
{
1093
0
    if (s.version() == 1) {
1094
0
        p = QPalette();
1095
0
        readV1ColorGroup(s, p, QPalette::Active);
1096
0
        readV1ColorGroup(s, p, QPalette::Disabled);
1097
0
        readV1ColorGroup(s, p, QPalette::Inactive);
1098
0
    } else {
1099
0
        int max = QPalette::NColorRoles;
1100
0
        if (s.version() <= QDataStream::Qt_2_1) {
1101
0
            p = QPalette();
1102
0
            max = QPalette::HighlightedText + 1;
1103
0
        } else if (s.version() <= QDataStream::Qt_4_3) {
1104
0
            p = QPalette();
1105
0
            max = QPalette::AlternateBase + 1;
1106
0
        } else if (s.version() <= QDataStream::Qt_5_11) {
1107
0
            p = QPalette();
1108
0
            max = QPalette::ToolTipText + 1;
1109
0
        } else if (s.version() <= QDataStream::Qt_6_5) {
1110
0
            p = QPalette();
1111
0
            max = QPalette::PlaceholderText + 1;
1112
0
        }
1113
1114
1115
0
        QBrush tmp;
1116
0
        for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
1117
0
            const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(grp);
1118
0
            for(int role = 0; role < max; ++role) {
1119
0
                s >> tmp;
1120
0
                p.setBrush(group, (QPalette::ColorRole)role, tmp);
1121
0
            }
1122
1123
            // Accent defaults to Highlight for stream versions that don't have it.
1124
0
            if (s.version() < QDataStream::Qt_6_6)
1125
0
                p.setBrush(group, QPalette::Accent, p.brush(group, QPalette::Highlight));
1126
0
        }
1127
1128
0
    }
1129
0
    return s;
1130
0
}
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
1142
bool QPalette::isCopyOf(const QPalette &p) const
1143
0
{
1144
0
    return d == p.d;
1145
0
}
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
*/
1155
void 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
0
{
1160
0
    QBrush alt_base = QBrush(qt_mix_colors(base.color(), button.color()));
1161
0
    QBrush mid_light = QBrush(qt_mix_colors(button.color(), light.color()));
1162
0
    QColor toolTipBase(255, 255, 220);
1163
0
    QColor toolTipText(0, 0, 0);
1164
1165
0
    setColorGroup(cg, windowText, button, light, dark, mid, text, bright_text, base,
1166
0
                  alt_base, window, mid_light, text,
1167
0
                  QBrush(Qt::black), QBrush(Qt::darkBlue), QBrush(Qt::white),
1168
0
                  QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase),
1169
0
                  QBrush(toolTipText));
1170
1171
0
    for (int cr = Highlight; cr <= LinkVisited; ++cr) {
1172
0
        if (cg == All) {
1173
0
            for (int group = Active; group < NColorGroups; ++group) {
1174
0
                d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(group), ColorRole(cr)));
1175
0
            }
1176
0
        } else {
1177
0
            d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(cg), ColorRole(cr)));
1178
0
        }
1179
0
    }
1180
0
}
1181
1182
1183
/*!\internal*/
1184
void
1185
QPalette::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
0
{
1194
0
    setColorGroup(cg, foreground, button, light, dark, mid,
1195
0
                  text, bright_text, base, alternate_base, background,
1196
0
                  midlight, button_text, shadow, highlight, highlighted_text,
1197
0
                  link, link_visited, background, foreground);
1198
0
}
1199
1200
/*!\internal*/
1201
void 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
0
{
1211
0
    setBrush(cg, WindowText, foreground);
1212
0
    setBrush(cg, Button, button);
1213
0
    setBrush(cg, Light, light);
1214
0
    setBrush(cg, Dark, dark);
1215
0
    setBrush(cg, Mid, mid);
1216
0
    setBrush(cg, Text, text);
1217
0
    setBrush(cg, BrightText, bright_text);
1218
0
    setBrush(cg, Base, base);
1219
0
    setBrush(cg, AlternateBase, alternate_base);
1220
0
    setBrush(cg, Window, background);
1221
0
    setBrush(cg, Midlight, midlight);
1222
0
    setBrush(cg, ButtonText, button_text);
1223
0
    setBrush(cg, Shadow, shadow);
1224
0
    setBrush(cg, Highlight, highlight);
1225
0
    setBrush(cg, HighlightedText, highlighted_text);
1226
0
    setBrush(cg, Link, link);
1227
0
    setBrush(cg, LinkVisited, link_visited);
1228
0
    setBrush(cg, ToolTipBase, toolTipBase);
1229
0
    setBrush(cg, ToolTipText, toolTipText);
1230
0
}
1231
1232
#ifndef QT_NO_DEBUG_STREAM
1233
static QString groupsToString(const QPalette &p, QPalette::ColorRole cr)
1234
0
{
1235
0
    const auto groupEnum = QMetaEnum::fromType<QPalette::ColorGroup>();
1236
1237
0
    QString groupString;
1238
0
    for (int group = 0; group < QPalette::NColorGroups; ++group) {
1239
0
        const auto cg = QPalette::ColorGroup(group);
1240
1241
0
        if (p.isBrushSet(cg, cr)) {
1242
0
            const auto &color = p.color(cg, cr);
1243
0
            groupString += QString::fromUtf8(groupEnum.valueToKey(cg)) + u':' +
1244
0
                           color.name(QColor::HexArgb) + u',';
1245
0
        }
1246
0
    }
1247
0
    groupString.chop(1);
1248
1249
0
    return groupString;
1250
0
}
1251
1252
static QString rolesToString(const QPalette &p)
1253
0
{
1254
0
    const auto roleEnum = QMetaEnum::fromType<QPalette::ColorRole>();
1255
1256
0
    QString roleString;
1257
0
    for (int role = 0; role < QPalette::NColorRoles; ++role) {
1258
0
        const auto cr = QPalette::ColorRole(role);
1259
1260
0
        auto groupString = groupsToString(p, cr);
1261
0
        if (!groupString.isEmpty())
1262
0
            roleString += QString::fromUtf8(roleEnum.valueToKey(cr)) + QStringLiteral(":[") +
1263
0
                          groupString + QStringLiteral("],");
1264
0
    }
1265
0
    roleString.chop(1);
1266
1267
0
    return roleString;
1268
0
}
1269
1270
QDebug operator<<(QDebug dbg, const QPalette &p)
1271
0
{
1272
0
    QDebugStateSaver saver(dbg);
1273
0
    dbg.nospace();
1274
1275
0
    dbg << "QPalette(resolve=" << Qt::hex << Qt::showbase << p.resolveMask();
1276
1277
0
    auto roleString = rolesToString(p);
1278
0
    if (!roleString.isEmpty())
1279
0
        dbg << ',' << roleString;
1280
1281
0
    dbg << ')';
1282
1283
0
    return dbg;
1284
0
 }
1285
#endif
1286
1287
QT_END_NAMESPACE
1288
1289
#include "moc_qpalette.cpp"