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
qqstylekitvariation.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
5
7
8/*!
9 \qmltype StyleVariation
10 \inqmlmodule Qt.labs.StyleKit
11 \inherits AbstractStylableControls
12 \brief Defines alternative styling for specific controls.
13
14
15 A StyleVariation lets you define alternative styling that can be applied
16 to specific controls in the application (\e{instance variations}),
17 or to all descendants of a particular parent control type
18 (\e{type variations}). For example, you can give controls in a sidebar a
19 compact appearance, or make buttons inside all \l {ToolBar}{toolbars} look
20 different from buttons elsewhere.
21
22 \section2 Instance Variations
23
24 Instance variations are activated by setting the \l {StyleVariation::}{variations}
25 attached property on any item in the application — all StyleKit controls that are
26 children or descendants of that item will receive the alternative styling. Variations
27 can also be set at multiple levels of the hierarchy simultaneously; when they conflict,
28 the variation closest to the control takes precedence.
29
30 Instance variations are defined in the \l Style or \l Theme that they affect:
31
32 \snippet InstanceVariationSnippets.qml instance variations in style
33
34 And they are applied from the application using the
35 \l {StyleVariation::}{variations} attached property:
36
37 \snippet InstanceVariationSnippets.qml apply instance variation
38
39 Variation names referred to from the application that are not defined in the active
40 style (or theme) are silently ignored — they act as hints that the style author can
41 choose to implement or leave unhandled.
42
43 \section2 Type Variations
44
45 Type variations are assigned to the \l {ControlStyle::}{variations} property of a
46 specific \l ControlStyle, without requiring a \l name. Unlike instance variations —
47 which require the application to explicitly opt in — type variations are applied
48 automatically to all controls of a given type whenever they are descendants of the
49 specified parent control type.
50
51 The following snippet shows how to make all \l {Button}{Buttons} inside a \l Frame look
52 distinct from buttons elsewhere:
53
54 \snippet TypeVariationSnippets.qml frame with variation
55
56 Because \l {AbstractStylableControls::}{groupBox} falls back to
57 \l {AbstractStylableControls::}{frame} in the style hierarchy, type variations
58 set on \c frame are automatically inherited by \c groupBox as well. To opt out,
59 reset the variations for the subtype.
60
61 \section2 Propagation order
62
63 A StyleVariation is local to the \l Style or \l Theme where it is defined. A Theme
64 cannot shadow an entire StyleVariation defined in the Style — only individual
65 properties within it can be overridden, just like any other style property.
66
67 For example, if both the \l Style and the active \l Theme define \c {frame.variations},
68 both type variation arrays take effect for a \l Frame. The resolution order for
69 individual properties is: the Theme's variation properties take precedence over the
70 Theme's direct properties, which take precedence over the Style's variation properties,
71 which take precedence over the Style's direct properties.
72
73 The same applies to instance variations. A StyleVariation defined in a \l Theme takes
74 precedence over the Theme's direct properties. If a StyleVariation with the same
75 \l name is also defined in the \l Style, both take effect, following the same
76 resolution order as described above.
77
78 In the following snippet, a button with \c {StyleVariation.variations: ["alert"]}
79 will be red in the light theme and cyan in the dark theme, with a 4-pixel border in
80 both. Because the dark theme overrides \c {button.background.radius} to be \c 6,
81 that property takes precedence over the \c {background.radius} set in the Style's
82 variation. As a result, the button's radius ends up being \c 6 in the dark theme, but \c 0
83 in the light theme:
84
85 \snippet VariationPropagation.qml propagation
86
87 \labs
88
89 \sa Style, Theme, {ControlStyle::variations}{ControlStyle.variations},
90 {StyleVariation::variations}{StyleVariation.variations}
91*/
92
93/*!
94 \qmlproperty string StyleVariation::name
95
96 The name of this variation.
97
98 The name identifies this variation when used as an
99 \l {Instance Variations}{instance variation}.
100
101 \sa {StyleVariation::variations}{variations} {Instance Variations}
102*/
103
104/*!
105 \qmlattachedproperty list<string> StyleVariation::variations
106
107 This property holds the list of \l{StyleVariation}{instance variations}
108 to activate for a \l Control, and its descendant controls.
109
110 If multiple variations in the list sets the same property, the first
111 one in the list takes precedence.
112
113 If variations are set on both a parent item and a descendant control, both
114 sets apply, with the control's own variations taking precedence
115 over those inherited from the parent.
116
117 \snippet InstanceVariationSnippets.qml apply instance variation
118
119 \sa name
120*/
121
122/*!
123 \qmlattachedproperty int StyleVariation::controlType
124
125 This property identifies the \l {StyleReader::controlType}{control type} of
126 the item it is attached to.
127
128 StyleKit uses it to resolve \l {Type Variations}{type variations} for descendant
129 controls — if a parent item's \c controlType matches a control type that has
130 \l {ControlStyle::}{variations} defined in the \l Style, those variations apply
131 to all descendant controls.
132
133 Built-in controls set this property automatically. Custom controls
134 must set it explicitly to participate in type variation resolution.
135
136 \sa {ControlStyle::variations}{ControlStyle.variations},
137 {StyleReader::controlType}{StyleReader.controlType}
138*/
139
140int QQStyleKitVariation::s_typeVariationCount = 0;
141int QQStyleKitVariationAttached::s_instanceVariationCount = 0;
142
143QQStyleKitVariation::QQStyleKitVariation(QObject *parent)
144 : QQStyleKitControls(parent)
145{
146 /* As an optimization, keep track of how many type variations that are defined
147 * inside the style. That way we can skip looking for them later if s_typeVariationCount == 0. */
148 ++s_typeVariationCount;
149}
150
151QQStyleKitVariationAttached *QQStyleKitVariation::qmlAttachedProperties(QObject *object)
152{
153 return new QQStyleKitVariationAttached(object);
154}
155
157{
158 return m_name;
159}
160
161void QQStyleKitVariation::setName(const QString &name)
162{
163 if (m_name == name)
164 return;
165
166 m_name = name;
167 emit nameChanged();
168}
169
170QQStyleKitVariationAttached::QQStyleKitVariationAttached(QObject *parent)
171 : QObject(parent)
172{
173}
174
176{
177 return m_variations;
178}
179
180void QQStyleKitVariationAttached::setVariations(const QStringList &variations)
181{
182 if (m_variations == variations)
183 return;
184
185 /* As an optimization, we count the number of instance variations set from the application.
186 * That way, if s_instanceVariationCount == 1, for example, and we found a variation while
187 * resolving the effective variations for a specific QQStyleReader, we can stop the search. */
188 s_instanceVariationCount++;
189
190 m_variations = variations;
191 emit variationsChanged();
192}
193
198
199void QQStyleKitVariationAttached::setControlType(QQStyleKitExtendableControlType type)
200{
201 if (m_controlType == type)
202 return;
203
204 m_controlType = type;
205 emit controlTypeChanged();
206}
207
208QT_END_NAMESPACE
209
210#include "moc_qqstylekitvariation_p.cpp"
void setControlType(QQStyleKitExtendableControlType type)
QQStyleKitExtendableControlType controlType() const
void setVariations(const QStringList &variations)
void setName(const QString &name)
Combined button and popup list for selecting options.