Coverage Report

Created: 2026-04-29 07:00

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
1.11M
{
25
1.11M
    return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
26
1.11M
                  (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
27
1.11M
}
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
139k
{
41
139k
    if (alpha < 0 or alpha > 100)
42
0
        return;
43
44
559k
    for (int cg = 0; cg < int(QPalette::NColorGroups); ++cg) {
45
419k
        const QPalette::ColorGroup group = QPalette::ColorGroup(cg);
46
47
        // skip if the brush has been set already
48
419k
        if (!pal.isBrushSet(group, QPalette::PlaceholderText)) {
49
419k
            QColor c = pal.color(group, QPalette::Text);
50
419k
            const int a = (c.alpha() * alpha) / 100;
51
419k
            c.setAlpha(a);
52
419k
            pal.setColor(group, QPalette::PlaceholderText, c);
53
419k
        }
54
419k
    }
55
139k
}
56
57
static void qt_ensure_default_accent_color(QPalette &pal)
58
139k
{
59
    // have a lighter/darker factor handy, depending on dark/light heuristics
60
139k
    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
559k
    for (int i = 0; i < QPalette::NColorGroups; ++i) {
64
419k
        const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(i);
65
419k
        if (!pal.isBrushSet(group, QPalette::Accent)) {
66
            // Default to highlight if available, otherwise use a shade of base
67
419k
            const QBrush accentBrush = pal.isBrushSet(group, QPalette::Highlight)
68
419k
                                     ? pal.brush(group, QPalette::Highlight)
69
419k
                                     : pal.brush(group, QPalette::Base).color().lighter(lighter);
70
419k
            pal.setBrush(group, QPalette::Accent, accentBrush);
71
419k
        }
72
419k
    }
73
139k
}
74
75
static void qt_palette_from_color(QPalette &pal, const QColor &button)
76
139k
{
77
139k
    int h, s, v;
78
139k
    button.getHsv(&h, &s, &v);
79
    // inactive and active are the same..
80
139k
    const QBrush whiteBrush = QBrush(Qt::white);
81
139k
    const QBrush blackBrush = QBrush(Qt::black);
82
139k
    const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
83
139k
    const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
84
139k
    const QBrush buttonBrush = QBrush(button);
85
139k
    const QBrush buttonBrushDark = QBrush(button.darker());
86
139k
    const QBrush buttonBrushDark150 = QBrush(button.darker(150));
87
139k
    const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
88
139k
    pal.setColorGroup(QPalette::Active, foregroundBrush, buttonBrush, buttonBrushLight150,
89
139k
                      buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
90
139k
                      baseBrush, buttonBrush);
91
139k
    pal.setColorGroup(QPalette::Inactive, foregroundBrush, buttonBrush, buttonBrushLight150,
92
139k
                      buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
93
139k
                      baseBrush, buttonBrush);
94
139k
    pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
95
139k
                      buttonBrushDark, buttonBrushDark150, buttonBrushDark,
96
139k
                      whiteBrush, buttonBrush, buttonBrush);
97
98
139k
    qt_placeholder_from_text(pal);
99
139k
    qt_ensure_default_accent_color(pal);
100
139k
}
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
157k
    : d(nullptr)
550
157k
{
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
157k
    if (QGuiApplicationPrivate::app_pal) {
555
17.9k
        d = QGuiApplicationPrivate::app_pal->d;
556
17.9k
        d->ref.ref();
557
17.9k
        setResolveMask(0);
558
139k
    } else {
559
139k
        init();
560
139k
        qt_palette_from_color(*this, Qt::black);
561
139k
        d->resolveMask = 0;
562
139k
    }
563
157k
}
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
139k
{
620
139k
    init();
621
139k
    const QBrush windowBrush(window);
622
139k
    const QBrush lightBrush(light);
623
139k
    setColorGroup(All, QBrush(windowText), windowBrush, lightBrush,
624
139k
                  QBrush(dark), QBrush(mid), QBrush(text), lightBrush,
625
139k
                  QBrush(base), windowBrush);
626
139k
}
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
689k
    : d(p.d), currentGroup(p.currentGroup)
673
689k
{
674
689k
    d->ref.ref();
675
689k
}
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
987k
{
693
987k
    if (d && !d->ref.deref())
694
419k
        delete d;
695
987k
}
696
697
/*!\internal*/
698
void QPalette::init()
699
279k
{
700
279k
    d = new QPalettePrivate;
701
279k
}
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
1.17M
{
752
1.17M
    Q_ASSERT(cr < NColorRoles);
753
1.17M
    if (gr >= (int)NColorGroups) {
754
335k
        if (gr == Current) {
755
335k
            gr = currentGroup;
756
335k
        } else {
757
0
            qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr);
758
0
            gr = Active;
759
0
        }
760
335k
    }
761
1.17M
    return d->data->br[gr][cr];
762
1.17M
}
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
23.9M
{
784
23.9M
    Q_ASSERT(cr < NColorRoles);
785
786
23.9M
    if (cg == All) {
787
13.4M
        for (uint i = 0; i < NColorGroups; i++)
788
10.0M
            setBrush(ColorGroup(i), cr, b);
789
3.35M
        return;
790
3.35M
    }
791
792
20.5M
    if (cg == Current) {
793
0
        cg = currentGroup;
794
20.5M
    } else if (cg >= NColorGroups) {
795
0
        qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg);
796
0
        cg = Active;
797
0
    }
798
799
20.5M
    const auto newResolveMask = d->resolveMask | ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr);
