Coverage Report

Created: 2026-02-10 07:39

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