aboutsummaryrefslogtreecommitdiffstats
path: root/src/labs/stylekit/qqstylekitglobal_p.h
blob: e4d6a151dc0b0b2ba57139ec61a28f9ad7f6c922 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default

#ifndef QQSTYLEKITGLOBAL_P_H
#define QQSTYLEKITGLOBAL_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QtQml/QtQml>

QT_BEGIN_NAMESPACE

class QQSK: public QObject
{
    Q_OBJECT

public:
    enum class Delegate {
        NoDelegate              = 0x0000,
        Control                 = 0x0001,
        Background              = 0x0002,
        Handle                  = 0x0004,
        HandleFirst             = 0x0008,
        HandleSecond            = 0x0010,
        Indicator               = 0x0020,
        IndicatorForeground     = 0x0040,
        IndicatorUp             = 0x0080,
        IndicatorUpForeground   = 0x0100,
        IndicatorDown           = 0x0200,
        IndicatorDownForeground = 0x0400,
    };
    Q_DECLARE_FLAGS(Delegates, Delegate)
    Q_FLAG(Delegate)

    enum class PropertyGroup {
        Control,
        Background,
        Foreground,
        Border,
        Handle,
        Image,
        Indicator,
        Shadow,
        Text,
        PATH_ID_GROUP_COUNT,

        /* Sub types, like states, are a part of a propertys storage ID, not its Path ID.
         * They appear in the group path, but are handled differently. */
        DelegateSubtype0,
        DelegateSubtype1,
        DelegateSubtype2,

        /* Read options are not a part of either the Path ID nor the Storage ID. They
         * just offer a convenient API for providing read options when reading a property.
         * The Global flag is used to signal that a property should be read directly from
         * the global style, circumventing the local StyleKitReader cache. */
        GlobalFlag,

        Unspecified
    };
    Q_ENUM(PropertyGroup)

    enum class PropertyPathFlag : quint8 {
        NoFlags             = 0x0,
        DelegateSubtype0    = 0x1,
        DelegateSubtype1    = 0x2,
        DelegateSubtype2    = 0x4,
        Global              = 0x8
    };
    Q_DECLARE_FLAGS(PropertyPathFlags, PropertyPathFlag)
    Q_FLAG(PropertyPathFlag)

    enum class Property {
        NoProperty,
        BottomLeftRadius,
        BottomMargin,
        BottomPadding,
        BottomRightRadius,
        Clip,
        Color,
        Data,
        Delegate,
        FillMode,
        Gradient,
        HOffset,
        Image,
        ImplicitWidth,
        ImplicitHeight,
        LeftMargin,
        LeftPadding,
        Margins,
        MinimumWidth,
        Opacity,
        Padding,
        Radius,
        RightMargin,
        RightPadding,
        Rotation,
        Scale,
        Source,
        Spacing,
        TopLeftRadius,
        TopMargin,
        TopPadding,
        TopRightRadius,
        Transition,
        Variations,
        Visible,
        VOffset,
        Width,
        Blur,
        Alignment,
        Bold,
        Italic,
        PointSize,
        COUNT
    };
    Q_ENUM(Property)

    enum class StateFlag {
        Unspecified = 0x000,
        Normal      = 0x001,
        Pressed     = 0x002,
        Hovered     = 0x004,
        Highlighted = 0x008,
        Focused     = 0x010,
        Checked     = 0x020,
        Vertical    = 0x040,
        Disabled    = 0x080,
        MAX_STATE   = 0x100,
    };
    Q_DECLARE_FLAGS(State, StateFlag)
    Q_FLAG(State)

    enum class Subclass {
        QQStyleKitState,
        QQStyleKitReader,
    };
    Q_ENUM(Subclass)

public:
    template <typename T, typename Owner, typename... Args>
    static inline T *lazyCreate(T *const &ptr, const Owner *self, Args&&... args)
    {
        if (!ptr) {
            auto *mutableSelf = const_cast<Owner *>(self);
            auto *&mutablePtr = const_cast<T *&>(ptr);
            mutablePtr = new T(std::forward<Args>(args)..., mutableSelf);
        }
        return ptr;
    }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QQSK::State)
Q_DECLARE_OPERATORS_FOR_FLAGS(QQSK::Delegates)
Q_DECLARE_OPERATORS_FOR_FLAGS(QQSK::PropertyPathFlags)

using PropertyPathId_t = quint32;
using PropertyStorageId = quint32;
using QQStyleKitExtendableControlType = quint32;
using QQStyleKitPropertyStorage = QHash<PropertyStorageId, QVariant>;

constexpr PropertyPathId_t maxPropertyStorageSpaceSize = std::numeric_limits<PropertyPathId_t>::max();
constexpr PropertyPathId_t nestedGroupCount = PropertyPathId_t(QQSK::PropertyGroup::PATH_ID_GROUP_COUNT);
constexpr PropertyPathId_t maxStateCombinationCount = PropertyPathId_t(QQSK::StateFlag::MAX_STATE);
constexpr PropertyPathId_t stateStorageSpaceSize = maxPropertyStorageSpaceSize / maxStateCombinationCount;
constexpr PropertyPathId_t subtypeCount = PropertyPathId_t(QQSK::PropertyPathFlag::DelegateSubtype2) - PropertyPathId_t(QQSK::PropertyPathFlag::DelegateSubtype0) + 1;
constexpr PropertyPathId_t nestedGroupsStartSize = maxPropertyStorageSpaceSize / (maxStateCombinationCount * subtypeCount);
constexpr PropertyPathId_t subtypeStorageSpaceSize = maxPropertyStorageSpaceSize / (subtypeCount * maxStateCombinationCount);

struct QQStyleKitPropertyGroupSpace {
    PropertyPathId_t size = 0;
    PropertyPathId_t start = 0;
};

class PropertyPathId {
    Q_GADGET

public:
    enum class Flag {
        ExcludeSubtype,
        IncludeSubtype
    };
    Q_ENUM(Flag)

    PropertyPathId(
        const QQSK::Property property = QQSK::Property::NoProperty,
        const PropertyPathId_t groupStart = PropertyPathId_t(0),
        QQSK::PropertyGroup subtype = QQSK::PropertyGroup::DelegateSubtype0);

    inline QQSK::Property property() const { return m_property; }
    inline PropertyPathId_t pathId() const
    {
        /* The path ID is the property's identifier when its group path is taken
         * into account. Each property inside QQStyleKitControlProperties has a unique
         * path ID. For example, both 'background.color' and 'indicator.color' use the
         * same QQSK::Property (Color), but they still have different path IDs. */
        return m_groupStart + PropertyPathId_t(m_property);
    }
    inline PropertyStorageId storageId(QQSK::State state) const
    {
        /* To compute the fully qualified property ID used as a key in a storage map
         * (QMap) that holds its value, we need to prefix the path ID with the state ID,
         * since the same path can have different values in different states.
         * Because StateFlag::Normal == 1, we subtract 1 so that the address space for
         * properties in the Normal state starts at 0. */
        Q_ASSERT(state != QQSK::StateFlag::Unspecified);
        const PropertyPathId_t stateIndex = PropertyPathId_t(state) - 1;
        const PropertyPathId_t stateStart = stateIndex * stateStorageSpaceSize;
        return stateStart + pathId();
    }

private:
    QQSK::Property m_property;
    PropertyPathId_t m_groupStart;
};

QT_END_NAMESPACE

#endif // QQSTYLEKITGLOBAL_P_H