1// Copyright (C) 2020 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 "qquickpalette_p.h"
5
6#include <QtQuick/private/qquickpalettecolorprovider_p.h>
7
8QT_BEGIN_NAMESPACE
9
10static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
11{
12 // use a switch to enable "unhandled enum" warnings:
13 switch (cg) {
14 case QPalette::Active:
15 case QPalette::Disabled:
16 case QPalette::Inactive:
17 return true;
18 case QPalette::NColorGroups:
19 case QPalette::Current:
20 case QPalette::All:
21 return false;
22 }
23
24 // GCC 8.x does not tread __builtin_unreachable() as constexpr
25#if defined(Q_CC_INTEL) || defined(Q_CC_CLANG) || (defined(Q_CC_GNU) && Q_CC_GNU >= 900)
26 // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
27 Q_UNREACHABLE();
28#endif
29 return false;
30}
31
32/*!
33 \internal
34
35 \class QQuickPalette
36 \brief Contains color groups for each QML item state.
37 \inmodule QtQuick
38 \since 6.0
39
40 This class is the wrapper around QPalette.
41
42 \sa QQuickColorGroup, QQuickAbstractPaletteProvider, QPalette
43 */
44
45/*!
46 \qmltype Palette
47 \instantiates QQuickPalette
48 \inherits QQuickColorGroup
49 \inqmlmodule QtQuick
50 \ingroup qtquick-visual
51 \brief Contains color groups for each QML item state.
52
53 A palette consists of three color groups: \c active, \c disabled, and \c inactive.
54 The \c active color group is the default group: its colors are used for other groups
55 if colors of these groups aren't explicitly specified.
56
57 In the following example, color is applied for all color groups:
58 \code
59 ApplicationWindow {
60 palette.buttonText: "salmon"
61
62 ColumnLayout {
63 Button {
64 text: qsTr("Disabled button")
65 enabled: false
66 }
67
68 Button {
69 text: qsTr("Enabled button")
70 }
71 }
72 }
73 \endcode
74 It means that text color will be the same for both buttons.
75
76 In the following example, colors will be different for enabled and disabled states:
77 \code
78 ApplicationWindow {
79 palette.buttonText: "salmon"
80 palette.disabled.buttonText: "lavender"
81
82 ColumnLayout {
83 Button {
84 text: qsTr("Disabled button")
85 enabled: false
86 }
87
88 Button {
89 text: qsTr("Enabled button")
90 }
91 }
92 }
93 \endcode
94
95 It is also possible to specify colors like this:
96
97 \snippet qtquickcontrols-custom-palette-buttons.qml palette
98
99 This approach is especially convenient when you need to specify a whole
100 palette with all color groups; but as with the other cases above, the
101 colors that are not specified are initialized from SystemPalette, or
102 potentially the \l {Styling Qt Quick Controls}{Qt Quick Controls style},
103 if one is in use.
104
105 \note Some Controls styles use some palette colors, but many styles use
106 independent colors.
107
108 \sa Window::palette, Item::palette, Popup::palette, SystemPalette
109*/
110
111/*!
112 \qmlproperty ColorGroup QtQuick::Palette::active
113
114 The Active group is used for windows that are in focus.
115
116 \sa QPalette::Active
117*/
118
119/*!
120 \qmlproperty ColorGroup QtQuick::Palette::inactive
121
122 The Inactive group is used for windows that have no keyboard focus.
123
124 \sa QPalette::Inactive
125*/
126
127/*!
128 \qmlproperty ColorGroup QtQuick::Palette::disabled
129
130 The Disabled group is used for elements that are disabled for some reason.
131
132 \sa QPalette::Disabled
133*/
134
135QQuickPalette::QQuickPalette(QObject *parent)
136 : QQuickColorGroup(parent)
137 , m_currentGroup(defaultCurrentGroup())
138{
139}
140
141QQuickColorGroup *QQuickPalette::active() const
142{
143 return colorGroup(groupTag: QPalette::Active);
144}
145
146QQuickColorGroup *QQuickPalette::inactive() const
147{
148 return colorGroup(groupTag: QPalette::Inactive);
149}
150
151QQuickColorGroup *QQuickPalette::disabled() const
152{
153 return colorGroup(groupTag: QPalette::Disabled);
154}
155
156/*!
157 \internal
158
159 Returns the palette's current color group.
160 The default value is Active.
161 */
162QPalette::ColorGroup QQuickPalette::currentColorGroup() const
163{
164 return m_currentGroup;
165}
166
167/*!
168 \internal
169
170 Sets \a currentGroup for this palette.
171
172 The current color group is used when accessing colors of this palette.
173 For example, if color group is Disabled, color accessors will be
174 returning colors form the respective group.
175 \code
176 QQuickPalette palette;
177
178 palette.setAlternateBase(Qt::green);
179 palette.disabled()->setAlternateBase(Qt::red);
180
181 auto color = palette.alternateBase(); // Qt::green
182
183 palette.setCurrentGroup(QPalette::Disabled);
184 color = palette.alternateBase(); // Qt::red
185 \endcode
186
187 Emits QColorGroup::changed().
188 */
189void QQuickPalette::setCurrentGroup(QPalette::ColorGroup currentGroup)
190{
191 if (m_currentGroup != currentGroup) {
192 m_currentGroup = currentGroup;
193 Q_EMIT changed();
194 }
195}
196
197void QQuickPalette::fromQPalette(QPalette palette)
198{
199 if (colorProvider().fromQPalette(p: std::move(palette))) {
200 Q_EMIT changed();
201 }
202}
203
204QPalette QQuickPalette::toQPalette() const
205{
206 return colorProvider().palette();
207}
208
209const QQuickAbstractPaletteProvider *QQuickPalette::paletteProvider() const
210{
211 return colorProvider().paletteProvider();
212}
213
214void QQuickPalette::setPaletteProvider(const QQuickAbstractPaletteProvider *paletteProvider)
215{
216 colorProvider().setPaletteProvider(paletteProvider);
217}
218
219void QQuickPalette::reset()
220{
221 if (colorProvider().reset()) {
222 Q_EMIT changed();
223 }
224}
225
226void QQuickPalette::inheritPalette(const QPalette &palette)
227{
228 if (colorProvider().inheritPalette(palette)) {
229 Q_EMIT changed();
230 }
231}
232
233void QQuickPalette::setActive(QQuickColorGroup *active)
234{
235 setColorGroup(groupTag: QPalette::Active, group: active, notifier: &QQuickPalette::activeChanged);
236}
237
238void QQuickPalette::setInactive(QQuickColorGroup *inactive)
239{
240 setColorGroup(groupTag: QPalette::Inactive, group: inactive, notifier: &QQuickPalette::inactiveChanged);
241}
242
243void QQuickPalette::setDisabled(QQuickColorGroup *disabled)
244{
245 setColorGroup(groupTag: QPalette::Disabled, group: disabled, notifier: &QQuickPalette::disabledChanged);
246}
247
248
249void QQuickPalette::setColorGroup(QPalette::ColorGroup groupTag,
250 const QQuickColorGroup::GroupPtr &group,
251 void (QQuickPalette::*notifier)())
252{
253 if (isValidColorGroup(groupTag, colorGroup: group)) {
254 if (colorProvider().copyColorGroup(cg: groupTag, p: group->colorProvider())) {
255 Q_EMIT (this->*notifier)();
256 Q_EMIT changed();
257 }
258 }
259}
260
261QQuickColorGroup::GroupPtr QQuickPalette::colorGroup(QPalette::ColorGroup groupTag) const
262{
263 if (auto group = findColorGroup(groupTag)) {
264 return group;
265 }
266
267 auto group = QQuickColorGroup::createWithParent(parent&: *const_cast<QQuickPalette*>(this));
268 const_cast<QQuickPalette*>(this)->registerColorGroup(group, groupTag);
269 return group;
270}
271
272QQuickColorGroup::GroupPtr QQuickPalette::findColorGroup(QPalette::ColorGroup groupTag) const
273{
274 Q_ASSERT(is_valid(groupTag));
275 return m_colorGroups[groupTag];
276}
277
278void QQuickPalette::registerColorGroup(QQuickColorGroup *group, QPalette::ColorGroup groupTag)
279{
280 Q_ASSERT(is_valid(groupTag));
281 auto &g = m_colorGroups[groupTag];
282 if (g) {
283 Q_ASSERT(g != group);
284 g->deleteLater();
285 }
286 g = group;
287
288 group->setGroupTag(groupTag);
289
290 QQuickColorGroup::connect(sender: group, signal: &QQuickColorGroup::changed, context: this, slot: &QQuickPalette::changed);
291}
292
293bool QQuickPalette::isValidColorGroup(QPalette::ColorGroup groupTag,
294 const QQuickColorGroup::GroupPtr &colorGroup) const
295{
296 if (!colorGroup) {
297 qWarning(msg: "Color group cannot be null.");
298 return false;
299 }
300
301 if (!colorGroup->parent()) {
302 qWarning(msg: "Color group should have a parent.");
303 return false;
304 }
305
306 if (colorGroup->parent() && !qobject_cast<QQuickPalette*>(object: colorGroup->parent())) {
307 qWarning(msg: "Color group should be a part of QQuickPalette.");
308 return false;
309 }
310
311 if (groupTag == defaultGroupTag()) {
312 qWarning(msg: "Register %i color group is not allowed."
313 " QQuickPalette is %i color group itself.", groupTag, groupTag);
314 return false;
315 }
316
317 if (findColorGroup(groupTag) == colorGroup) {
318 qWarning(msg: "The color group is already a part of the current palette.");
319 return false;
320 }
321
322 return true;
323}
324
325QT_END_NAMESPACE
326
327#include "moc_qquickpalette_p.cpp"
328

source code of qtdeclarative/src/quick/items/qquickpalette.cpp