Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqstylekittheme.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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 <QtQuickTemplates2/private/qquicktheme_p.h>
5#include <QtQuick/private/qquickpalette_p.h>
6#include <QtGui/private/qguiapplication_p.h>
7#include <QtGui/qpa/qplatformtheme.h>
8
11
13
14/*!
15 \qmltype Theme
16 \inqmlmodule Qt.labs.StyleKit
17 \inherits AbstractStyle
18 \brief Defines color and style overrides for a color scheme.
19
20 A Theme overrides properties defined in a \l Style to provide a
21 distinct visual appearance for a particular color scheme. A style
22 typically configures structural properties such as implicit size,
23 padding, and radii, while a theme specifies colors, shadows, and
24 other visual attributes. However, this is not a restriction — a
25 theme can override any property that a style can set.
26
27 A style can provide a \l {Style::light}{light} and a
28 \l {Style::dark}{dark} theme. When \l {Style::themeName}{themeName}
29 is set to \c "System" (the default), the active theme follows the
30 \l {QStyleHints::colorScheme}{operating system's color scheme}.
31 You can also create additional themes using \l CustomTheme and
32 \l {Style::themeName}{switch between them} at runtime.
33
34 Properties that are not set in the theme fall back to those defined
35 in the \l Style.
36
37 The following example defines light, dark, and high-contrast
38 themes, each providing different colors for the controls:
39
40 \snippet ThemeSnippets.qml themes
41
42 For a complete example showing themes in action, see the
43 \l {StyleKit Quick Controls Example}.
44
45 \labs
46
47 \sa Style, CustomTheme, {StyleKit Property Resolution}
48*/
49
50static QQuickTheme::Scope scopeForType(QQStyleKitExtendableControlType type)
51{
52 switch (type) {
53 case QQStyleKitReader::ControlType::AbstractButton:
54 case QQStyleKitReader::ControlType::Button:
55 case QQStyleKitReader::ControlType::DelayButton:
56 case QQStyleKitReader::ControlType::FlatButton:
57 case QQStyleKitReader::ControlType::RoundButton:
58 return QQuickTheme::Button;
59 case QQStyleKitReader::ControlType::CheckBox:
60 return QQuickTheme::CheckBox;
61 case QQStyleKitReader::ControlType::CheckDelegate:
62 case QQStyleKitReader::ControlType::RadioDelegate:
63 case QQStyleKitReader::ControlType::SwipeDelegate:
64 case QQStyleKitReader::ControlType::SwitchDelegate:
65 return QQuickTheme::ListView;
66 case QQStyleKitReader::ControlType::ComboBox:
67 return QQuickTheme::ComboBox;
68 case QQStyleKitReader::ControlType::GroupBox:
69 return QQuickTheme::GroupBox;
70 case QQStyleKitReader::ControlType::ItemDelegate:
71 return QQuickTheme::ItemView;
72 case QQStyleKitReader::ControlType::Label:
73 return QQuickTheme::Label;
74 case QQStyleKitReader::ControlType::MenuBar:
75 case QQStyleKitReader::ControlType::MenuBarItem:
76 return QQuickTheme::MenuBar;
77 case QQStyleKitReader::ControlType::Menu:
78 case QQStyleKitReader::ControlType::MenuItem:
79 case QQStyleKitReader::ControlType::MenuSeparator:
80 return QQuickTheme::Menu;
81 case QQStyleKitReader::ControlType::RadioButton:
82 return QQuickTheme::RadioButton;
83 case QQStyleKitReader::ControlType::SpinBox:
84 return QQuickTheme::SpinBox;
85 case QQStyleKitReader::ControlType::SwitchControl:
86 return QQuickTheme::Switch;
87 case QQStyleKitReader::ControlType::TabBar:
88 case QQStyleKitReader::ControlType::TabButton:
89 return QQuickTheme::TabBar;
90 case QQStyleKitReader::ControlType::TextArea:
91 return QQuickTheme::TextArea;
92 case QQStyleKitReader::ControlType::TextInput:
93 case QQStyleKitReader::ControlType::TextField:
94 return QQuickTheme::TextField;
95 case QQStyleKitReader::ControlType::ToolBar:
96 case QQStyleKitReader::ControlType::ToolButton:
97 case QQStyleKitReader::ControlType::ToolSeparator:
98 return QQuickTheme::ToolBar;
99 default:
100 return QQuickTheme::System;
101 }
102 Q_UNREACHABLE();
103}
104
105QQStyleKitTheme::QQStyleKitTheme(QObject *parent)
107{
108}
109
110QQStyleKitStyle *QQStyleKitTheme::style() const
111{
112 QObject *parentObj = parent();
113 if (!parentObj)
114 return nullptr;
115 Q_ASSERT(qobject_cast<QQStyleKitStyle *>(parentObj));
116 return static_cast<QQStyleKitStyle *>(parentObj);
117}
118
119QPalette QQStyleKitTheme::paletteForControlType(QQStyleKitExtendableControlType type) const
120{
121 const QQuickTheme::Scope scope = scopeForType(type);
122 return m_effectivePalettes[int(scope)];
123}
124
125QFont QQStyleKitTheme::fontForControlType(QQStyleKitExtendableControlType type) const
126{
127 const QQuickTheme::Scope scope = scopeForType(type);
128 return m_effectiveFonts[int(scope)];
129}
130
131void QQStyleKitTheme::updateThemePalettes()
132{
133 const QQStyleKitPalette *pals = palettes();
134 if (!pals)
135 return;
136
137 // Collect palette fallback chain
138 QVector<const QQStyleKitPalette *> fbChain;
139 for (auto *fb = pals; fb; fb = fb->fallbackPalette())
140 fbChain.append(fb);
141
142 auto resolveFromPaletteChain = [&](QQuickTheme::Scope scope,
143 QQuickPalette* (QQStyleKitPalette::*getter)() const) -> QPalette
144 {
145 QPalette result;
146
147 // Apply from farthest fallback -> local
148 for (int i = fbChain.size() - 1; i >= 0; --i) {
149 const QQStyleKitPalette *fb = fbChain[i];
150 // Apply system palette first as a base, and override with scope-specific palette
151 if (scope != QQuickTheme::System && fb->isSet(QQuickTheme::System)) {
152 if (auto *sys = fb->system())
153 result = sys->toQPalette().resolve(result);
154 }
155 if (fb->isSet(scope)) {
156 if (auto *p = (fb->*getter)())
157 result = p->toQPalette().resolve(result);
158 }
159 }
160
161 return result;
162 };
163
164 auto setResolved = [&](QQuickPalette* (QQStyleKitPalette::*getter)() const,
165 QQuickTheme::Scope scope)
166 {
167 m_effectivePalettes[int(scope)] = resolveFromPaletteChain(scope, getter);
168 };
169
170 setResolved(&QQStyleKitPalette::system, QQuickTheme::System);
171 setResolved(&QQStyleKitPalette::button, QQuickTheme::Button);
172 setResolved(&QQStyleKitPalette::checkBox, QQuickTheme::CheckBox);
173 setResolved(&QQStyleKitPalette::comboBox, QQuickTheme::ComboBox);
174 setResolved(&QQStyleKitPalette::groupBox, QQuickTheme::GroupBox);
175 setResolved(&QQStyleKitPalette::itemDelegate, QQuickTheme::ItemView);
176 setResolved(&QQStyleKitPalette::label, QQuickTheme::Label);
177 setResolved(&QQStyleKitPalette::radioButton, QQuickTheme::RadioButton);
178 setResolved(&QQStyleKitPalette::spinBox, QQuickTheme::SpinBox);
179 setResolved(&QQStyleKitPalette::tabBar, QQuickTheme::TabBar);
180 setResolved(&QQStyleKitPalette::textArea, QQuickTheme::TextArea);
181 setResolved(&QQStyleKitPalette::textField, QQuickTheme::TextField);
182 setResolved(&QQStyleKitPalette::toolBar, QQuickTheme::ToolBar);
183}
184
185void QQStyleKitTheme::updateThemeFonts()
186{
187 const QQStyleKitFont *fonts = this->fonts();
188 if (!fonts)
189 return;
190
191 // Collect font fallback chain
192 QVector<const QQStyleKitFont *> fbChain;
193 for (auto *fb = fonts; fb; fb = fb->fallbackFont())
194 fbChain.append(fb);
195
196 auto resolveFromFontChain = [&](QQuickTheme::Scope scope) -> QFont
197 {
198 QFont result;
199
200 // Apply from farthest fallback -> local
201 for (int i = fbChain.size() - 1; i >= 0; --i) {
202 const QQStyleKitFont *fb = fbChain[i];
203 // Apply system font first as a base, and override with scope-specific font
204 if (scope != QQuickTheme::System && fb->isSet(QQuickTheme::System)) {
205 result = fb->fontForScope(QQuickTheme::System).resolve(result);
206 }
207 if (fb->isSet(scope)) {
208 result = fb->fontForScope(scope).resolve(result);
209 }
210 }
211
212 return result;
213 };
214
215 for (int i = 0; i < NScopes; ++i) {
216 const QQuickTheme::Scope scope = static_cast<QQuickTheme::Scope>(i);
217 m_effectiveFonts[i] = resolveFromFontChain(scope);
218 }
219}
220
222{
224 m_completed = true;
225}
226
227QT_END_NAMESPACE
228
229#include "moc_qqstylekittheme_p.cpp"
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QQuickPalette * groupBox() const
QQuickPalette * checkBox() const
QQuickPalette * toolBar() const
QQuickPalette * textField() const
QQuickPalette * spinBox() const
QQuickPalette * system() const
QQuickPalette * comboBox() const
QQuickPalette * itemDelegate() const
QQuickPalette * button() const
QQuickPalette * radioButton() const
QQuickPalette * textArea() const
QQuickPalette * tabBar() const
QQuickPalette * label() const
QQStyleKitPalette * palettes()
QQStyleKitFont * fonts()
QQStyleKitStyle * style() const
QFont fontForControlType(QQStyleKitExtendableControlType type) const
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QPalette paletteForControlType(QQStyleKitExtendableControlType type) const
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE QQuickTheme::Scope scopeForType(QQStyleKitExtendableControlType type)
\qmltype Theme \inqmlmodule Qt.labs.StyleKit \inherits AbstractStyle