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
qqstylekitcontrolproperties.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
8
10
11// ************* ControlStyleProperties ****************
12
13/*!
14 \qmltype ControlStyleProperties
15 \inqmlmodule Qt.labs.StyleKit
16 \brief Defines the stylable properties for a control.
17
18 ControlStyleProperties defines the stylable properties for a
19 control: the visual building blocks \l background, \l indicator, \l handle,
20 and \l text, as well as layout properties like \l padding, \l spacing,
21 and \l transition.
22
23 The style properties are accessed through inherited types such as
24 \l ControlStyle and \l StyleReader.
25
26 \labs
27
28 \sa ControlStyle, StyleReader, ControlStateStyle, DelegateStyle
29*/
30
31/*!
32 \qmlproperty DelegateStyle ControlStyleProperties::background
33
34 Grouped property for styling the background of a control.
35
36 The background delegate is typically the main visual rectangle behind
37 the control. Use it to set \l {DelegateStyle::color}{colors},
38 \l {DelegateStyle::border}{borders},
39 \l {DelegateStyle::radius}{radii},
40 \l {DelegateStyle::shadow}{shadows},
41 \l {DelegateStyle::gradient}{gradients},
42 and \l {DelegateStyle::image}{images}.
43
44 \note The default \l {Style::fallbackStyle}{fallback style} sets \c {background.visible}
45 to \c false for controls that typically should not draw a background,
46 such as \l [QtQuickControls]{CheckBox}, \l [QtQuickControls]{RadioButton},
47 and \l [QtQuickControls]{Slider}. To show their background, set
48 \c {background.visible} to \c true explicitly.
49*/
50
51/*!
52 \qmlproperty real ControlStyleProperties::bottomPadding
53
54 The \l [QtQuickControls]{Control Layout}{bottom padding}
55 of the control. If not set, falls back to \l padding.
56
57 \sa padding, topPadding, leftPadding, rightPadding
58*/
59
60/*!
61 \qmlproperty HandleStyle ControlStyleProperties::handle
62
63 Grouped property for styling the handle of a control.
64
65 The handle is used by controls such as \l [QtQuickControls]{Switch},
66 \l [QtQuickControls]{Slider}, and \l [QtQuickControls]{RangeSlider}.
67 For a RangeSlider, the two handles can be styled individually through
68 \l {HandleStyle::first}{handle.first} and \l {HandleStyle::second}{handle.second}.
69
70 \sa HandleStyle, DelegateStyle
71*/
72
73/*!
74 \qmlproperty IndicatorStyle ControlStyleProperties::indicator
75
76 Grouped property for styling the indicator of a control. For a
77 \l {AbstractStylableControls::}{checkBox}, the indicator is the
78 frame, and its \l {IndicatorStyle::}{foreground} is the check mark.
79 For a \l {AbstractStylableControls::}{slider}, the indicator is
80 the groove, and the foreground is the fill.
81
82 \sa DelegateStyle
83*/
84
85/*!
86 \qmlproperty real ControlStyleProperties::leftPadding
87
88 The \l [QtQuickControls]{Control Layout}{left padding} of the control. If not set, falls back to
89 \l padding.
90
91 \sa padding, rightPadding, topPadding, bottomPadding
92*/
93
94/*!
95 \qmlproperty real ControlStyleProperties::padding
96
97 The uniform spacing between the
98 \l [QtQuickControls]{Control Layout}{control's content area and the
99 bounds of the control}. Setting this provides a default value for
100 \l leftPadding, \l rightPadding, \l topPadding, and \l bottomPadding.
101 Each side can be overridden individually.
102
103 \sa leftPadding, rightPadding, topPadding, bottomPadding
104*/
105
106/*!
107 \qmlproperty real ControlStyleProperties::rightPadding
108
109 The \l [QtQuickControls]{Control Layout}{right padding} of the control.
110 If not set, falls back to \l padding.
111
112 \sa padding, leftPadding, topPadding, bottomPadding
113*/
114
115/*!
116 \qmlproperty real ControlStyleProperties::spacing
117
118 The spacing between visual elements inside the control, for example
119 between an indicator and a label.
120*/
121
122/*!
123 \qmlproperty TextStyle ControlStyleProperties::text
124
125 Grouped property for styling the text label of a control.
126*/
127
128/*!
129 \qmlproperty real ControlStyleProperties::topPadding
130
131 The \l [QtQuickControls]{Control Layout}{top padding}
132 of the control. If not set, falls back to \l padding.
133
134 \sa padding, bottomPadding, leftPadding, rightPadding
135*/
136
137/*!
138 \qmlproperty Transition ControlStyleProperties::transition
139
140 A \l [QtQuick]{Transition} used to animate style properties when the
141 control enters a new state, such as \l {ControlStateStyle::}{hovered}
142 or \l {ControlStateStyle::}{pressed}. If set
143 to \c null (the default), property changes are applied immediately
144 without animation.
145
146 \snippet DelegateStyle_transitions.qml custom transition
147
148 To avoid repeating the same target properties for each delegate,
149 StyleKit provides \l StyleAnimation for convenience, which can be
150 used instead of, or in combination with, the
151 \l {Animation and Transitions in Qt Quick}{standard animations:}
152
153 \snippet DelegateStyle_transitions.qml transition
154
155 Also note that \l ColorAnimation has a special feature that
156 animates \e all color properties that changed during a
157 state change if \l {PropertyAnimation::}{property} and
158 \l {PropertyAnimation::}{properties} are left unset.
159*/
160
161// ************* DelegateStyle ****************
162
163/*!
164 \qmltype DelegateStyle
165 \inqmlmodule Qt.labs.StyleKit
166 \brief Defines the visual appearance of an element within a control.
167
168 DelegateStyle describes the visual appearance of a visual element
169 within a \l ControlStyle, such as its \l {ControlStyleProperties::}{background},
170 \l {ControlStyleProperties::}{indicator}, or a sub-element like
171 \l {IndicatorStyle::foreground}{indicator.foreground}.
172 It provides properties for controlling
173 \l {DelegateStyle::implicitWidth}{size},
174 \l {DelegateStyle::}{color}, \l {DelegateStyle::}{border},
175 \l {DelegateStyle::}{radius}, \l {DelegateStyle::}{shadow},
176 \l {DelegateStyle::}{image}, \l {DelegateStyle::}{opacity}, and more.
177
178 \labs
179
180 \sa ControlStyle, ControlStateStyle,
181 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
182*/
183
184/*!
185 \qmlproperty Qt::Alignment DelegateStyle::alignment
186
187 The alignment of the delegate within its parent. The default
188 value is \c {Qt.AlignLeft | Qt.AlignVCenter}.
189*/
190
191/*!
192 \qmlproperty BorderStyle DelegateStyle::border
193
194 Grouped property for styling the border of this delegate.
195*/
196
197/*!
198 \qmlproperty real DelegateStyle::bottomLeftRadius
199
200 The bottom-left corner radius. If not set, falls back to \l radius.
201
202 \sa radius, topLeftRadius, topRightRadius, bottomRightRadius
203*/
204
205/*!
206 \qmlproperty real DelegateStyle::bottomMargin
207
208 The bottom margin of this delegate. If not set, falls back to
209 \l margins.
210
211 \sa margins, topMargin, leftMargin, rightMargin
212*/
213
214/*!
215 \qmlproperty real DelegateStyle::bottomRightRadius
216
217 The bottom-right corner radius. If not set, falls back to \l radius.
218
219 \sa radius, topLeftRadius, topRightRadius, bottomLeftRadius
220*/
221
222/*!
223 \qmlproperty bool DelegateStyle::clip
224
225 Whether the delegate clips its contents. The default value is \c false.
226*/
227
228/*!
229 \qmlproperty color DelegateStyle::color
230
231 The fill color of this delegate. The default value is \c transparent.
232
233 Unlike a Quick \l [QtQuick]{Rectangle}, where a gradient replaces
234 the color, StyleKit draws the \l gradient on top of the color. This
235 means you can use a semi-transparent gradient as an overlay (for
236 example, a subtle shading effect) while the color shows through
237 underneath.
238
239 \snippet ControlStateStyle_properties.qml color and gradient
240
241 \sa gradient, opacity
242*/
243
244/*!
245 \qmlproperty QObject DelegateStyle::data
246
247 An arbitrary object that can be used for passing
248 custom data from the style to a custom \l delegate component.
249
250 This allows you to define custom style properties beyond what the
251 StyleKit API provides. The data object can vary between states and
252 themes, making it possible to style elements in a custom \l delegate
253 that are not covered by the built-in properties.
254
255 The following snippet uses a custom delegate that draws an overlay
256 \l Text whose color varies depending on the control's state. The delegate
257 inherits \l StyledItem, which is optional but ensures the rest of
258 the button background is rendered normally.
259
260 \snippet DelegateStyle_delegates.qml data
261
262 \note The \c data object is propagated as a whole. Unlike regular style
263 properties, individual properties \e inside the data object do not
264 propagate separately.
265
266 \sa delegate
267*/
268
269/*!
270 \qmlproperty Component DelegateStyle::delegate
271
272 The delegate used to render the DelegateStyle in a
273 \l {Qt Quick Controls}{Qt Quick Control}.
274
275 The default value is \c null, in which case \l StyledItem is used
276 for rendering instead. If you want to hide the delegate altogether
277 (and prevent if from being created), set \l visible to \c false.
278
279 The delegate needs to define the following required properties:
280 \qml
281 required property DelegateStyle delegateStyle
282 required property QtObject control
283 \endqml
284
285 \c delegateStyle points to the DelegateStyle that describes how the
286 delegate should be styled. \c control points to the
287 \l {Qt Quick Controls}{Qt Quick Control} that owns the delegate. The latter
288 can be used to resolve additional information about the control not
289 available from the style.
290
291 If you know the specific type of the owning control, you can use it
292 instead of \l QtObject for the \c control property. For example, since
293 a handle delegate in the snippet below is always used inside a Slider, the
294 type can be set to \l {Qt Quick Templates 2 QML Types}{T.Slider}:
295
296 \snippet DelegateStyle_delegates.qml delegate
297
298 \note If a DelegateStyle has a \l {shadow}{drop shadow} defined, it will be
299 drawn separately by a \l {ShadowStyle::delegate}{shadow delegate.}
300
301 \sa data, visible, StyledItem
302*/
303
304/*!
305 \qmlproperty Gradient DelegateStyle::gradient
306
307 The gradient of this delegate. The default value is \c null (no gradient).
308
309 Unlike a Quick \l [QtQuick]{Rectangle}, where a gradient replaces
310 the color, StyleKit draws the \l gradient on top of the color. This
311 means you can use a semi-transparent gradient as an overlay (for
312 example, a subtle shading effect) while the color shows through
313 underneath.
314
315 \snippet ControlStateStyle_properties.qml color and gradient
316
317 \sa color
318*/
319
320/*!
321 \qmlproperty ImageStyle DelegateStyle::image
322
323 Grouped property for placing an image inside this delegate.
324
325 \sa ImageStyle
326*/
327
328/*!
329 \qmlproperty real DelegateStyle::implicitHeight
330
331 The implicit height of this delegate.
332*/
333
334/*!
335 \qmlproperty real DelegateStyle::implicitWidth
336
337 The implicit width of this delegate. Set this to \l {Style::Stretch}{Style.Stretch}
338 to make the delegate fill the available width of the control.
339*/
340
341/*!
342 \qmlproperty real DelegateStyle::leftMargin
343
344 The left margin of this delegate. If not set, falls back to
345 \l margins.
346
347 \sa margins, rightMargin, topMargin, bottomMargin
348*/
349
350/*!
351 \qmlproperty real DelegateStyle::margins
352
353 The uniform margin around this delegate. Setting this provides a
354 default value for \l leftMargin, \l rightMargin, \l topMargin,
355 and \l bottomMargin. Each side can be overridden individually.
356
357 \sa leftMargin, rightMargin, topMargin, bottomMargin
358*/
359
360/*!
361 \qmlproperty real DelegateStyle::minimumWidth
362
363 The minimum width of this delegate. The delegate will not be sized
364 smaller than this value.
365*/
366
367/*!
368 \qmlproperty real DelegateStyle::opacity
369
370 The opacity of this delegate, from \c 0.0 (fully transparent) to
371 \c 1.0 (fully opaque). The default value is \c 1.0.
372
373 \sa visible, color
374*/
375
376/*!
377 \qmlproperty real DelegateStyle::radius
378
379 The corner radius applied to all four corners of this delegate.
380 Individual corners can be overridden with \l topLeftRadius,
381 \l topRightRadius, \l bottomLeftRadius, and \l bottomRightRadius.
382
383 \sa topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius
384*/
385
386/*!
387 \qmlproperty real DelegateStyle::rightMargin
388
389 The right margin of this delegate. If not set, falls back to
390 \l margins.
391
392 \sa margins, leftMargin, topMargin, bottomMargin
393*/
394
395/*!
396 \qmlproperty real DelegateStyle::rotation
397
398 The rotation of this delegate, in degrees.
399*/
400
401/*!
402 \qmlproperty real DelegateStyle::scale
403
404 The scale factor of this delegate. The default value is \c 1.0.
405*/
406
407/*!
408 \qmlproperty ShadowStyle DelegateStyle::shadow
409
410 Grouped property for styling a drop shadow behind this delegate.
411
412 \sa ShadowStyle
413*/
414
415/*!
416 \qmlproperty real DelegateStyle::topLeftRadius
417
418 The top-left corner radius. If not set, falls back to \l radius.
419
420 \sa radius, topRightRadius, bottomLeftRadius, bottomRightRadius
421*/
422
423/*!
424 \qmlproperty real DelegateStyle::topMargin
425
426 The top margin of this delegate. If not set, falls back to
427 \l margins.
428
429 \sa margins, bottomMargin, leftMargin, rightMargin
430*/
431
432/*!
433 \qmlproperty real DelegateStyle::topRightRadius
434
435 The top-right corner radius. If not set, falls back to \l radius.
436
437 \sa radius, topLeftRadius, bottomLeftRadius, bottomRightRadius
438*/
439
440/*!
441 \qmlproperty bool DelegateStyle::visible
442
443 Whether this delegate is visible. The default value is \c true.
444
445 \note Although the default value is \c true, the
446 \l {Style::fallbackStyle}{fallback style} (which overrides many of the default
447 values) sets \c {background.visible} to \c false for controls that typically
448 should not draw a background, such as \l [QtQuickControls]{CheckBox},
449 \l [QtQuickControls]{RadioButton}, and \l [QtQuickControls]{Slider}.
450
451 When \c visible is \c false, the \l delegate will not be created. If you need
452 a hidden delegate to be created, consider setting \l opacity to \c 0 instead.
453
454 \sa opacity
455*/
456
457// ************* ImageStyle ****************
458
459/*!
460 \qmltype ImageStyle
461 \inqmlmodule Qt.labs.StyleKit
462 \brief Defines the image style for a delegate.
463
464 ImageStyle provides properties for placing an image inside a
465 \l DelegateStyle. It is available as the
466 \l {DelegateStyle::image}{image} grouped property on any delegate.
467
468 \labs
469
470 \sa DelegateStyle, ControlStyle, ControlStateStyle,
471 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
472*/
473
474/*!
475 \qmlproperty color ImageStyle::color
476
477 A color overlay applied to the image. This is typically used to tint
478 monochrome icons to match the style's color scheme.
479*/
480
481/*!
482 \qmlproperty enumeration ImageStyle::fillMode
483
484 How the image should be scaled or tiled within the delegate. The
485 value is one of the \l [QtQuick]{Image::fillMode}{Image.fillMode}
486 enum values.
487*/
488
489/*!
490 \qmlproperty url ImageStyle::source
491
492 The URL of the image to display inside the delegate.
493*/
494
495// ************* BorderStyle ****************
496
497/*!
498 \qmltype BorderStyle
499 \inqmlmodule Qt.labs.StyleKit
500 \brief Defines the border style for a delegate.
501
502 BorderStyle provides properties for the border drawn around a
503 \l DelegateStyle. It is available as the
504 \l {DelegateStyle::border}{border} grouped property on any delegate.
505
506 \labs
507
508 \sa DelegateStyle, ControlStyle, ControlStateStyle,
509 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
510*/
511
512/*!
513 \qmlproperty color BorderStyle::color
514
515 The color of the border. The default value is \c transparent.
516*/
517
518/*!
519 \qmlproperty real BorderStyle::width
520
521 The width of the border in pixels.
522*/
523
524// ************* ShadowStyle ****************
525
526/*!
527 \qmltype ShadowStyle
528 \inqmlmodule Qt.labs.StyleKit
529 \brief Defines the drop shadow style for a delegate.
530
531 ShadowStyle provides properties for rendering a drop shadow behind
532 a \l DelegateStyle. It is available as the
533 \l {DelegateStyle::shadow}{shadow} grouped property on any delegate.
534
535 \snippet DelegateStyle_shadow.qml drop shadow
536
537 By adjusting scale and color, shadows can also be used to create
538 glow effects. The following snippet adds a diffuse white glow to
539 the handle of a \l [QtQuickControls]{Switch} that intensifies
540 when checked:
541
542 \snippet DelegateStyle_shadow.qml glow
543
544 \labs
545
546 \sa DelegateStyle, ControlStyle, ControlStateStyle,
547 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
548*/
549
550/*!
551 \qmlproperty real ShadowStyle::blur
552
553 The blur of the shadow. A value of \c 0.0 produces a sharp shadow, while
554 larger values produce a softer, more diffuse shadow.
555 The default value is \c 10.0.
556*/
557
558/*!
559 \qmlproperty color ShadowStyle::color
560
561 The color of the shadow. The default value is \c transparent, which
562 means that no shadow will be drawn by default.
563
564 \sa visible, opacity
565*/
566
567/*!
568 \qmlproperty Component ShadowStyle::delegate
569
570 A custom QML \l [QML]{Component} that replaces the default shadow
571 rendering. When set, StyleKit instantiates this component instead
572 of drawing the default shadow.
573*/
574
575/*!
576 \qmlproperty real ShadowStyle::horizontalOffset
577
578 The horizontal offset of the shadow from the delegate, in pixels.
579*/
580
581/*!
582 \qmlproperty real ShadowStyle::opacity
583
584 The opacity of the shadow, from \c 0.0 (fully transparent) to
585 \c 1.0 (fully opaque). The default value is \c 1.0.
586
587 \sa visible, color
588*/
589
590/*!
591 \qmlproperty real ShadowStyle::scale
592
593 The scale factor of the shadow relative to the delegate.
594 The default value is \c 1.0.
595*/
596
597/*!
598 \qmlproperty real ShadowStyle::verticalOffset
599
600 The vertical offset of the shadow from the delegate, in pixels.
601*/
602
603/*!
604 \qmlproperty bool ShadowStyle::visible
605
606 Whether the shadow is visible. The default value is \c true.
607
608 However, since the default shadow \l color is \c transparent,
609 the shadow will not be visible unless a different color is set.
610
611 \sa opacity
612*/
613
614// ************* HandleStyle ****************
615
616/*!
617 \qmltype HandleStyle
618 \inqmlmodule Qt.labs.StyleKit
619 \inherits DelegateStyle
620 \brief Defines the handle style for controls such as \l [QtQuickControls]{Switch},
621 \l [QtQuickControls]{Slider} and \l [QtQuickControls]{RangeSlider}.
622
623 HandleStyle extends \l DelegateStyle with properties that are specific to
624 styling a handle.
625
626 Some controls have more than one handle. For example,
627 \l [QtQuickControls]{RangeSlider} has both a \l [QtQuickControls]{RangeSlider::}{first} and a \l [QtQuickControls]{RangeSlider::}{second} handle.
628 These can be styled independently using the \l first and \l second
629 sub-handles, \c {slider.handle.first} and \c {slider.handle.second}.
630 Properties not set on a sub-handle fall back to the handle itself.
631
632 \labs
633
634 \sa DelegateStyle, ControlStyle, ControlStateStyle,
635 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
636*/
637
638/*!
639 \qmlproperty DelegateStyle HandleStyle::first
640
641 Grouped property for styling the first handle of for example a
642 \l [QtQuickControls]{RangeSlider}. Unset properties fall back to
643 the HandleStyle itself.
644*/
645
646/*!
647 \qmlproperty DelegateStyle HandleStyle::second
648
649 Grouped property for styling the second handle of for example a
650 \l [QtQuickControls]{RangeSlider}. Unset properties fall back to
651 the HandleStyle itself.
652*/
653
654// ************* SubIndicatorStyle ****************
655
656/*!
657 \qmltype SubIndicatorStyle
658 \inqmlmodule Qt.labs.StyleKit
659 \inherits DelegateStyle
660 \brief Defines the style for a sub-indicator delegate.
661
662 SubIndicatorStyle extends \l DelegateStyle with a \l foreground
663 property. It is used for styling sub-indicator delegates such as
664 \l {IndicatorStyle::first}{indicator.first} and
665 \l {IndicatorStyle::second}{indicator.second} in controls
666 with multiple indicators, like \l [QtQuickControls]{SpinBox}.
667 For SpinBox, \c {indicator.first} styles the increment button, and
668 \c {indicator.second} styles the decrement button.
669 It is equivalent to \l IndicatorStyle, but does not itself
670 contain sub-indicators.
671
672 \labs
673
674 \sa IndicatorStyle, DelegateStyle, ControlStyle, ControlStateStyle,
675 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
676*/
677
678/*!
679 \qmlproperty DelegateStyle SubIndicatorStyle::foreground
680
681 Grouped property for styling the foreground element of this
682 indicator. The foreground typically represents a checkmark, icon
683 or arrow rendered inside the indicator.
684*/
685
686// ************* IndicatorStyle ****************
687
688/*!
689 \qmltype IndicatorStyle
690 \inqmlmodule Qt.labs.StyleKit
691 \inherits DelegateStyle
692 \brief Defines the style for a control's indicator.
693
694 IndicatorStyle extends \l DelegateStyle with properties that are specific to
695 styling an indicator.
696
697 The IndicatorStyle itself describes the indicator background, while the
698 \l foreground describes the content drawn inside it. For example,
699 \c {checkBox.indicator} styles the check box frame and
700 \c {checkBox.indicator.foreground} styles the check mark. For
701 \l {AbstractStylableControls::}{switchControl},
702 \l {AbstractStylableControls::}{slider} and
703 \l {AbstractStylableControls::}{progressBar}, the indicator styles
704 the groove and the foreground styles the fill.
705
706 \snippet DelegateStyle_indicator.qml checkBox
707
708 Some controls have more than one indicator. For example,
709 \l [QtQuickControls]{SpinBox} has both an increment and a decrement
710 button. These can be styled independently using the \l first and \l second
711 sub-indicators, \c {spinBox.indicator.first} and
712 \c {spinBox.indicator.second}. For SpinBox, \c {indicator.first} styles
713 the increment button, and \c {indicator.second} styles the decrement
714 button. Properties not set on a sub-indicator fall back to the indicator
715 itself.
716
717 \note The \c up and \c down properties are kept as aliases for
718 \c first and \c second for backward compatibility. New code
719 should use \c first and \c second, as these names are generic and can be
720 used by controls with sub-indicators that do not represent up/down actions.
721 The compatibility aliases may be removed in a future version.
722
723 \snippet DelegateStyle_indicator.qml up and down indicator
724
725 \labs
726
727 \sa SubIndicatorStyle, DelegateStyle, ControlStyle, ControlStateStyle,
728 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
729*/
730
731/*!
732 \qmlproperty DelegateStyle IndicatorStyle::foreground
733
734 Grouped property for styling the foreground element of this
735 indicator. For example, \c {checkBox.indicator} describes
736 the check box frame, while \c {checkBox.indicator.foreground} is the check mark.
737
738 For controls like \l {AbstractStylableControls::}{slider},
739 \l {AbstractStylableControls::}{progressBar}, and
740 \l {AbstractStylableControls::}{switchControl}, the \c {indicator.foreground}
741 represents the progress track or fill within the groove, while the \c indicator
742 itself represents the groove.
743*/
744
745/*!
746 \qmlproperty SubIndicatorStyle IndicatorStyle::first
747
748 Grouped property for styling the first sub-indicator of controls that
749 expose multiple indicators. For \l [QtQuickControls]{SpinBox}, this
750 styles the increment button.
751 Unset properties fall back to the indicator itself.
752
753 \note The \c up property is kept as an alias for \c first for backward
754 compatibility. New code should use \c first, as this name is generic
755 and can be used by controls with sub-indicators that do not represent
756 up actions. The compatibility alias may be removed in a future version.
757
758 \sa second
759*/
760
761/*!
762 \qmlproperty SubIndicatorStyle IndicatorStyle::second
763
764 Grouped property for styling the second sub-indicator of for example a
765 \l [QtQuickControls]{SpinBox}.
766 Unset properties fall back to the indicator itself.
767
768 \note The \c down property is kept as an alias for \c second for backward
769 compatibility. New code should use \c second, as this name is generic
770 and can be used by controls with sub-indicators that do not represent
771 down actions. The compatibility alias may be removed in a future version.
772
773 \sa first
774*/
775
776// ************* TextStyle ****************
777
778/*!
779 \qmltype TextStyle
780 \inqmlmodule Qt.labs.StyleKit
781 \brief Defines the text style for a control's label.
782
783 TextStyle provides properties for controlling the appearance of
784 text labels within a control, such as
785 \l color, \l alignment and \l padding,
786 and certain font-related properties such as
787 \l {TextStyle::}{bold},
788 \l {TextStyle::}{italic}, and
789 \l {TextStyle::pointSize}{font size}.
790
791 It is available as the \l {ControlStyleProperties::text}{text}
792 grouped property on every \l ControlStateStyle.
793
794 \labs
795
796 \sa DelegateStyle, ControlStyle, ControlStateStyle,
797 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
798*/
799
800/*!
801 \qmlproperty Qt::Alignment TextStyle::alignment
802
803 The alignment of the text within its available area.
804*/
805
806/*!
807 \qmlproperty bool TextStyle::bold
808
809 Whether the text should be rendered in bold. The default value
810 is \c false.
811
812 \sa italic
813*/
814
815/*!
816 \qmlproperty real TextStyle::bottomPadding
817
818 The bottom padding around the text. If not set, falls back to
819 \l padding.
820
821 \sa padding, topPadding, leftPadding, rightPadding
822*/
823
824/*!
825 \qmlproperty color TextStyle::color
826
827 The color of the text.
828*/
829
830/*!
831 \qmlproperty bool TextStyle::italic
832
833 Whether the text should be rendered in italic. The default value
834 is \c false.
835
836 \sa bold
837*/
838
839/*!
840 \qmlproperty real TextStyle::leftPadding
841
842 The left padding around the text. If not set, falls back to
843 \l padding.
844
845 \sa padding, rightPadding, topPadding, bottomPadding
846*/
847
848/*!
849 \qmlproperty real TextStyle::padding
850
851 The uniform padding around the text. Setting this provides a
852 default value for \l leftPadding, \l rightPadding, \l topPadding,
853 and \l bottomPadding. Each side can be overridden individually.
854
855 \sa leftPadding, rightPadding, topPadding, bottomPadding
856*/
857
858/*!
859 \qmlproperty real TextStyle::pointSize
860
861 The point size of the text font.
862*/
863
864/*!
865 \qmlproperty real TextStyle::rightPadding
866
867 The right padding around the text. If not set, falls back to
868 \l padding.
869
870 \sa padding, leftPadding, topPadding, bottomPadding
871*/
872
873/*!
874 \qmlproperty real TextStyle::topPadding
875
876 The top padding around the text. If not set, falls back to
877 \l padding.
878
879 \sa padding, bottomPadding, leftPadding, rightPadding
880*/
881
882// ************* QQStyleKitPropertyGroup ****************
883
884QHash<PropertyPathId_t, QString> QQStyleKitPropertyGroup::s_pathStrings;
885
886QQStyleKitPropertyGroup::QQStyleKitPropertyGroup(QQSK::PropertyGroup, QObject *parent)
887 : QObject(parent)
888{
889}
890
891PropertyPathId QQStyleKitPropertyGroup::propertyPathId(QQSK::Property property, PropertyPathId::Flag flag) const
892{
893 if (flag == PropertyPathId::Flag::IncludeSubtype) {
894 if (m_pathFlags.testFlag(QQSK::PropertyPathFlag::DelegateSubtype1))
895 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype1);
896 else if (m_pathFlags.testFlag(QQSK::PropertyPathFlag::DelegateSubtype2))
897 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype2);
898 }
899 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype0);
900}
901
903{
904 /* Start from the root of the path and build the path down to this group. This
905 * mirrors how the groups were originally created and avoids rounding issues
906 * that can arise if attempting to reconstruct the path “backwards”.
907 * Note: For each group, m_groupSpace.start is stored relative to the root,
908 * while m_groupSpace.size is relative to the parent group. However, when
909 * calculating the group index, the group-space start must be computed
910 * relative to the parent group.
911 * We cache the requested paths, as the same paths are typically requested
912 * repeatedly. The number of possible paths (and thus leaf groups) is well below
913 * 100, and in practice the cache usually ends up with fewer than 20 entries. */
914 if (s_pathStrings.contains(m_groupSpace.start))
915 return s_pathStrings[m_groupSpace.start];
916
917 constexpr PropertyPathId_t rootGroupsSize = nestedGroupsStartSize / nestedGroupCount;
918 const auto metaEnum = QMetaEnum::fromType<QQSK::PropertyGroup>();
919
920 PropertyPathId_t nestedGroupStart = m_groupSpace.start;
921 PropertyPathId_t nestedGroupSize = rootGroupsSize;
922 PropertyPathId_t nestedGroupIndex = nestedGroupStart / nestedGroupSize;
923 auto groupType = QQSK::PropertyGroup(nestedGroupIndex);
924 if (groupType == QQSK::PropertyGroup::Control)
925 return {};
926
927 QString groupName = QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(groupType)));
928 groupName[0] = groupName[0].toLower();
929 QString pathString = groupName;
930
931 while (true) {
932 nestedGroupStart -= nestedGroupIndex * nestedGroupSize;
933 nestedGroupSize /= nestedGroupCount;
934 nestedGroupIndex = nestedGroupStart / nestedGroupSize;
935 groupType = QQSK::PropertyGroup(nestedGroupIndex);
936 if (groupType == QQSK::PropertyGroup::Control)
937 break;
938
939 QString groupName = QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(groupType)));
940 groupName[0] = groupName[0].toLower();
941 pathString += '.'_L1 + groupName;
942 }
943
944 s_pathStrings.insert(m_groupSpace.start, pathString);
945 return pathString;
946}
947
948QQStyleKitControlProperties *QQStyleKitPropertyGroup::controlProperties() const
949{
951 Q_ASSERT(qobject_cast<const QQStyleKitControlProperties *>(this));
952 auto *self = const_cast<QQStyleKitPropertyGroup *>(this);
953 return static_cast<QQStyleKitControlProperties *>(self);
954 }
955 Q_ASSERT(qobject_cast<const QQStyleKitControlProperties *>(parent()));
956 return static_cast<QQStyleKitControlProperties *>(parent());
957}
958
959template<typename T>
960T *QQStyleKitPropertyGroup::lazyCreateGroup(T * const &ptr, QQSK::PropertyGroup group) const
961{
962 T *nestedGroup = QQSK::lazyCreate(ptr, controlProperties(), group);
963
964 // Nested groups inherit path flags from their parents
965 nestedGroup->m_pathFlags = m_pathFlags;
966
967 if (group == QQSK::PropertyGroup::DelegateSubtype1) {
968 /* Subtypes, like states, are not part of a property's path ID—they belong to the
969 * storage ID instead. They are therefore prefixed later, during lookup, when
970 * propagation determines which value to read.
971 * For now, we simply record which subtype this group (and any nested groups) is
972 * associated with. The subtype will then be taken into account later when reading
973 * properties from the group. Setting aside space for the sub types was already
974 * taken care of during the construction of the root QQStyleKitControlProperties. */
975 nestedGroup->m_pathFlags.setFlag(QQSK::PropertyPathFlag::DelegateSubtype1);
976 nestedGroup->m_groupSpace = m_groupSpace;
977 } else if (group == QQSK::PropertyGroup::DelegateSubtype2) {
978 nestedGroup->m_pathFlags.setFlag(QQSK::PropertyPathFlag::DelegateSubtype2);
979 nestedGroup->m_groupSpace = m_groupSpace;
980 } else {
981 /* Calculate the available property ID space for the nested group. This is done by
982 * dividing the available space inside _this_ group on the number of potential groups
983 * that _this_ group can potentially contain. */
984 const PropertyPathId_t nestedGroupIndex = PropertyPathId_t(group);
985 const PropertyPathId_t nestedGroupSize = m_groupSpace.size / nestedGroupCount;
986 nestedGroup->m_groupSpace.size = nestedGroupSize;
987 nestedGroup->m_groupSpace.start = m_groupSpace.start + (nestedGroupIndex * nestedGroupSize);
988 /* Ensure that we haven’t exhausted the available PropertyPathId space. There must be
989 * enough room remaining to assign IDs for all properties defined in QQSK::Property.
990 * If this assertion triggers, consider switching to a wider PropertyPathId_t type or
991 * optimizing how the space is allocated. For example, certain nested paths (such as
992 * control.handle.indicator) can never occur, yet we currently reserve INNER_GROUP_COUNT
993 * for every nesting level, which is wasteful. */
994 Q_ASSERT(nestedGroupSize >= PropertyPathId_t(QQSK::Property::COUNT));
995 }
996 return nestedGroup;
997}
998
999/* This macro will check if the caller has the same group path as \a GROUP_PATH.
1000 * This is needed since a QQSK::Property (e.g Color) can sometimes be a
1001 * property in several different subclasses of QQStyleKitPropertyGroup.
1002 * For example, both control.background.color and control.indicator.color has a
1003 * color property. But the group path differs, so they are in reality two completely
1004 * different properties. And in that case, when the former changes value, we want to
1005 * emit changes globally only to that property, and not the latter.
1006 * The caller of this macro will therefore need to go through all the usages of its
1007 * subclass in the API, to figure out which group itself is an instance of. For the
1008 * one that is a match, the macro will go through all readers and emit the same
1009 * signal for them. */
1010#define CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(CONTROL_PROPERTIES, GROUP_PATH) if
1011 (this == CONTROL_PROPERTIES -> GROUP_PATH ) {
1012 for (QQStyleKitReader *reader : QQStyleKitReader::s_allReaders) {
1013 const auto baseTypes = QQStyleKitPropertyResolver::baseTypesForType(reader->controlType());
1014 if (reader->controlType() != controlType && !baseTypes.contains(controlType))
1015 continue;
1016 reader->clearLocalStorage();
1017 ((reader-> GROUP_PATH ->*changedSignals)(), ...);
1018 }
1019 return; \
1020}
1021
1022template<typename SUBCLASS>
1023void QQStyleKitPropertyGroup::handleStylePropertyChanged(void (SUBCLASS::*changedSignal)()) {
1024 handleStylePropertiesChanged<SUBCLASS>(changedSignal);
1025}
1026
1027template <typename SUBCLASS, typename... CHANGED_SIGNALS>
1028void QQStyleKitPropertyGroup::handleStylePropertiesChanged(CHANGED_SIGNALS... changedSignals)
1029{
1030 /* This function will check which subclass of QQStyleKitProperties this
1031 * group is (nested) inside. Based on that, it will decide if the signals
1032 * should be emitted locally or not, and if the changed properties affects
1033 * all existing QQStyleKitReaders, and therefore will need to be
1034 * emitted 'globally'. Note that it only makes sense to call this function
1035 * for changed properties that are available from a QQStyleKitReader.
1036 * Properities only available from e.g QQStyleKitControl (such as
1037 * variations), are anyway not readable from a QQStyleKitReader. */
1038 static_assert(std::is_base_of<QQStyleKitPropertyGroup, SUBCLASS>::value,
1039 "SUBCLASS must inherit QQStyleKitPropertyGroup");
1040
1041 auto *group = static_cast<SUBCLASS *>(this);
1042 const QQSK::Subclass objectWrittenTo = controlProperties()->subclass();
1043
1044 if (objectWrittenTo == QQSK::Subclass::QQStyleKitState) {
1045 ((group->*changedSignals)(), ...);
1046
1047 if (shouldEmitGlobally()) {
1048 const QQStyleKitControl *control = controlProperties()->asQQStyleKitState()->control();
1049 const QQStyleKitExtendableControlType type = control->controlType();
1050 group->emitGlobally(type, changedSignals...);
1051 }
1052 return;
1053 }
1054
1055 if (objectWrittenTo == QQSK::Subclass::QQStyleKitReader) {
1056 /* Unless the StyleReader has told us not to emit any signals (because it's only
1057 * syncing it's own local storage with old values before starting a transition), we
1058 * emit the signal like normal. This will cause the control to repaint (perhaps
1059 * using a transition). */
1060 if (shouldEmitLocally()) {
1061 QQStyleKitReader *reader = controlProperties()->asQQStyleKitReader();
1062 /* Readers notify their consumer in two different ways depending on who is
1063 * consuming them. A QML control binds to the reader's change signals, so we
1064 * emit those directly. A widget consumer (m_target set) doesn't listen on
1065 * signals; it repaints in response to a QEvent::StyleAnimationUpdate posted
1066 * to the widget, and only while a transition is actually running. */
1067 if (!reader->m_target)
1068 ((group->*changedSignals)(), ...);
1069 else
1070 QCoreApplication::postEvent(reader->m_target, new QEvent(QEvent::StyleAnimationUpdate));
1071 }
1072 return;
1073 }
1074
1075 Q_UNREACHABLE();
1076}
1077
1079{
1080 /* This function will emit changed signals for all style properties in the
1081 * StyleKit API (for a single QQStyleKitReader), which is needed after
1082 * doing a style-, or theme change. */
1083 const int startIndex = QQStyleKitPropertyGroup::staticMetaObject.propertyOffset();
1084 const QMetaObject* meta = metaObject();
1085 for (int i = startIndex; i < meta->propertyCount(); ++i) {
1086 const QMetaProperty prop = meta->property(i);
1087 const QMetaObject* propMetaObject = QMetaType::fromName(prop.typeName()).metaObject();
1088 if (propMetaObject) {
1089 if (propMetaObject->inherits(&QQStyleKitDelegateProperties::staticMetaObject)) {
1090 /* Skip recursing into QQStyleKitDelegateProperties, because those are lazy
1091 * created when read, and reading them from here would accidentally
1092 * create them. */
1093 continue;
1094 }
1095 if (propMetaObject->inherits(&QQStyleKitPropertyGroup::staticMetaObject)) {
1096 // The property is of type QQStyleKitPropertyGroup, so recurse into it
1097 QObject *childObj = qvariant_cast<QObject *>(property(prop.name()));
1098 if (auto *child = qobject_cast<QQStyleKitPropertyGroup *>(childObj))
1099 child->emitChangedForAllStylePropertiesRecursive(emitFlags);
1100 continue;
1101 }
1102 }
1103
1104 if (!emitFlags.testFlag(EmitFlag::AllProperties)) {
1105 // Only emit for color properties when the Colors flag is set
1106 if (emitFlags.testFlag(EmitFlag::Colors)) {
1107 if (prop.metaType() != QMetaType::fromType<QColor>())
1108 continue;
1109 }
1110 }
1111
1112 // Emit the changed signal for the property
1113 Q_ASSERT(prop.hasNotifySignal());
1114 QMetaMethod notify = prop.notifySignal();
1115 notify.invoke(this, Qt::DirectConnection);
1116 }
1117}
1118
1119bool QQStyleKitPropertyGroup::shouldEmitLocally()
1120{
1121 return !controlProperties()->asQQStyleKitReader()->dontEmitChangedSignals();
1122}
1123
1124bool QQStyleKitPropertyGroup::shouldEmitGlobally()
1125{
1126 QQStyleKitStyle *parentStyle = controlProperties()->style();
1127 if (!parentStyle)
1128 return false;
1129
1130 if (parentStyle->loaded() && !parentStyle->m_isUpdatingPalette) {
1131 /* When a property has changed in the 'global' QQStyleKitStyle itself, it can
1132 * potentially affect all control instances. We therefore need to go through all
1133 * QQStyleKitReaders and inform that their own local property that matches the
1134 * 'global' property needs to be re-read. We emit the signals directly, omitting any
1135 * applied transitions in the QQStyleKitReaders, to optimize for speed. The exception
1136 * is if we're just updating the palette in the Style to match the palette in the current
1137 * control / QQStyleKitReader. Such a change will only affect a single control. */
1138 return parentStyle == QQStyleKitStyle::current();
1139 }
1140 return false;
1141}
1142
1143// ************* QQStyleKitImageProperties ****************
1144
1145QQStyleKitImageProperties::QQStyleKitImageProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1146 : QQStyleKitPropertyGroup(group, parent)
1147{
1148}
1149
1150template <typename... CHANGED_SIGNALS>
1151void QQStyleKitImageProperties::emitGlobally(
1152 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1153{
1154 // Go through all instances of QQStyleKitImageProperties
1155 const QQStyleKitControlProperties *cp = controlProperties();
1156 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->image());
1157 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->image());
1158 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->image());
1159 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->image());
1160}
1161
1162QUrl QQStyleKitImageProperties::source() const
1163{
1164 return styleProperty<QUrl>(QQSK::Property::Source);
1165}
1166
1167void QQStyleKitImageProperties::setSource(const QUrl &source)
1168{
1169 if (setStyleProperty(QQSK::Property::Source, source))
1170 handleStylePropertyChanged(&QQStyleKitImageProperties::sourceChanged);
1171}
1172
1173QColor QQStyleKitImageProperties::color() const
1174{
1175 return styleProperty<QColor>(QQSK::Property::Color);
1176}
1177
1178void QQStyleKitImageProperties::setColor(const QColor &color)
1179{
1180 if (setStyleProperty(QQSK::Property::Color, color))
1181 handleStylePropertyChanged(&QQStyleKitImageProperties::colorChanged);
1182}
1183
1184QQuickImage::FillMode QQStyleKitImageProperties::fillMode() const
1185{
1186 return styleProperty<QQuickImage::FillMode>(QQSK::Property::FillMode);
1187}
1188
1189void QQStyleKitImageProperties::setFillMode(QQuickImage::FillMode fillMode)
1190{
1191 if (setStyleProperty(QQSK::Property::FillMode, fillMode))
1192 handleStylePropertyChanged(&QQStyleKitImageProperties::fillModeChanged);
1193}
1194
1195// ************* QQStyleKitBorderProperties ****************
1196
1197QQStyleKitBorderProperties::QQStyleKitBorderProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1198 : QQStyleKitPropertyGroup(group, parent)
1199{
1200}
1201
1202template <typename... CHANGED_SIGNALS>
1203void QQStyleKitBorderProperties::emitGlobally(
1204 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1205{
1206 // Go through all instances of QQStyleKitBorderProperties
1207 const QQStyleKitControlProperties *cp = controlProperties();
1208 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->border());
1209 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->border());
1210 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->border());
1211 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->border());
1212}
1213
1214qreal QQStyleKitBorderProperties::width() const
1215{
1216 return styleProperty<qreal>(QQSK::Property::Width);
1217}
1218
1219void QQStyleKitBorderProperties::setWidth(qreal width)
1220{
1221 if (setStyleProperty(QQSK::Property::Width, width))
1222 handleStylePropertyChanged(&QQStyleKitBorderProperties::widthChanged);
1223}
1224
1225QColor QQStyleKitBorderProperties::color() const
1226{
1227 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1228}
1229
1230void QQStyleKitBorderProperties::setColor(const QColor &color)
1231{
1232 if (setStyleProperty(QQSK::Property::Color, color))
1233 handleStylePropertyChanged(&QQStyleKitBorderProperties::colorChanged);
1234}
1235
1236// ************* QQStyleKitShadowProperties ****************
1237
1238QQStyleKitShadowProperties::QQStyleKitShadowProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1239 : QQStyleKitPropertyGroup(group, parent)
1240{
1241}
1242
1243template <typename... CHANGED_SIGNALS>
1244void QQStyleKitShadowProperties::emitGlobally(
1245 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1246{
1247 // Go through all instances of QQStyleKitShadowProperties
1248 const QQStyleKitControlProperties *cp = controlProperties();
1249 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->shadow());
1250 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->shadow());
1251 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->shadow());
1252 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->shadow());
1253}
1254
1255QColor QQStyleKitShadowProperties::color() const
1256{
1257 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1258}
1259
1260void QQStyleKitShadowProperties::setColor(QColor color)
1261{
1262 if (setStyleProperty(QQSK::Property::Color, color))
1263 handleStylePropertyChanged(&QQStyleKitShadowProperties::colorChanged);
1264}
1265
1266qreal QQStyleKitShadowProperties::opacity() const
1267{
1268 return styleProperty<qreal>(QQSK::Property::Opacity, 1.0);
1269}
1270
1271void QQStyleKitShadowProperties::setOpacity(qreal opacity)
1272{
1273 if (setStyleProperty(QQSK::Property::Opacity, opacity))
1274 handleStylePropertyChanged(&QQStyleKitShadowProperties::opacityChanged);
1275}
1276
1277qreal QQStyleKitShadowProperties::scale() const
1278{
1279 return styleProperty<qreal>(QQSK::Property::Scale, 1.0);
1280}
1281
1282void QQStyleKitShadowProperties::setScale(qreal scale)
1283{
1284 if (setStyleProperty(QQSK::Property::Scale, scale))
1285 handleStylePropertyChanged(&QQStyleKitShadowProperties::scaleChanged);
1286}
1287
1288qreal QQStyleKitShadowProperties::verticalOffset() const
1289{
1290 return styleProperty<qreal>(QQSK::Property::VOffset);
1291}
1292
1293void QQStyleKitShadowProperties::setVerticalOffset(qreal verticalOffset)
1294{
1295 if (setStyleProperty(QQSK::Property::VOffset, verticalOffset))
1296 handleStylePropertyChanged(&QQStyleKitShadowProperties::verticalOffsetChanged);
1297}
1298
1299qreal QQStyleKitShadowProperties::horizontalOffset() const
1300{
1301 return styleProperty<qreal>(QQSK::Property::HOffset);
1302}
1303
1304void QQStyleKitShadowProperties::setHorizontalOffset(qreal horizontalOffset)
1305{
1306 if (setStyleProperty(QQSK::Property::HOffset, horizontalOffset))
1307 handleStylePropertyChanged(&QQStyleKitShadowProperties::horizontalOffsetChanged);
1308}
1309
1310qreal QQStyleKitShadowProperties::blur() const
1311{
1312 return styleProperty<qreal>(QQSK::Property::Blur, 10.0);
1313}
1314
1315void QQStyleKitShadowProperties::setBlur(qreal blur)
1316{
1317 if (setStyleProperty(QQSK::Property::Blur, blur))
1318 handleStylePropertyChanged(&QQStyleKitShadowProperties::blurChanged);
1319}
1320
1321bool QQStyleKitShadowProperties::visible() const
1322{
1323 return styleProperty<bool>(QQSK::Property::Visible, true);
1324}
1325
1326void QQStyleKitShadowProperties::setVisible(bool visible)
1327{
1328 if (setStyleProperty(QQSK::Property::Visible, visible))
1329 handleStylePropertyChanged(&QQStyleKitShadowProperties::visibleChanged);
1330}
1331
1332QQmlComponent *QQStyleKitShadowProperties::delegate() const
1333{
1334 return styleProperty<QQmlComponent *>(QQSK::Property::Delegate);
1335}
1336
1337void QQStyleKitShadowProperties::setDelegate(QQmlComponent *delegate)
1338{
1339 if (setStyleProperty(QQSK::Property::Delegate, delegate))
1340 handleStylePropertyChanged(&QQStyleKitShadowProperties::delegateChanged);
1341}
1342
1343// ************* QQStyleKitDelegateProperties ****************
1344
1345QQStyleKitDelegateProperties::QQStyleKitDelegateProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1346 : QQStyleKitPropertyGroup(group, parent)
1347{
1348}
1349
1350template <typename... CHANGED_SIGNALS>
1351void QQStyleKitDelegateProperties::emitGlobally(
1352 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1353{
1354 // Go through all instances of QQStyleKitDelegateProperties
1355 const QQStyleKitControlProperties *cp = controlProperties();
1359 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground());
1360}
1361
1362qreal QQStyleKitDelegateProperties::radius() const
1363{
1364 return styleProperty<qreal>(QQSK::Property::Radius);
1365}
1366
1367void QQStyleKitDelegateProperties::setRadius(qreal radius)
1368{
1369 if (setStyleProperty(QQSK::Property::Radius, radius))
1370 handleStylePropertiesChanged<QQStyleKitDelegateProperties>(
1371 &QQStyleKitDelegateProperties::radiusChanged,
1372 &QQStyleKitDelegateProperties::topLeftRadiusChanged,
1373 &QQStyleKitDelegateProperties::topRightRadiusChanged,
1374 &QQStyleKitDelegateProperties::bottomLeftRadiusChanged,
1375 &QQStyleKitDelegateProperties::bottomRightRadiusChanged);
1376}
1377
1378qreal QQStyleKitDelegateProperties::topLeftRadius() const
1379{
1380 return styleProperty<qreal>(QQSK::Property::TopLeftRadius, QQSK::Property::Radius);
1381}
1382
1383void QQStyleKitDelegateProperties::setTopLeftRadius(qreal radius)
1384{
1385 if (setStyleProperty(QQSK::Property::TopLeftRadius, radius))
1386 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topLeftRadiusChanged);
1387}
1388
1389qreal QQStyleKitDelegateProperties::topRightRadius() const
1390{
1391 return styleProperty<qreal>(QQSK::Property::TopRightRadius, QQSK::Property::Radius);
1392}
1393
1394void QQStyleKitDelegateProperties::setTopRightRadius(qreal radius)
1395{
1396 if (setStyleProperty(QQSK::Property::TopRightRadius, radius))
1397 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topRightRadiusChanged);
1398}
1399
1400qreal QQStyleKitDelegateProperties::bottomLeftRadius() const
1401{
1402 return styleProperty<qreal>(QQSK::Property::BottomLeftRadius, QQSK::Property::Radius);
1403}
1404
1405void QQStyleKitDelegateProperties::setBottomLeftRadius(qreal radius)
1406{
1407 if (setStyleProperty(QQSK::Property::BottomLeftRadius, radius))
1408 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomLeftRadiusChanged);
1409}
1410
1411qreal QQStyleKitDelegateProperties::bottomRightRadius() const
1412{
1413 return styleProperty<qreal>(QQSK::Property::BottomRightRadius, QQSK::Property::Radius);
1414}
1415
1416void QQStyleKitDelegateProperties::setBottomRightRadius(qreal radius)
1417{
1418 if (setStyleProperty(QQSK::Property::BottomRightRadius, radius))
1419 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomRightRadiusChanged);
1420}
1421
1422qreal QQStyleKitDelegateProperties::scale() const
1423{
1424 return styleProperty<qreal>(QQSK::Property::Scale, 1.0);
1425}
1426
1427void QQStyleKitDelegateProperties::setScale(qreal scale)
1428{
1429 if (setStyleProperty(QQSK::Property::Scale, scale))
1430 handleStylePropertyChanged(&QQStyleKitDelegateProperties::scaleChanged);
1431}
1432
1433qreal QQStyleKitDelegateProperties::rotation() const
1434{
1435 return styleProperty<qreal>(QQSK::Property::Rotation);
1436}
1437
1438void QQStyleKitDelegateProperties::setRotation(qreal rotation)
1439{
1440 if (setStyleProperty(QQSK::Property::Rotation, rotation))
1441 handleStylePropertyChanged(&QQStyleKitDelegateProperties::rotationChanged);
1442}
1443
1444qreal QQStyleKitDelegateProperties::implicitWidth() const
1445{
1446 return styleProperty<qreal>(QQSK::Property::ImplicitWidth);
1447}
1448
1449void QQStyleKitDelegateProperties::setImplicitWidth(qreal width)
1450{
1451 if (setStyleProperty(QQSK::Property::ImplicitWidth, width))
1452 handleStylePropertyChanged(&QQStyleKitDelegateProperties::implicitWidthChanged);
1453}
1454
1455qreal QQStyleKitDelegateProperties::implicitHeight() const
1456{
1457 return styleProperty<qreal>(QQSK::Property::ImplicitHeight);
1458}
1459
1460void QQStyleKitDelegateProperties::setImplicitHeight(qreal height)
1461{
1462 if (setStyleProperty(QQSK::Property::ImplicitHeight, height))
1463 handleStylePropertyChanged(&QQStyleKitDelegateProperties::implicitHeightChanged);
1464}
1465
1466qreal QQStyleKitDelegateProperties::minimumWidth() const
1467{
1468 return styleProperty<qreal>(QQSK::Property::MinimumWidth);
1469}
1470
1471void QQStyleKitDelegateProperties::setMinimumWidth(qreal width)
1472{
1473 if (setStyleProperty(QQSK::Property::MinimumWidth, width))
1474 handleStylePropertyChanged(&QQStyleKitDelegateProperties::minimumWidthChanged);
1475}
1476
1477qreal QQStyleKitDelegateProperties::margins() const
1478{
1479 return styleProperty<qreal>(QQSK::Property::Margins);
1480}
1481
1482void QQStyleKitDelegateProperties::setMargins(qreal margins)
1483{
1484 if (setStyleProperty(QQSK::Property::Margins, margins))
1485 handleStylePropertiesChanged<QQStyleKitDelegateProperties>(
1486 &QQStyleKitDelegateProperties::marginsChanged,
1487 &QQStyleKitDelegateProperties::leftMarginChanged,
1488 &QQStyleKitDelegateProperties::rightMarginChanged,
1489 &QQStyleKitDelegateProperties::topMarginChanged,
1490 &QQStyleKitDelegateProperties::bottomMarginChanged);
1491}
1492
1493qreal QQStyleKitDelegateProperties::leftMargin() const
1494{
1495 return styleProperty<qreal>(QQSK::Property::LeftMargin, QQSK::Property::Margins);
1496}
1497
1498void QQStyleKitDelegateProperties::setLeftMargin(qreal margin)
1499{
1500 if (setStyleProperty(QQSK::Property::LeftMargin, margin))
1501 handleStylePropertyChanged(&QQStyleKitDelegateProperties::leftMarginChanged);
1502}
1503
1504qreal QQStyleKitDelegateProperties::rightMargin() const
1505{
1506 return styleProperty<qreal>(QQSK::Property::RightMargin, QQSK::Property::Margins);
1507}
1508
1509void QQStyleKitDelegateProperties::setRightMargin(qreal margin)
1510{
1511 if (setStyleProperty(QQSK::Property::RightMargin, margin))
1512 handleStylePropertyChanged(&QQStyleKitDelegateProperties::rightMarginChanged);
1513}
1514
1515qreal QQStyleKitDelegateProperties::topMargin() const
1516{
1517 return styleProperty<qreal>(QQSK::Property::TopMargin, QQSK::Property::Margins);
1518}
1519
1520void QQStyleKitDelegateProperties::setTopMargin(qreal margin)
1521{
1522 if (setStyleProperty(QQSK::Property::TopMargin, margin))
1523 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topMarginChanged);
1524}
1525
1526qreal QQStyleKitDelegateProperties::bottomMargin() const
1527{
1528 return styleProperty<qreal>(QQSK::Property::BottomMargin, QQSK::Property::Margins);
1529}
1530
1531void QQStyleKitDelegateProperties::setBottomMargin(qreal margin)
1532{
1533 if (setStyleProperty(QQSK::Property::BottomMargin, margin))
1534 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomMarginChanged);
1535}
1536
1537Qt::Alignment QQStyleKitDelegateProperties::alignment() const
1538{
1539 return styleProperty<Qt::Alignment>(QQSK::Property::Alignment, Qt::AlignLeft | Qt::AlignVCenter);
1540}
1541
1542void QQStyleKitDelegateProperties::setAlignment(Qt::Alignment alignment)
1543{
1544 if (setStyleProperty(QQSK::Property::Alignment, alignment))
1545 handleStylePropertyChanged(&QQStyleKitDelegateProperties::alignmentChanged);
1546}
1547
1548qreal QQStyleKitDelegateProperties::opacity() const
1549{
1550 return styleProperty<qreal>(QQSK::Property::Opacity, 1.0);
1551}
1552
1553void QQStyleKitDelegateProperties::setOpacity(qreal opacity)
1554{
1555 if (setStyleProperty(QQSK::Property::Opacity, opacity))
1556 handleStylePropertyChanged(&QQStyleKitDelegateProperties::opacityChanged);
1557}
1558
1559QColor QQStyleKitDelegateProperties::color() const
1560{
1561 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1562}
1563
1564void QQStyleKitDelegateProperties::setColor(const QColor &color)
1565{
1566 if (setStyleProperty(QQSK::Property::Color, color))
1567 handleStylePropertyChanged(&QQStyleKitDelegateProperties::colorChanged);
1568}
1569
1570bool QQStyleKitDelegateProperties::visible() const
1571{
1572 return styleProperty<bool>(QQSK::Property::Visible, true);
1573}
1574
1575void QQStyleKitDelegateProperties::setVisible(bool visible)
1576{
1577 if (setStyleProperty(QQSK::Property::Visible, visible))
1578 handleStylePropertyChanged(&QQStyleKitDelegateProperties::visibleChanged);
1579}
1580
1581bool QQStyleKitDelegateProperties::clip() const
1582{
1583 return styleProperty<bool>(QQSK::Property::Clip, false);
1584}
1585
1586void QQStyleKitDelegateProperties::setClip(bool clip)
1587{
1588 if (setStyleProperty(QQSK::Property::Clip, clip))
1589 handleStylePropertyChanged(&QQStyleKitDelegateProperties::clipChanged);
1590}
1591
1592QQuickGradient *QQStyleKitDelegateProperties::gradient() const
1593{
1594 return styleProperty<QQuickGradient *>(QQSK::Property::Gradient);
1595}
1596
1597void QQStyleKitDelegateProperties::setGradient(QQuickGradient *gradient)
1598{
1599 if (setStyleProperty(QQSK::Property::Gradient, gradient))
1600 handleStylePropertyChanged(&QQStyleKitDelegateProperties::gradientChanged);
1601}
1602
1603QObject *QQStyleKitDelegateProperties::data() const
1604{
1605 return styleProperty<QObject *>(QQSK::Property::Data);
1606}
1607
1608void QQStyleKitDelegateProperties::setData(QObject *data)
1609{
1610 if (setStyleProperty(QQSK::Property::Data, data))
1611 handleStylePropertyChanged(&QQStyleKitDelegateProperties::dataChanged);
1612}
1613
1614QQmlComponent *QQStyleKitDelegateProperties::delegate() const
1615{
1616 return styleProperty<QQmlComponent *>(QQSK::Property::Delegate);
1617}
1618
1619void QQStyleKitDelegateProperties::setDelegate(QQmlComponent *delegate)
1620{
1621 if (setStyleProperty(QQSK::Property::Delegate, delegate))
1622 handleStylePropertyChanged(&QQStyleKitDelegateProperties::delegateChanged);
1623}
1624
1625QQStyleKitBorderProperties *QQStyleKitDelegateProperties::border() const
1626{
1627 return lazyCreateGroup(m_border, QQSK::PropertyGroup::Border);
1628}
1629
1630QQStyleKitShadowProperties *QQStyleKitDelegateProperties::shadow() const
1631{
1632 return lazyCreateGroup(m_shadow, QQSK::PropertyGroup::Shadow);
1633}
1634
1635QQStyleKitImageProperties *QQStyleKitDelegateProperties::image() const
1636{
1637 return lazyCreateGroup(m_image, QQSK::PropertyGroup::Image);
1638}
1639
1640// ************* QQStyleKitHandleProperties ****************
1641
1642QQStyleKitHandleProperties::QQStyleKitHandleProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1643 : QQStyleKitDelegateProperties(group, parent)
1644{
1645}
1646
1647QQStyleKitDelegateProperties *QQStyleKitHandleProperties::first() const
1648{
1649 return lazyCreateGroup(m_first, QQSK::PropertyGroup::DelegateSubtype1);
1650}
1651
1652QQStyleKitDelegateProperties *QQStyleKitHandleProperties::second() const
1653{
1654 return lazyCreateGroup(m_second, QQSK::PropertyGroup::DelegateSubtype2);
1655}
1656
1657// ************* QQStyleKitIndicatorProperties ****************
1658
1659QQStyleKitIndicatorProperties::QQStyleKitIndicatorProperties(
1660 QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1661 : QQStyleKitDelegateProperties(group, parent)
1662{
1663}
1664
1665template <typename... CHANGED_SIGNALS>
1667 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1668{
1669 // Go through all instances of QQStyleKitIndicatorProperties
1670 const QQStyleKitControlProperties *cp = controlProperties();
1671 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->first());
1672 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->second());
1673}
1674
1675QQStyleKitDelegateProperties *QQStyleKitIndicatorProperties::foreground() const
1676{
1677 return lazyCreateGroup(m_foreground, QQSK::PropertyGroup::Foreground);
1678}
1679
1680// ************* QQStyleKitIndicatorWithSubTypes ****************
1681
1682QQStyleKitIndicatorWithSubTypes::QQStyleKitIndicatorWithSubTypes(
1683 QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1684 : QQStyleKitDelegateProperties(group, parent)
1685{
1686}
1687
1688template <typename... CHANGED_SIGNALS>
1690 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1691{
1692 // Go through all instances of QQStyleKitIndicatorWithSubTypes
1693 const QQStyleKitControlProperties *cp = controlProperties();
1695}
1696
1697QQStyleKitDelegateProperties *QQStyleKitIndicatorWithSubTypes::foreground() const
1698{
1699 return lazyCreateGroup(m_foreground, QQSK::PropertyGroup::Foreground);
1700}
1701
1706
1711
1713{
1714 return lazyCreateGroup(m_first, QQSK::PropertyGroup::DelegateSubtype1);
1715}
1716
1718{
1719 return lazyCreateGroup(m_second, QQSK::PropertyGroup::DelegateSubtype2);
1720}
1721
1722// ************* QQStyleKitTextProperties ****************
1723QQStyleKitTextProperties::QQStyleKitTextProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1724 : QQStyleKitPropertyGroup(group, parent)
1725{
1726}
1727
1728template <typename... CHANGED_SIGNALS>
1730 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1731{
1732 const QQStyleKitControlProperties *cp = controlProperties();
1734}
1735
1737{
1738 return styleProperty<QColor>(QQSK::Property::Color);
1739}
1740
1741void QQStyleKitTextProperties::setColor(const QColor &color)
1742{
1743 if (setStyleProperty(QQSK::Property::Color, color))
1744 handleStylePropertyChanged(&QQStyleKitTextProperties::colorChanged);
1745}
1746
1748{
1749 return styleProperty<Qt::Alignment>(QQSK::Property::Alignment);
1750}
1751
1752void QQStyleKitTextProperties::setAlignment(Qt::Alignment alignment)
1753{
1754 if (setStyleProperty(QQSK::Property::Alignment, alignment))
1755 handleStylePropertyChanged(&QQStyleKitTextProperties::alignmentChanged);
1756}
1757
1759{
1760 return styleProperty<bool>(QQSK::Property::Bold, false);
1761}
1762
1764{
1765 if (setStyleProperty(QQSK::Property::Bold, bold))
1766 handleStylePropertyChanged(&QQStyleKitTextProperties::boldChanged);
1767}
1768
1770{
1771 return styleProperty<bool>(QQSK::Property::Italic, false);
1772}
1773
1775{
1776 if (setStyleProperty(QQSK::Property::Italic, italic))
1777 handleStylePropertyChanged(&QQStyleKitTextProperties::italicChanged);
1778}
1779
1781{
1782 return styleProperty<qreal>(QQSK::Property::PointSize);
1783}
1784
1786{
1787 if (setStyleProperty(QQSK::Property::PointSize, pointSize))
1788 handleStylePropertyChanged(&QQStyleKitTextProperties::pointSizeChanged);
1789}
1790
1792{
1793 return styleProperty<qreal>(QQSK::Property::Padding);
1794}
1795
1806
1808{
1809 return styleProperty<qreal>(QQSK::Property::LeftPadding, QQSK::Property::Padding);
1810}
1811
1813{
1814 if (setStyleProperty(QQSK::Property::LeftPadding, padding))
1815 handleStylePropertyChanged(&QQStyleKitTextProperties::leftPaddingChanged);
1816}
1817
1819{
1820 return styleProperty<qreal>(QQSK::Property::RightPadding, QQSK::Property::Padding);
1821}
1822
1824{
1825 if (setStyleProperty(QQSK::Property::RightPadding, padding))
1826 handleStylePropertyChanged(&QQStyleKitTextProperties::rightPaddingChanged);
1827}
1828
1830{
1831 return styleProperty<qreal>(QQSK::Property::TopPadding, QQSK::Property::Padding);
1832}
1833
1835{
1836 if (setStyleProperty(QQSK::Property::TopPadding, padding))
1837 handleStylePropertyChanged(&QQStyleKitTextProperties::topPaddingChanged);
1838}
1839
1841{
1842 return styleProperty<qreal>(QQSK::Property::BottomPadding, QQSK::Property::Padding);
1843}
1844
1846{
1847 if (setStyleProperty(QQSK::Property::BottomPadding, padding))
1848 handleStylePropertyChanged(&QQStyleKitTextProperties::bottomPaddingChanged);
1849}
1850
1851// ************* QQStyleKitControlProperties ****************
1852
1853QQStyleKitControlProperties::QQStyleKitControlProperties(QQSK::PropertyGroup group, QObject *parent)
1854 : QQStyleKitPropertyGroup(group, parent)
1855{
1856 /* Calculate the free space storage ID space that can accommodate all unique style
1857 * properties that may be applied to a control. Since we'll prepend different states
1858 * and subtypes during the property propagation lookup phase later, we need to reserve
1859 * ID space for them both already now. More docs about the property space is written in
1860 * the implementation of PropertyPathId. */
1861 m_groupSpace.size = nestedGroupsStartSize;
1862 m_groupSpace.start = 0;
1863
1864 if (group == QQSK::PropertyGroup::GlobalFlag) {
1865 /* A property path may include pseudo-groups that offers a convenient API for
1866 * reading properties with specific options applied. The 'global' group is one such
1867 * pseudo-group. When it is prefixed to a property path, it indicates that the property
1868 * should be read directly from the style, bypassing any active transitions that might
1869 * otherwise affect its value.
1870 * Note: The global group should be ignored when computing a PropertyPathId_t, as it
1871 * only affect _where_ the property should be read from, not its ID. */
1872 m_pathFlags.setFlag(QQSK::PropertyPathFlag::Global);
1873 }
1874}
1875
1876QQStyleKitStyle *QQStyleKitControlProperties::style() const
1877{
1878 if (subclass() == QQSK::Subclass::QQStyleKitState) {
1879 /* A QQStyleKitControlState (and its subclasses) should always be a (grand)child of a
1880 * QQStyleKitStyle. And it belongs to that style, even it that style is not the
1881 * currently active application style. This is opposed to a QQStyleKitReader,
1882 * that normally belongs / communicates with the currently active style.
1883 * NOTE: a style can also be a fallback style for another style (which can be recursive,
1884 * meaning that a fallback style can also have its own fallback style, and so on). But
1885 * this function will return the nearest style, and not the root style */
1886 QObject *obj = parent();
1887 while (obj && !obj->metaObject()->inherits(&QQStyleKitStyle::staticMetaObject))
1888 obj = obj->parent();
1889 return obj ? static_cast<QQStyleKitStyle *>(obj) : nullptr;
1890 }
1891
1892 if (subclass() == QQSK::Subclass::QQStyleKitReader) {
1893 const auto *reader = static_cast<const QQStyleKitReader *>(this);
1894 if (reader->m_explicitStyle)
1895 return reader->m_explicitStyle;
1896 }
1897
1898 // For a QQStyleKitReader without an explicit style, we return the currently active style for now
1899 return QQStyleKitStyle::current();
1900}
1901
1902QQSK::Subclass QQStyleKitControlProperties::subclass() const
1903{
1904 /* QQStyleKitControlProperties is subclassed by several different classes in this
1905 * framework. As such, it's basically just an interface because it only declares the
1906 * different properties that can be read or written to in a QQStyleKitStyle, such as
1907 * hovered.background.color or pressed.indicator.foreground.color. It says nothing
1908 * about how those properties are stored, instead that is up to each individual
1909 * subclass to decide */
1910 if (metaObject()->inherits(&QQStyleKitReader::staticMetaObject))
1911 return QQSK::Subclass::QQStyleKitReader;
1912 if (metaObject()->inherits(&QQStyleKitControlState::staticMetaObject))
1913 return QQSK::Subclass::QQStyleKitState;
1914 Q_UNREACHABLE();
1915}
1916
1917QQStyleKitReader *QQStyleKitControlProperties::asQQStyleKitReader() const
1918{
1919 Q_ASSERT(subclass() == QQSK::Subclass::QQStyleKitReader);
1920 return static_cast<QQStyleKitReader *>(const_cast<QQStyleKitControlProperties *>(this));
1921}
1922
1923QQStyleKitControlState *QQStyleKitControlProperties::asQQStyleKitState() const
1924{
1925 Q_ASSERT(subclass() == QQSK::Subclass::QQStyleKitState);
1926 Q_ASSERT(metaObject()->inherits(&QQStyleKitControlState::staticMetaObject));
1927 return static_cast<QQStyleKitControlState *>(const_cast<QQStyleKitControlProperties *>(this));
1928}
1929
1930void QQStyleKitControlProperties::forEachUsedDelegate(
1931 std::function<void (QQStyleKitDelegateProperties *, QQSK::Delegate, const QString &)> f)
1932{
1933 // If adding more delegates here, remember to keep StyleAnimation.qml in sync
1934 if (m_background)
1935 f(m_background, QQSK::Delegate::Background, "background"_L1);
1936
1937 if (m_indicator) {
1938 f(m_indicator, QQSK::Delegate::Indicator, "indicator"_L1);
1939 if (m_indicator->m_foreground)
1940 f(m_indicator->m_foreground, QQSK::Delegate::IndicatorForeground, "indicator.foreground"_L1);
1941 if (m_indicator->m_first) {
1942 f(m_indicator->m_first, QQSK::Delegate::IndicatorFirst, "indicator.first"_L1);
1943 if (m_indicator->m_first->m_foreground)
1944 f(m_indicator->m_first->m_foreground, QQSK::Delegate::IndicatorFirstForeground, "indicator.first.foreground"_L1);
1945 }
1946 if (m_indicator->m_second) {
1947 f(m_indicator->m_second, QQSK::Delegate::IndicatorSecond, "indicator.second"_L1);
1948 if (m_indicator->m_second->m_foreground)
1949 f(m_indicator->m_second->m_foreground, QQSK::Delegate::IndicatorSecondForeground, "indicator.second.foreground"_L1);
1950 }
1951 }
1952
1953 if (m_handle) {
1954 f(m_handle, QQSK::Delegate::Handle, "handle"_L1);
1955 if (m_handle->m_first)
1956 f(m_handle->m_first, QQSK::Delegate::HandleFirst, "handle.first"_L1);
1957 if (m_handle->m_second)
1958 f(m_handle->m_second, QQSK::Delegate::HandleSecond, "handle.second"_L1);
1959 }
1960}
1961
1962void QQStyleKitControlProperties::emitChangedForAllStyleProperties(EmitFlags emitFlags)
1963{
1964 /* This brute-force function will emit update signals for _all_ style properties
1965 * in the QQStyleKitStyle API. Doing so is typically needed after a style-, or theme
1966 * change, as we don't know which properties are affected by such a big change. */
1967 if (emitFlags.testFlag(EmitFlag::AllProperties)) {
1968 emit leftPaddingChanged();
1969 emit rightPaddingChanged();
1970 emit topPaddingChanged();
1971 emit bottomPaddingChanged();
1972 emit spacingChanged();
1973 emit transitionChanged();
1974 emit textChanged();
1975 }
1976
1977 forEachUsedDelegate([=](QQStyleKitDelegateProperties *delegate, QQSK::Delegate, const QString &){
1978 delegate->emitChangedForAllStylePropertiesRecursive(emitFlags);
1979 });
1980}
1981
1982template <typename... CHANGED_SIGNALS>
1983void QQStyleKitControlProperties::emitGlobally(
1984 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1985{
1986 for (QQStyleKitReader *reader : QQStyleKitReader::s_allReaders) {
1987 if (reader->controlType() != controlType)
1988 continue;
1989 ((reader->*changedSignals)(), ...);
1990 }
1991}
1992
1993qreal QQStyleKitControlProperties::spacing() const
1994{
1995 return styleProperty<qreal>(QQSK::Property::Spacing);
1996}
1997
1998void QQStyleKitControlProperties::setSpacing(qreal spacing)
1999{
2000 if (setStyleProperty(QQSK::Property::Spacing, spacing))
2001 handleStylePropertyChanged(&QQStyleKitControlProperties::spacingChanged);
2002}
2003
2004qreal QQStyleKitControlProperties::padding() const
2005{
2006 return styleProperty<qreal>(QQSK::Property::Padding);
2007}
2008
2009void QQStyleKitControlProperties::setPadding(qreal padding)
2010{
2011 if (setStyleProperty(QQSK::Property::Padding, padding))
2012 handleStylePropertiesChanged<QQStyleKitControlProperties>(
2013 &QQStyleKitControlProperties::paddingChanged,
2014 &QQStyleKitControlProperties::leftPaddingChanged,
2015 &QQStyleKitControlProperties::rightPaddingChanged,
2016 &QQStyleKitControlProperties::topPaddingChanged,
2017 &QQStyleKitControlProperties::bottomPaddingChanged);
2018}
2019
2020qreal QQStyleKitControlProperties::leftPadding() const
2021{
2022 return styleProperty<qreal>(QQSK::Property::LeftPadding, QQSK::Property::Padding);
2023}
2024
2025void QQStyleKitControlProperties::setLeftPadding(qreal leftPadding)
2026{
2027 if (setStyleProperty(QQSK::Property::LeftPadding, leftPadding))
2028 handleStylePropertyChanged(&QQStyleKitControlProperties::leftPaddingChanged);
2029}
2030
2031qreal QQStyleKitControlProperties::rightPadding() const
2032{
2033 return styleProperty<qreal>(QQSK::Property::RightPadding, QQSK::Property::Padding);
2034}
2035
2036void QQStyleKitControlProperties::setRightPadding(qreal rightPadding)
2037{
2038 if (setStyleProperty(QQSK::Property::RightPadding, rightPadding))
2039 handleStylePropertyChanged(&QQStyleKitControlProperties::rightPaddingChanged);
2040}
2041
2042qreal QQStyleKitControlProperties::topPadding() const
2043{
2044 return styleProperty<qreal>(QQSK::Property::TopPadding, QQSK::Property::Padding);
2045}
2046
2047void QQStyleKitControlProperties::setTopPadding(qreal topPadding)
2048{
2049 if (setStyleProperty(QQSK::Property::TopPadding, topPadding))
2050 handleStylePropertyChanged(&QQStyleKitControlProperties::topPaddingChanged);
2051}
2052
2053qreal QQStyleKitControlProperties::bottomPadding() const
2054{
2055 return styleProperty<qreal>(QQSK::Property::BottomPadding, QQSK::Property::Padding);
2056}
2057
2058void QQStyleKitControlProperties::setBottomPadding(qreal bottomPadding)
2059{
2060 if (setStyleProperty(QQSK::Property::BottomPadding, bottomPadding))
2061 handleStylePropertyChanged(&QQStyleKitControlProperties::bottomPaddingChanged);
2062}
2063
2064QQuickTransition *QQStyleKitControlProperties::transition() const
2065{
2066 return styleProperty<QQuickTransition *>(QQSK::Property::Transition);
2067}
2068
2069void QQStyleKitControlProperties::setTransition(QQuickTransition *transition)
2070{
2071 if (setStyleProperty(QQSK::Property::Transition, transition))
2072 handleStylePropertyChanged(&QQStyleKitControlProperties::transitionChanged);
2073}
2074
2075QQStyleKitTextProperties *QQStyleKitControlProperties::text() const
2076{
2077 return lazyCreateGroup(m_text, QQSK::PropertyGroup::Text);
2078}
2079
2080QQStyleKitDelegateProperties *QQStyleKitControlProperties::background() const
2081{
2082 return lazyCreateGroup(m_background, QQSK::PropertyGroup::Background);
2083}
2084
2085QQStyleKitHandleProperties *QQStyleKitControlProperties::handle() const
2086{
2087 return lazyCreateGroup(m_handle, QQSK::PropertyGroup::Handle);
2088}
2089
2090QQStyleKitIndicatorWithSubTypes *QQStyleKitControlProperties::indicator() const
2091{
2092 return lazyCreateGroup(m_indicator, QQSK::PropertyGroup::Indicator);
2093}
2094
2095QT_END_NAMESPACE
2096
2097#include "moc_qqstylekitcontrolproperties_p.cpp"
QQStyleKitDelegateProperties * first() const
QQStyleKitDelegateProperties * second() const
QQStyleKitDelegateProperties * foreground() const
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
QQStyleKitDelegateProperties * foreground() const
QQStyleKitIndicatorProperties * down() const
QQStyleKitIndicatorProperties * up() const
QQStyleKitIndicatorProperties * second() const
QQStyleKitIndicatorProperties * first() const
void emitChangedForAllStylePropertiesRecursive(EmitFlags emitFlags)
T * lazyCreateGroup(T *const &ptr, QQSK::PropertyGroup group) const
void handleStylePropertyChanged(void(SUBCLASS::*changedSignal)())
void handleStylePropertiesChanged(CHANGED_SIGNALS... changedSignals)
QQStyleKitControlProperties * controlProperties() const
void setBottomPadding(qreal bottomPadding)
void emitGlobally(QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
Combined button and popup list for selecting options.
#define CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(CONTROL_PROPERTIES, GROUP_PATH)