800
20.5M
    const auto valueChanged = d->data->br[cg][cr] != b;
801
802
20.5M
    if (valueChanged) {
803
19.7M
        detach();
804
19.7M
        d->data.detach();
805
19.7M
        d->data->br[cg][cr] = b;
806
19.7M
    } else if (d->resolveMask != newResolveMask) {
807
419k
        detach();
808
419k
    }
809
810
20.5M
    d->resolveMask = newResolveMask;
811
20.5M
}
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
1.25M
{
829
    // NoRole has no resolve mask and should never be set anyway
830
1.25M
    if (cr == NoRole)
831
0
        return false;
832
833
1.25M
    if (cg == Current)
834
0
        cg = currentGroup;
835
836
1.25M
    if (cg >= NColorGroups) {
837
0
        qWarning() << "Wrong color group:" << cg;
838
0
        return false;
839
0
    }
840
841
1.25M
    if (cr >= NColorRoles) {
842
0
        qWarning() << "Wrong color role:" << cr;
843
0
        return false;
844
0
    }
845
846
1.25M
    return d->resolveMask & (ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr));
847
1.25M
}
848
849
/*!
850
    \internal
851
*/
852
void QPalette::detach()
853
20.2M
{
854
20.2M
    if (d->ref.loadRelaxed() != 1) {
855
139k
        QPalettePrivate *x = new QPalettePrivate(d->data);
856
139k
        x->resolveMask = d->resolveMask;
857
139k
        if (!d->ref.deref())
858
0
            delete d;
859
139k
        d = x;
860
20.1M
    } else {
861
20.1M
        d->detach_no = ++QPalettePrivate::qt_palette_private_count;
862
20.1M
    }
863
20.2M
}
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
139k
{
891
139k
    if (isCopyOf(p) || d->data == p.d->data)
892
0
        return true;
893
139k
    for(int grp = 0; grp < (int)NColorGroups; grp++) {
894
139k
        for(int role = 0; role < (int)NColorRoles; role++) {
895
            // Dont't verify NoRole, because it has no resolve bit
896
139k
            if (role == NoRole)
897
0
                continue;
898
139k
            if (d->data->br[grp][role] != p.d->data->br[grp][role])
899
139k
                return false;
900
139k
        }
901
139k
    }
902
0
    return true;
903
139k
}
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
139k
{
970
139k
    if ((*this == other && d->resolveMask == other.d->resolveMask)
971
139k
        || d->resolveMask == 0) {
972
139k
        QPalette o = other;
973
139k
        o.setResolveMask(d->resolveMask);
974
139k
        return o;
975
139k
    }
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
139k
{
1006
139k
    return d->resolveMask;
1007
139k
}
1008
1009
/*!
1010
    \internal
1011
*/
1012
void QPalette::setResolveMask(QPalette::ResolveMask mask)
1013
297k
{
1014
297k
    if (mask == d->resolveMask)
1015
157k
        return;
1016
1017
139k
    detach();
1018
139k
    d->resolveMask = mask;
1019
139k
}
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
139k
{
1144
139k
    return d == p.d;
1145
139k
}
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
559k
{
1160
559k
    QBrush alt_base = QBrush(qt_mix_colors(base.color(), button.color()));
1161
559k
    QBrush mid_light = QBrush(qt_mix_colors(button.color(), light.color()));
1162
559k
    QColor toolTipBase(255, 255, 220);
1163
559k
    QColor toolTipText(0, 0, 0);
1164
1165
559k
    setColorGroup(cg, windowText, button, light, dark, mid, text, bright_text, base,
1166
559k
                  alt_base, window, mid_light, text,
1167
559k
                  QBrush(Qt::black), QBrush(Qt::darkBlue), QBrush(Qt::white),
1168
559k
                  QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase),
1169
559k
                  QBrush(toolTipText));
1170
1171
2.79M
    for (int cr = Highlight; cr <= LinkVisited; ++cr) {
1172
2.23M
        if (cg == All) {
1173
2.23M
            for (int group = Active; group < NColorGroups; ++group) {
1174
1.67M
                d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(group), ColorRole(cr)));
1175
1.67M
            }
1176
1.67M
        } else {
1177
1.67M
            d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(cg), ColorRole(cr)));
1178
1.67M
        }
1179
2.23M
    }
1180
559k
}
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
559k
{
1211
559k
    setBrush(cg, WindowText, foreground);
1212
559k
    setBrush(cg, Button, button);
1213
559k
    setBrush(cg, Light, light);
1214
559k
    setBrush(cg, Dark, dark);
1215
559k
    setBrush(cg, Mid, mid);
1216
559k
    setBrush(cg, Text, text);
1217
559k
    setBrush(cg, BrightText, bright_text);
1218
559k
    setBrush(cg, Base, base);
1219
559k
    setBrush(cg, AlternateBase, alternate_base);
1220
559k
    setBrush(cg, Window, background);
1221
559k
    setBrush(cg, Midlight, midlight);
1222
559k
    setBrush(cg, ButtonText, button_text);
1223
559k
    setBrush(cg, Shadow, shadow);
1224
559k
    setBrush(cg, Highlight, highlight);
1225
559k
    setBrush(cg, HighlightedText, highlighted_text);
1226
559k
    setBrush(cg, Link, link);
1227
559k
    setBrush(cg, LinkVisited, link_visited);
1228
559k
    setBrush(cg, ToolTipBase, toolTipBase);
1229
559k
    setBrush(cg, ToolTipText, toolTipText);
1230
559k
}
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"