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
qqstylekitpropertypath_p.h
Go to the documentation of this file.
1// Copyright (C) 2026 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// Qt-Security score:significant reason:default
4
5#ifndef QQSTYLEKITPROPERTYPATH_P_H
6#define QQSTYLEKITPROPERTYPATH_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
20
21/* Each style property in StyleKit needs a unique PropertyStorageId that can be used as
22 * a key in the map that stores its value. To compute such an ID, we must consider the
23 * property's full nested path, since properties like 'background.color' and
24 * 'background.border.color' refer to different values.
25 *
26 * Because a property may have multiple values depending on the control's state and
27 * subtype, we distinguish between a property's path ID and its storage ID. The path
28 * ID represents the portion of the property path that does not vary during lookups.
29 * For example, in the full path:
30 *
31 * "button.pressed.indicator.up.background.color"
32 *
33 * the portion that is invariant is:
34 *
35 * "indicator.background.color"
36 *
37 * The other parts of the path—such as the control type ('button'), the state ('pressed'),
38 * and the subtype ('up')—are resolved dynamically by the propagation engine. During lookup,
39 * the engine substitutes these components in decreasing order of specificity. For instance:
40 *
41 * - If the property is not found on 'button', it falls back to 'abstractButton'.
42 * - If it is not found in the 'pressed' state, it falls back to 'normal'.
43 * - If it is not found in the 'up' subtype, it falls back to 'indicator'.
44 *
45 * These varying components are prepended in sequence by the propagation engine to form
46 * the final PropertyStorageId, which uniquely identifies the stored value in the map.
47 *
48 * Note that a property path may also include groups known as Options. These are not part
49 * of the Path ID or the Storage ID; they are simply flags used by QQStyleKitPropertyResolver
50 * to control how a property should be read.
51 *
52 * In general, the structure of a property path is:
53 *
54 * control.options.states.subtype.nested_group_path.property
55 *
56 * However, for API convenience, subtypes are written inside the delegate they belong to.
57 * For example, although the storage path is "spinBox.up.indicator.background.color", the
58 * style syntax is "spinBox.indicator.up.background.color". */
59
60QT_BEGIN_NAMESPACE
61
62class QQStyleKitPropertyGroup;
63
64using PropertyPathId = quint32;
65using PropertyStorageId = quint32;
66using QQStyleKitExtendableControlType = quint32;
67using QQStyleKitPropertyStorage = QHash<PropertyStorageId, QVariant>;
68
69constexpr PropertyPathId maxPropertyStorageSpaceSize = std::numeric_limits<PropertyPathId>::max();
70constexpr PropertyPathId nestedGroupCount = PropertyPathId(QQSK::PropertyGroup::PATH_ID_GROUP_COUNT);
71constexpr PropertyPathId maxStateCombinationCount = PropertyPathId(QQSK::StateFlag::MAX_STATE);
72constexpr PropertyPathId stateStorageSpaceSize = maxPropertyStorageSpaceSize / maxStateCombinationCount;
73constexpr PropertyPathId subtypeCount = PropertyPathId(QQSK::PropertyPathFlag::DelegateSubtype2) - PropertyPathId(QQSK::PropertyPathFlag::DelegateSubtype0) + 1;
74constexpr PropertyPathId nestedGroupsStartSize = maxPropertyStorageSpaceSize / (maxStateCombinationCount * subtypeCount);
75constexpr PropertyPathId subtypeStorageSpaceSize = maxPropertyStorageSpaceSize / (subtypeCount * maxStateCombinationCount);
76
81
84
85public:
90 Q_ENUM(Flag)
91
97
98 inline QQSK::Property property() const { return m_property; }
99 inline QString toString() const { return pathIdToPathString(pathId()); }
100
101 static QString pathIdToPathString(PropertyPathId pathId);
102 static QString storageIdToPathString(PropertyStorageId storageId);
103
104 inline PropertyPathId pathId() const
105 {
106 /* The path ID is the property's identifier when its group path is taken
107 * into account. Each property inside QQStyleKitControlProperties has a unique
108 * path ID. For example, both 'background.color' and 'indicator.color' use the
109 * same QQSK::Property (Color), but they still have different path IDs.
110 * Whether or not to include the subtype, and therefore prepend it in front of
111 * the group path, was decided already in the constructor. */
112 return m_groupStart + PropertyPathId(m_property);
113 }
114
115 inline QQSK::PropertyGroup subType() const
116 {
117 return extractSubtype(m_groupStart);
118 }
119
120 inline PropertyStorageId createStorageId(QQSK::State state) const
121 {
122 /* To compute the fully qualified property ID used as a key in a storage map
123 * (QMap) that holds its value, we need to prefix the path ID with the state ID,
124 * since the same path can have different values in different states.
125 * Because StateFlag::Normal == 1, we subtract 1 so that the address space for
126 * properties in the Normal state starts at 0. */
127 Q_ASSERT(state != QQSK::StateFlag::Unspecified);
128 const PropertyPathId stateIndex = PropertyPathId(state) - 1;
129 const PropertyPathId stateStart = stateIndex * stateStorageSpaceSize;
130 return stateStart + pathId();
131 }
132
133 static inline QQSK::PropertyGroup extractSubtype(PropertyPathId pathId)
134 {
135 /* The subtype occupies its own slab at the start of the path ID space, so the
136 * subtype index is recovered by dividing the path ID by the slab size. Both the
137 * group start and the full path ID lie within the same slab, so the result is the
138 * same whether or not the property is included. */
139 const PropertyPathId subtypeIndex = pathId / subtypeStorageSpaceSize;
140 return QQSK::PropertyGroup(int(QQSK::PropertyGroup::DelegateSubtype0) + int(subtypeIndex));
141 }
142
143 static inline QQSK::State extractState(PropertyStorageId storageId)
144 {
145 /* Reverse the storageId function above, and return the state from the
146 * given PropertyStorageId. The state occupies the most significant portion
147 * of storageId. Adding 1 reverses the -1 applied in storageId() when encoding
148 * the state. */
149 const PropertyPathId stateIndex = storageId / stateStorageSpaceSize;
150 return QQSK::State(stateIndex + 1);
151 }
152
153 static inline PropertyPathId extractPropertyPathId(PropertyStorageId storageId,
154 QQStyleKitPropertyPath::Flag flag = QQStyleKitPropertyPath::Flag::IncludeSubtype)
155 {
156 /* Reverse the storageId function above, and return the path ID from the
157 * given PropertyStorageId. The state is stripped by taking the remainder,
158 * leaving the path ID including the subtype. When ExcludeSubtype, the subtype
159 * slab is stripped with a second remainder operation. */
160 if (flag == Flag::IncludeSubtype)
161 return storageId % stateStorageSpaceSize;
162 else
163 return (storageId % stateStorageSpaceSize) % subtypeStorageSpaceSize;
164 }
165
166private:
167 QQSK::Property m_property;
168 PropertyPathId m_groupStart;
169
170 static QHash<PropertyPathId, QString> s_cachedPathStrings;
171};
172
173QT_END_NAMESPACE
174
175#endif // QQSTYLEKITPROPERTYPATH_P_H
QQStyleKitDelegateProperties * delegateStyle() const
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void setDelegateStyle(QQStyleKitDelegateProperties *delegateProperties)
QQStyleKitDelegateProperties * first() const
void forEachExistingNestedGroup(const std::function< void(QQStyleKitPropertyGroup *)> &f) const override
QQStyleKitDelegateProperties * second() const
QQStyleKitDelegateProperties * foreground() const
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
void forEachExistingNestedGroup(const std::function< void(QQStyleKitPropertyGroup *)> &f) const override
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
void forEachExistingNestedGroup(const std::function< void(QQStyleKitPropertyGroup *)> &f) const override
QQStyleKitDelegateProperties * foreground() const
QQStyleKitIndicatorProperties * down() const
QQStyleKitIndicatorProperties * up() const
QQStyleKitIndicatorProperties * second() const
QQStyleKitIndicatorProperties * first() const
bool setStyleProperty(QQSK::Property property, T value)
QQStyleKitPropertyGroupSpace m_groupSpace
void emitChangedForAllStylePropertiesRecursive(EmitFlags emitFlags)
T styleProperty(QQSK::Property property, const T &defaultValue) const
T styleProperty(QQSK::Property property, QQSK::Property alternative=QQSK::Property::NoProperty) const
T * lazyCreateGroup(T *const &ptr, QQSK::PropertyGroup group) const
QQSK::PropertyPathFlags pathFlags() const
void handleStylePropertyChanged(void(SUBCLASS::*changedSignal)())
virtual void forEachExistingNestedGroup(const std::function< void(QQStyleKitPropertyGroup *)> &f) const
void handleStylePropertiesChanged(CHANGED_SIGNALS... changedSignals)
bool isDefined(QQSK::Property property) const
QQStyleKitControlProperties * controlProperties() const
QQStyleKitPropertyGroupSpace groupSpace() const
PropertyPathId pathId() const
static QQSK::PropertyGroup extractSubtype(PropertyPathId pathId)
static QQSK::State extractState(PropertyStorageId storageId)
static QString pathIdToPathString(PropertyPathId pathId)
static QString storageIdToPathString(PropertyStorageId storageId)
static PropertyPathId extractPropertyPathId(PropertyStorageId storageId, QQStyleKitPropertyPath::Flag flag=QQStyleKitPropertyPath::Flag::IncludeSubtype)
PropertyStorageId createStorageId(QQSK::State state) const
QQSK::PropertyGroup subType() const
QQSK::Property property() const
void setBottomPadding(qreal bottomPadding)
void setAlignment(Qt::Alignment alignment)
void forEachExistingNestedGroup(const std::function< void(QQStyleKitPropertyGroup *)> &f) const override
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
QQStyleKitTextProperties * first() const
QQStyleKitTextProperties * second() const
Combined button and popup list for selecting options.
constexpr PropertyPathId subtypeStorageSpaceSize
constexpr PropertyPathId stateStorageSpaceSize
constexpr PropertyPathId maxPropertyStorageSpaceSize
constexpr PropertyPathId nestedGroupCount
constexpr PropertyPathId maxStateCombinationCount
constexpr PropertyPathId nestedGroupsStartSize
constexpr PropertyPathId subtypeCount