1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qpalette.h"
41 #include "qguiapplication.h"
42 #include "qguiapplication_p.h"
43 #include "qdatastream.h"
44 #include "qvariant.h"
45 #include "qdebug.h"
46
47 QT_BEGIN_NAMESPACE
48
49 static int qt_palette_count = 1;
50
51 class QPalettePrivate {
52 public:
QPalettePrivate()53 QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { }
54 QAtomicInt ref;
55 QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
56 int ser_no;
57 int detach_no;
58 };
59
qt_mix_colors(QColor a,QColor b)60 static QColor qt_mix_colors(QColor a, QColor b)
61 {
62 return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
63 (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
64 }
65
qt_palette_from_color(QPalette & pal,const QColor & button)66 static void qt_palette_from_color(QPalette &pal, const QColor &button)
67 {
68 int h, s, v;
69 button.getHsv(&h, &s, &v);
70 // inactive and active are the same..
71 const QBrush whiteBrush = QBrush(Qt::white);
72 const QBrush blackBrush = QBrush(Qt::black);
73 const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
74 const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
75 const QBrush buttonBrush = QBrush(button);
76 const QBrush buttonBrushDark = QBrush(button.darker());
77 const QBrush buttonBrushDark150 = QBrush(button.darker(150));
78 const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
79 pal.setColorGroup(QPalette::Active, foregroundBrush, buttonBrush, buttonBrushLight150,
80 buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
81 baseBrush, buttonBrush);
82 pal.setColorGroup(QPalette::Inactive, foregroundBrush, buttonBrush, buttonBrushLight150,
83 buttonBrushDark, buttonBrushDark150, foregroundBrush, whiteBrush,
84 baseBrush, buttonBrush);
85 pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
86 buttonBrushDark, buttonBrushDark150, buttonBrushDark,
87 whiteBrush, buttonBrush, buttonBrush);
88 }
89
90 /*!
91 \fn QPalette &QPalette::operator=(QPalette &&other)
92
93 Move-assigns \a other to this QPalette instance.
94
95 \since 5.2
96 */
97
98 /*!
99 \fn const QColor &QPalette::color(ColorRole role) const
100
101 \overload
102
103 Returns the color that has been set for the given color \a role in
104 the current ColorGroup.
105
106 \sa brush(), ColorRole
107 */
108
109 /*!
110 \fn const QBrush &QPalette::brush(ColorRole role) const
111
112 \overload
113
114 Returns the brush that has been set for the given color \a role in
115 the current ColorGroup.
116
117 \sa color(), setBrush(), ColorRole
118 */
119
120 /*!
121 \fn void QPalette::setColor(ColorRole role, const QColor &color)
122
123 \overload
124
125 Sets the color used for the given color \a role, in all color
126 groups, to the specified solid \a color.
127
128 \sa brush(), setColor(), ColorRole
129 */
130
131 /*!
132 \fn void QPalette::setBrush(ColorRole role, const QBrush &brush)
133
134 Sets the brush for the given color \a role to the specified \a
135 brush for all groups in the palette.
136
137 \sa brush(), setColor(), ColorRole
138 */
139
140 /*!
141 \fn const QBrush & QPalette::foreground() const
142 \obsolete
143
144 Use windowText() instead.
145 */
146
147 /*!
148 \fn const QBrush & QPalette::windowText() const
149
150 Returns the window text (general foreground) brush of the
151 current color group.
152
153 \sa ColorRole, brush()
154 */
155
156 /*!
157 \fn const QBrush & QPalette::button() const
158
159 Returns the button brush of the current color group.
160
161 \sa ColorRole, brush()
162 */
163
164 /*!
165 \fn const QBrush & QPalette::light() const
166
167 Returns the light brush of the current color group.
168
169 \sa ColorRole, brush()
170 */
171
172 /*!
173 \fn const QBrush& QPalette::midlight() const
174
175 Returns the midlight brush of the current color group.
176
177 \sa ColorRole, brush()
178 */
179
180 /*!
181 \fn const QBrush & QPalette::dark() const
182
183 Returns the dark brush of the current color group.
184
185 \sa ColorRole, brush()
186 */
187
188 /*!
189 \fn const QBrush & QPalette::mid() const
190
191 Returns the mid brush of the current color group.
192
193 \sa ColorRole, brush()
194 */
195
196 /*!
197 \fn const QBrush & QPalette::text() const
198
199 Returns the text foreground brush of the current color group.
200
201 \sa ColorRole, brush()
202 */
203
204 /*!
205 \fn const QBrush & QPalette::brightText() const
206
207 Returns the bright text foreground brush of the current color group.
208
209 \sa ColorRole, brush()
210 */
211
212 /*!
213 \fn const QBrush & QPalette::buttonText() const
214
215 Returns the button text foreground brush of the current color group.
216
217 \sa ColorRole, brush()
218 */
219
220 /*!
221 \fn const QBrush & QPalette::base() const
222
223 Returns the base brush of the current color group.
224
225 \sa ColorRole, brush()
226 */
227
228 /*!
229 \fn const QBrush & QPalette::alternateBase() const
230
231 Returns the alternate base brush of the current color group.
232
233 \sa ColorRole, brush()
234 */
235
236 /*!
237 \fn const QBrush & QPalette::toolTipBase() const
238 \since 4.4
239
240 Returns the tool tip base brush of the current color group. This brush is
241 used by QToolTip and QWhatsThis.
242
243 \note Tool tips use the Inactive color group of QPalette, because tool
244 tips are not active windows.
245
246 \sa ColorRole, brush()
247 */
248
249 /*!
250 \fn const QBrush & QPalette::toolTipText() const
251 \since 4.4
252
253 Returns the tool tip text brush of the current color group. This brush is
254 used by QToolTip and QWhatsThis.
255
256 \note Tool tips use the Inactive color group of QPalette, because tool
257 tips are not active windows.
258
259 \sa ColorRole, brush()
260 */
261
262 /*!
263 \fn const QBrush & QPalette::background() const
264 \obsolete
265
266 Use window() instead.
267 */
268
269 /*!
270 \fn const QBrush & QPalette::window() const
271
272 Returns the window (general background) brush of the current
273 color group.
274
275 \sa ColorRole, brush()
276 */
277
278 /*!
279 \fn const QBrush & QPalette::shadow() const
280
281 Returns the shadow brush of the current color group.
282
283 \sa ColorRole, brush()
284 */
285
286 /*!
287 \fn const QBrush & QPalette::highlight() const
288
289 Returns the highlight brush of the current color group.
290
291 \sa ColorRole, brush()
292 */
293
294 /*!
295 \fn const QBrush & QPalette::highlightedText() const
296
297 Returns the highlighted text brush of the current color group.
298
299 \sa ColorRole, brush()
300 */
301
302 /*!
303 \fn const QBrush & QPalette::link() const
304
305 Returns the unvisited link text brush of the current color group.
306
307 \sa ColorRole, brush()
308 */
309
310 /*!
311 \fn const QBrush & QPalette::linkVisited() const
312
313 Returns the visited link text brush of the current color group.
314
315 \sa ColorRole, brush()
316 */
317
318 /*!
319 \fn const QBrush & QPalette::placeholderText() const
320 \since 5.12
321
322 Returns the placeholder text brush of the current color group.
323
324 \note Before Qt 5.12, the placeholder text color was hard-coded in the code as
325 QPalette::text().color() where an alpha of 128 was applied.
326 We continue to support this behavior by default, unless you set your own brush.
327 One can get back the original placeholder color setting the special QBrush default
328 constructor as placeholder brush.
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 Background This value is obsolete. Use Window instead.
438
439 \value WindowText A general foreground color.
440
441 \value Foreground This value is obsolete. Use WindowText instead.
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 HighlightedText A text color that contrasts with \c Highlight.
510 By default, the highlighted text color is Qt::white.
511
512 There are two color roles related to hyperlinks:
513
514 \value Link A text color used for unvisited hyperlinks.
515 By default, the link color is Qt::blue.
516
517 \value LinkVisited A text color used for already visited hyperlinks.
518 By default, the linkvisited color is Qt::magenta.
519
520 Note that we do not use the \c Link and \c LinkVisited roles when
521 rendering rich text in Qt, and that we recommend that you use CSS
522 and the QTextDocument::setDefaultStyleSheet() function to alter
523 the appearance of links. For example:
524
525 \snippet textdocument-css/main.cpp 0
526
527 \value NoRole No role; this special role is often used to indicate that a
528 role has not been assigned.
529
530 \omitvalue NColorRoles
531 */
532
533 /*!
534 Constructs a palette object that uses the application's default palette.
535
536 \sa QApplication::setPalette(), QApplication::palette()
537 */
QPalette()538 QPalette::QPalette()
539 : d(nullptr)
540 {
541 data.current_group = Active;
542 data.resolve_mask = 0;
543 // Initialize to application palette if present, else default to black.
544 // This makes it possible to instantiate QPalette outside QGuiApplication,
545 // for example in the platform plugins.
546 if (QGuiApplicationPrivate::app_pal) {
547 d = QGuiApplicationPrivate::app_pal->d;
548 d->ref.ref();
549 } else {
550 init();
551 qt_palette_from_color(*this, Qt::black);
552 data.resolve_mask = 0;
553 }
554 }
555
556 /*!
557 Constructs a palette from the \a button color. The other colors are
558 automatically calculated, based on this color. \c Window will be
559 the button color as well.
560 */
QPalette(const QColor & button)561 QPalette::QPalette(const QColor &button)
562 {
563 init();
564 qt_palette_from_color(*this, button);
565 }
566
567 /*!
568 Constructs a palette from the \a button color. The other colors are
569 automatically calculated, based on this color. \c Window will be
570 the button color as well.
571 */
QPalette(Qt::GlobalColor button)572 QPalette::QPalette(Qt::GlobalColor button)
573 {
574 init();
575 qt_palette_from_color(*this, button);
576 }
577
578 /*!
579 Constructs a palette. You can pass either brushes, pixmaps or
580 plain colors for \a windowText, \a button, \a light, \a dark, \a
581 mid, \a text, \a bright_text, \a base and \a window.
582
583 \sa QBrush
584 */
QPalette(const QBrush & windowText,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & window)585 QPalette::QPalette(const QBrush &windowText, const QBrush &button,
586 const QBrush &light, const QBrush &dark,
587 const QBrush &mid, const QBrush &text,
588 const QBrush &bright_text, const QBrush &base,
589 const QBrush &window)
590 {
591 init();
592 setColorGroup(All, windowText, button, light, dark, mid, text, bright_text,
593 base, window);
594 }
595
596
597 /*!\obsolete
598
599 Constructs a palette with the specified \a windowText, \a
600 window, \a light, \a dark, \a mid, \a text, and \a base colors.
601 The button color will be set to the window color.
602 */
QPalette(const QColor & windowText,const QColor & window,const QColor & light,const QColor & dark,const QColor & mid,const QColor & text,const QColor & base)603 QPalette::QPalette(const QColor &windowText, const QColor &window,
604 const QColor &light, const QColor &dark, const QColor &mid,
605 const QColor &text, const QColor &base)
606 {
607 init();
608 const QBrush windowBrush(window);
609 const QBrush lightBrush(light);
610 setColorGroup(All, QBrush(windowText), windowBrush, lightBrush,
611 QBrush(dark), QBrush(mid), QBrush(text), lightBrush,
612 QBrush(base), windowBrush);
613 }
614
615 /*!
616 Constructs a palette from a \a button color and a \a window.
617 The other colors are automatically calculated, based on these
618 colors.
619 */
QPalette(const QColor & button,const QColor & window)620 QPalette::QPalette(const QColor &button, const QColor &window)
621 {
622 init();
623 int h, s, v;
624 window.getHsv(&h, &s, &v);
625
626 const QBrush windowBrush = QBrush(window);
627 const QBrush whiteBrush = QBrush(Qt::white);
628 const QBrush blackBrush = QBrush(Qt::black);
629 const QBrush baseBrush = v > 128 ? whiteBrush : blackBrush;
630 const QBrush foregroundBrush = v > 128 ? blackBrush : whiteBrush;
631 const QBrush disabledForeground = QBrush(Qt::darkGray);
632
633 const QBrush buttonBrush = QBrush(button);
634 const QBrush buttonBrushDark = QBrush(button.darker());
635 const QBrush buttonBrushDark150 = QBrush(button.darker(150));
636 const QBrush buttonBrushLight150 = QBrush(button.lighter(150));
637
638 //inactive and active are identical
639 setColorGroup(Inactive, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
640 buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
641 windowBrush);
642 setColorGroup(Active, foregroundBrush, buttonBrush, buttonBrushLight150, buttonBrushDark,
643 buttonBrushDark150, foregroundBrush, whiteBrush, baseBrush,
644 windowBrush);
645 setColorGroup(Disabled, disabledForeground, buttonBrush, buttonBrushLight150,
646 buttonBrushDark, buttonBrushDark150, disabledForeground,
647 whiteBrush, baseBrush, windowBrush);
648 }
649
650 /*!
651 Constructs a copy of \a p.
652
653 This constructor is fast thanks to \l{implicit sharing}.
654 */
QPalette(const QPalette & p)655 QPalette::QPalette(const QPalette &p)
656 : d(p.d), data(p.data)
657 {
658 d->ref.ref();
659 }
660
661 /*!
662 \fn QPalette::QPalette(QPalette &&other)
663 \since 5.4
664
665 Move-constructs a QPalette instance, making it point at the same
666 object that \a other was pointing to.
667
668 After being moved from, you can only assign to or destroy \a other.
669 Any other operation will result in undefined behavior.
670 */
671
672 /*!
673 Destroys the palette.
674 */
~QPalette()675 QPalette::~QPalette()
676 {
677 if (d && !d->ref.deref())
678 delete d;
679 }
680
681 /*!\internal*/
init()682 void QPalette::init() {
683 d = new QPalettePrivate;
684 data.resolve_mask = 0;
685 data.current_group = Active; //as a default..
686 }
687
688 /*!
689 Assigns \a p to this palette and returns a reference to this
690 palette.
691
692 This operation is fast thanks to \l{implicit sharing}.
693 */
operator =(const QPalette & p)694 QPalette &QPalette::operator=(const QPalette &p)
695 {
696 p.d->ref.ref();
697 data = p.data;
698 if (d && !d->ref.deref())
699 delete d;
700 d = p.d;
701 return *this;
702 }
703
704 /*!
705 \fn void QPalette::swap(QPalette &other)
706 \since 5.0
707
708 Swaps this palette instance with \a other. This function is very
709 fast and never fails.
710 */
711
712 /*!
713 Returns the palette as a QVariant
714 */
operator QVariant() const715 QPalette::operator QVariant() const
716 {
717 return QVariant(QMetaType::QPalette, this);
718 }
719
720 /*!
721 \fn const QColor &QPalette::color(ColorGroup group, ColorRole role) const
722
723 Returns the color in the specified color \a group, used for the
724 given color \a role.
725
726 \sa brush(), setColor(), ColorRole
727 */
728
729 /*!
730 \fn const QBrush &QPalette::brush(ColorGroup group, ColorRole role) const
731
732 Returns the brush in the specified color \a group, used for the
733 given color \a role.
734
735 \sa color(), setBrush(), ColorRole
736 */
brush(ColorGroup gr,ColorRole cr) const737 const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const
738 {
739 Q_ASSERT(cr < NColorRoles);
740 if(gr >= (int)NColorGroups) {
741 if(gr == Current) {
742 gr = (ColorGroup)data.current_group;
743 } else {
744 qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr);
745 gr = Active;
746 }
747 }
748 return d->br[gr][cr];
749 }
750
751 /*!
752 \fn void QPalette::setColor(ColorGroup group, ColorRole role, const QColor &color)
753
754 Sets the color in the specified color \a group, used for the given
755 color \a role, to the specified solid \a color.
756
757 \sa setBrush(), color(), ColorRole
758 */
759
760 /*!
761 \fn void QPalette::setBrush(ColorGroup group, ColorRole role, const QBrush &brush)
762 \overload
763
764 Sets the brush in the specified color \a group, used for the given
765 color \a role, to \a brush.
766
767 \sa brush(), setColor(), ColorRole
768 */
setBrush(ColorGroup cg,ColorRole cr,const QBrush & b)769 void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
770 {
771 Q_ASSERT(cr < NColorRoles);
772
773 if (cg == All) {
774 for (uint i = 0; i < NColorGroups; i++)
775 setBrush(ColorGroup(i), cr, b);
776 return;
777 }
778
779 if (cg == Current) {
780 cg = ColorGroup(data.current_group);
781 } else if (cg >= NColorGroups) {
782 qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg);
783 cg = Active;
784 }
785
786 // For placeholder we want to continue to respect the original behavior, which is
787 // derivating the text color, but only if user has not yet set his own brush.
788 // We then use Qt::NoBrush as an inernal way to know if the brush is customized or not.
789
790 // ### Qt 6 - remove this special case
791 // Part 1 - Restore initial color to the given color group
792 if (cr == PlaceholderText && b == QBrush()) {
793 QColor col = brush(Text).color();
794 col.setAlpha(128);
795 setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
796 return;
797 }
798
799 if (d->br[cg][cr] != b) {
800 detach();
801 d->br[cg][cr] = b;
802 }
803 data.resolve_mask |= (1<<cr);
804
805 // ### Qt 6 - remove this special case
806 // Part 2 - Update initial color to the given color group
807 if (cr == Text && d->br[cg][PlaceholderText].style() == Qt::NoBrush) {
808 QColor col = brush(Text).color();
809 col.setAlpha(128);
810 setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
811 }
812 }
813
814 /*!
815 \since 4.2
816
817 Returns \c true if the ColorGroup \a cg and ColorRole \a cr has been
818 set previously on this palette; otherwise returns \c false.
819
820 \sa setBrush()
821 */
isBrushSet(ColorGroup cg,ColorRole cr) const822 bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
823 {
824 Q_UNUSED(cg);
825 return (data.resolve_mask & (1<<cr));
826 }
827
828 /*!
829 \internal
830 */
detach()831 void QPalette::detach()
832 {
833 if (d->ref.loadRelaxed() != 1) {
834 QPalettePrivate *x = new QPalettePrivate;
835 for(int grp = 0; grp < (int)NColorGroups; grp++) {
836 for(int role = 0; role < (int)NColorRoles; role++)
837 x->br[grp][role] = d->br[grp][role];
838 }
839 if(!d->ref.deref())
840 delete d;
841 d = x;
842 }
843 ++d->detach_no;
844 }
845
846 /*!
847 \fn bool QPalette::operator!=(const QPalette &p) const
848
849 Returns \c true (slowly) if this palette is different from \a p;
850 otherwise returns \c false (usually quickly).
851
852 \note The current ColorGroup is not taken into account when
853 comparing palettes
854
855 \sa operator==()
856 */
857
858 /*!
859 Returns \c true (usually quickly) if this palette is equal to \a p;
860 otherwise returns \c false (slowly).
861
862 \note The current ColorGroup is not taken into account when
863 comparing palettes
864
865 \sa operator!=()
866 */
operator ==(const QPalette & p) const867 bool QPalette::operator==(const QPalette &p) const
868 {
869 if (isCopyOf(p))
870 return true;
871 for(int grp = 0; grp < (int)NColorGroups; grp++) {
872 for(int role = 0; role < (int)NColorRoles; role++) {
873 if(d->br[grp][role] != p.d->br[grp][role])
874 return false;
875 }
876 }
877 return true;
878 }
879
880 /*!
881 \fn bool QPalette::isEqual(ColorGroup cg1, ColorGroup cg2) const
882
883 Returns \c true (usually quickly) if color group \a cg1 is equal to
884 \a cg2; otherwise returns \c false.
885 */
isEqual(QPalette::ColorGroup group1,QPalette::ColorGroup group2) const886 bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) const
887 {
888 if(group1 >= (int)NColorGroups) {
889 if(group1 == Current) {
890 group1 = (ColorGroup)data.current_group;
891 } else {
892 qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1);
893 group1 = Active;
894 }
895 }
896 if(group2 >= (int)NColorGroups) {
897 if(group2 == Current) {
898 group2 = (ColorGroup)data.current_group;
899 } else {
900 qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2);
901 group2 = Active;
902 }
903 }
904 if(group1 == group2)
905 return true;
906 for(int role = 0; role < (int)NColorRoles; role++) {
907 if(d->br[group1][role] != d->br[group2][role])
908 return false;
909 }
910 return true;
911 }
912
913 /*! \fn int QPalette::serialNumber() const
914 \obsolete
915
916 Returns a number that identifies the contents of this QPalette
917 object. Distinct QPalette objects can only have the same serial
918 number if they refer to the same contents (but they don't have
919 to). Also, the serial number of a QPalette may change during the
920 lifetime of the object.
921
922 Use cacheKey() instead.
923
924 \warning The serial number doesn't necessarily change when the
925 palette is altered. This means that it may be dangerous to use it
926 as a cache key.
927
928 \sa operator==()
929 */
930
931 /*!
932 Returns a number that identifies the contents of this QPalette
933 object. Distinct QPalette objects can have the same key if
934 they refer to the same contents.
935
936 The cacheKey() will change when the palette is altered.
937 */
cacheKey() const938 qint64 QPalette::cacheKey() const
939 {
940 return (((qint64) d->ser_no) << 32) | ((qint64) (d->detach_no));
941 }
942
943 /*!
944 Returns a new QPalette that is a union of this instance and \a other.
945 Color roles set in this instance take precedence.
946 */
resolve(const QPalette & other) const947 QPalette QPalette::resolve(const QPalette &other) const
948 {
949 if ((*this == other && data.resolve_mask == other.data.resolve_mask)
950 || data.resolve_mask == 0) {
951 QPalette o = other;
952 o.data.resolve_mask = data.resolve_mask;
953 return o;
954 }
955
956 QPalette palette(*this);
957 palette.detach();
958
959 for(int role = 0; role < (int)NColorRoles; role++)
960 if (!(data.resolve_mask & (1<<role)))
961 for(int grp = 0; grp < (int)NColorGroups; grp++)
962 palette.d->br[grp][role] = other.d->br[grp][role];
963 palette.data.resolve_mask |= other.data.resolve_mask;
964
965 return palette;
966 }
967
968 /*!
969 \fn uint QPalette::resolve() const
970 \internal
971 */
972
973 /*!
974 \fn void QPalette::resolve(uint mask)
975 \internal
976 */
977
978
979 /*****************************************************************************
980 QPalette stream functions
981 *****************************************************************************/
982
983 #ifndef QT_NO_DATASTREAM
984
985 static const int NumOldRoles = 7;
986 static const int oldRoles[7] = { QPalette::WindowText, QPalette::Window, QPalette::Light,
987 QPalette::Dark, QPalette::Mid, QPalette::Text, QPalette::Base };
988
989 /*!
990 \relates QPalette
991
992 Writes the palette, \a p to the stream \a s and returns a
993 reference to the stream.
994
995 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
996 */
997
operator <<(QDataStream & s,const QPalette & p)998 QDataStream &operator<<(QDataStream &s, const QPalette &p)
999 {
1000 for (int grp = 0; grp < (int)QPalette::NColorGroups; grp++) {
1001 if (s.version() == 1) {
1002 // Qt 1.x
1003 for (int i = 0; i < NumOldRoles; ++i)
1004 s << p.d->br[grp][oldRoles[i]].color();
1005 } else {
1006 int max = (int)QPalette::NColorRoles;
1007 if (s.version() <= QDataStream::Qt_2_1)
1008 max = QPalette::HighlightedText + 1;
1009 else if (s.version() <= QDataStream::Qt_4_3)
1010 max = QPalette::AlternateBase + 1;
1011 else if (s.version() <= QDataStream::Qt_5_11)
1012 max = QPalette::ToolTipText + 1;
1013 for (int r = 0; r < max; r++)
1014 s << p.d->br[grp][r];
1015 }
1016 }
1017 return s;
1018 }
1019
readV1ColorGroup(QDataStream & s,QPalette & pal,QPalette::ColorGroup grp)1020 static void readV1ColorGroup(QDataStream &s, QPalette &pal, QPalette::ColorGroup grp)
1021 {
1022 for (int i = 0; i < NumOldRoles; ++i) {
1023 QColor col;
1024 s >> col;
1025 pal.setColor(grp, (QPalette::ColorRole)oldRoles[i], col);
1026 }
1027 }
1028
1029 /*!
1030 \relates QPalette
1031
1032 Reads a palette from the stream, \a s into the palette \a p, and
1033 returns a reference to the stream.
1034
1035 \sa{Serializing Qt Data Types}{Format of the QDataStream operators}
1036 */
1037
operator >>(QDataStream & s,QPalette & p)1038 QDataStream &operator>>(QDataStream &s, QPalette &p)
1039 {
1040 if(s.version() == 1) {
1041 p = QPalette();
1042 readV1ColorGroup(s, p, QPalette::Active);
1043 readV1ColorGroup(s, p, QPalette::Disabled);
1044 readV1ColorGroup(s, p, QPalette::Inactive);
1045 } else {
1046 int max = QPalette::NColorRoles;
1047 if (s.version() <= QDataStream::Qt_2_1) {
1048 p = QPalette();
1049 max = QPalette::HighlightedText + 1;
1050 } else if (s.version() <= QDataStream::Qt_4_3) {
1051 p = QPalette();
1052 max = QPalette::AlternateBase + 1;
1053 } else if (s.version() <= QDataStream::Qt_5_11) {
1054 p = QPalette();
1055 max = QPalette::ToolTipText + 1;
1056 }
1057
1058 QBrush tmp;
1059 for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
1060 for(int role = 0; role < max; ++role) {
1061 s >> tmp;
1062 p.setBrush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role, tmp);
1063 }
1064 }
1065 }
1066 return s;
1067 }
1068 #endif //QT_NO_DATASTREAM
1069
1070 /*!
1071 Returns \c true if this palette and \a p are copies of each other,
1072 i.e. one of them was created as a copy of the other and neither
1073 was subsequently modified; otherwise returns \c false. This is much
1074 stricter than equality.
1075
1076 \sa operator=(), operator==()
1077 */
1078
isCopyOf(const QPalette & p) const1079 bool QPalette::isCopyOf(const QPalette &p) const
1080 {
1081 return d == p.d;
1082 }
1083
1084 /*!
1085
1086 Sets a the group at \a cg. You can pass either brushes, pixmaps or
1087 plain colors for \a windowText, \a button, \a light, \a dark, \a
1088 mid, \a text, \a bright_text, \a base and \a window.
1089
1090 \sa QBrush
1091 */
setColorGroup(ColorGroup cg,const QBrush & windowText,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & window)1092 void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBrush &button,
1093 const QBrush &light, const QBrush &dark, const QBrush &mid,
1094 const QBrush &text, const QBrush &bright_text, const QBrush &base,
1095 const QBrush &window)
1096 {
1097 QBrush alt_base = QBrush(qt_mix_colors(base.color(), button.color()));
1098 QBrush mid_light = QBrush(qt_mix_colors(button.color(), light.color()));
1099 QColor toolTipBase(255, 255, 220);
1100 QColor toolTipText(0, 0, 0);
1101
1102 setColorGroup(cg, windowText, button, light, dark, mid, text, bright_text, base,
1103 alt_base, window, mid_light, text,
1104 QBrush(Qt::black), QBrush(Qt::darkBlue), QBrush(Qt::white),
1105 QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase),
1106 QBrush(toolTipText));
1107
1108 data.resolve_mask &= ~(1 << Highlight);
1109 data.resolve_mask &= ~(1 << HighlightedText);
1110 data.resolve_mask &= ~(1 << LinkVisited);
1111 data.resolve_mask &= ~(1 << Link);
1112 }
1113
1114
1115 /*!\internal*/
1116 void
setColorGroup(ColorGroup cg,const QBrush & foreground,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & alternate_base,const QBrush & background,const QBrush & midlight,const QBrush & button_text,const QBrush & shadow,const QBrush & highlight,const QBrush & highlighted_text,const QBrush & link,const QBrush & link_visited)1117 QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
1118 const QBrush &light, const QBrush &dark, const QBrush &mid,
1119 const QBrush &text, const QBrush &bright_text,
1120 const QBrush &base, const QBrush &alternate_base,
1121 const QBrush &background, const QBrush &midlight,
1122 const QBrush &button_text, const QBrush &shadow,
1123 const QBrush &highlight, const QBrush &highlighted_text,
1124 const QBrush &link, const QBrush &link_visited)
1125 {
1126 setColorGroup(cg, foreground, button, light, dark, mid,
1127 text, bright_text, base, alternate_base, background,
1128 midlight, button_text, shadow, highlight, highlighted_text,
1129 link, link_visited, background, foreground);
1130 }
1131
1132 /*!\internal*/
setColorGroup(ColorGroup cg,const QBrush & foreground,const QBrush & button,const QBrush & light,const QBrush & dark,const QBrush & mid,const QBrush & text,const QBrush & bright_text,const QBrush & base,const QBrush & alternate_base,const QBrush & background,const QBrush & midlight,const QBrush & button_text,const QBrush & shadow,const QBrush & highlight,const QBrush & highlighted_text,const QBrush & link,const QBrush & link_visited,const QBrush & toolTipBase,const QBrush & toolTipText)1133 void QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBrush &button,
1134 const QBrush &light, const QBrush &dark, const QBrush &mid,
1135 const QBrush &text, const QBrush &bright_text,
1136 const QBrush &base, const QBrush &alternate_base,
1137 const QBrush &background, const QBrush &midlight,
1138 const QBrush &button_text, const QBrush &shadow,
1139 const QBrush &highlight, const QBrush &highlighted_text,
1140 const QBrush &link, const QBrush &link_visited,
1141 const QBrush &toolTipBase, const QBrush &toolTipText)
1142 {
1143 setBrush(cg, WindowText, foreground);
1144 setBrush(cg, Button, button);
1145 setBrush(cg, Light, light);
1146 setBrush(cg, Dark, dark);
1147 setBrush(cg, Mid, mid);
1148 setBrush(cg, Text, text);
1149 setBrush(cg, BrightText, bright_text);
1150 setBrush(cg, Base, base);
1151 setBrush(cg, AlternateBase, alternate_base);
1152 setBrush(cg, Window, background);
1153 setBrush(cg, Midlight, midlight);
1154 setBrush(cg, ButtonText, button_text);
1155 setBrush(cg, Shadow, shadow);
1156 setBrush(cg, Highlight, highlight);
1157 setBrush(cg, HighlightedText, highlighted_text);
1158 setBrush(cg, Link, link);
1159 setBrush(cg, LinkVisited, link_visited);
1160 setBrush(cg, ToolTipBase, toolTipBase);
1161 setBrush(cg, ToolTipText, toolTipText);
1162 }
1163
qt_fusionPalette()1164 Q_GUI_EXPORT QPalette qt_fusionPalette()
1165 {
1166 QColor backGround(239, 239, 239);
1167 QColor light = backGround.lighter(150);
1168 QColor mid(backGround.darker(130));
1169 QColor midLight = mid.lighter(110);
1170 QColor base = Qt::white;
1171 QColor disabledBase(backGround);
1172 QColor dark = backGround.darker(150);
1173 QColor darkDisabled = QColor(209, 209, 209).darker(110);
1174 QColor text = Qt::black;
1175 QColor hightlightedText = Qt::white;
1176 QColor disabledText = QColor(190, 190, 190);
1177 QColor button = backGround;
1178 QColor shadow = dark.darker(135);
1179 QColor disabledShadow = shadow.lighter(150);
1180
1181 QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base);
1182 fusionPalette.setBrush(QPalette::Midlight, midLight);
1183 fusionPalette.setBrush(QPalette::Button, button);
1184 fusionPalette.setBrush(QPalette::Shadow, shadow);
1185 fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText);
1186
1187 fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);
1188 fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);
1189 fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);
1190 fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);
1191 fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);
1192 fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);
1193
1194 fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198));
1195 fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198));
1196 fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145));
1197 return fusionPalette;
1198 }
1199
1200 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QPalette & p)1201 QDebug operator<<(QDebug dbg, const QPalette &p)
1202 {
1203 const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"};
1204 const char *colorRoleNames[] =
1205 {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text",
1206 "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight",
1207 "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole",
1208 "ToolTipBase","ToolTipText", "PlaceholderText" };
1209 QDebugStateSaver saver(dbg);
1210 QDebug nospace = dbg.nospace();
1211 const uint mask = p.resolve();
1212 nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ',';
1213 for (int role = 0; role < (int)QPalette::NColorRoles; ++role) {
1214 if (mask & (1<<role)) {
1215 if (role)
1216 nospace << ',';
1217 nospace << colorRoleNames[role] << ":[";
1218 for (int group = 0; group < (int)QPalette::NColorGroups; ++group) {
1219 if (group)
1220 nospace << ',';
1221 const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group),
1222 static_cast<QPalette::ColorRole>(role)).rgba();
1223 nospace << colorGroupNames[group] << ':' << color;
1224 }
1225 nospace << ']';
1226 }
1227 }
1228 nospace << ')' << Qt::noshowbase << Qt::dec;
1229 return dbg;
1230 }
1231 #endif
1232
1233 QT_END_NAMESPACE
1234