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::up}{indicator.up} and
665 \l {IndicatorStyle::down}{indicator.down} in controls
666 like \l [QtQuickControls]{SpinBox}.
667 It is equivalent to \l IndicatorStyle, but does not itself
668 contain sub-indicators.
669
670 \labs
671
672 \sa IndicatorStyle, DelegateStyle, ControlStyle, ControlStateStyle,
673 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
674*/
675
676/*!
677 \qmlproperty DelegateStyle SubIndicatorStyle::foreground
678
679 Grouped property for styling the foreground element of this
680 indicator. The foreground typically represents a checkmark, icon
681 or arrow rendered inside the indicator.
682*/
683
684// ************* IndicatorStyle ****************
685
686/*!
687 \qmltype IndicatorStyle
688 \inqmlmodule Qt.labs.StyleKit
689 \inherits DelegateStyle
690 \brief Defines the style for a control's indicator.
691
692 IndicatorStyle extends \l DelegateStyle with properties that are specific to
693 styling an indicator.
694
695 The IndicatorStyle itself describes the indicator background, while the
696 \l foreground describes the content drawn inside it. For example,
697 \c {checkBox.indicator} styles the check box frame and
698 \c {checkBox.indicator.foreground} styles the check mark. For
699 \l {AbstractStylableControls::}{switchControl},
700 \l {AbstractStylableControls::}{slider} and
701 \l {AbstractStylableControls::}{progressBar}, the indicator styles
702 the groove and the foreground styles the fill.
703
704 \snippet DelegateStyle_indicator.qml checkBox
705
706 Some controls have more than one indicator. For example,
707 \l [QtQuickControls]{SpinBox} has both an increment and a decrement
708 button. These can be styled independently using the \l up and \l down
709 sub-indicators, \c {spinBox.indicator.up} and
710 \c {spinBox.indicator.down}. Properties not set on a sub-indicator
711 fall back to the indicator itself.
712
713 \snippet DelegateStyle_indicator.qml up and down indicator
714
715 \labs
716
717 \sa SubIndicatorStyle, DelegateStyle, ControlStyle, ControlStateStyle,
718 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
719*/
720
721/*!
722 \qmlproperty SubIndicatorStyle IndicatorStyle::down
723
724 Grouped property for styling the down (decrement) sub-indicator.
725 This is used by controls such as \l [QtQuickControls]{SpinBox}.
726 Unset properties fall back to the indicator itself.
727
728 \sa up
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::up
747
748 Grouped property for styling the up (increment) sub-indicator.
749 This is used by controls such as \l [QtQuickControls]{SpinBox}.
750 Unset properties fall back to the indicator itself.
751
752 \sa down
753*/
754
755// ************* TextStyle ****************
756
757/*!
758 \qmltype TextStyle
759 \inqmlmodule Qt.labs.StyleKit
760 \brief Defines the text style for a control's label.
761
762 TextStyle provides properties for controlling the appearance of
763 text labels within a control, such as
764 \l color, \l alignment and \l padding,
765 and certain font-related properties such as
766 \l {TextStyle::}{bold},
767 \l {TextStyle::}{italic}, and
768 \l {TextStyle::pointSize}{font size}.
769
770 It is available as the \l {ControlStyleProperties::text}{text}
771 grouped property on every \l ControlStateStyle.
772
773 \labs
774
775 \sa DelegateStyle, ControlStyle, ControlStateStyle,
776 {qtlabsstylekit-fallbackstyle.html}{FallbackStyle Reference}
777*/
778
779/*!
780 \qmlproperty Qt::Alignment TextStyle::alignment
781
782 The alignment of the text within its available area.
783*/
784
785/*!
786 \qmlproperty bool TextStyle::bold
787
788 Whether the text should be rendered in bold. The default value
789 is \c false.
790
791 \sa italic
792*/
793
794/*!
795 \qmlproperty real TextStyle::bottomPadding
796
797 The bottom padding around the text. If not set, falls back to
798 \l padding.
799
800 \sa padding, topPadding, leftPadding, rightPadding
801*/
802
803/*!
804 \qmlproperty color TextStyle::color
805
806 The color of the text.
807*/
808
809/*!
810 \qmlproperty bool TextStyle::italic
811
812 Whether the text should be rendered in italic. The default value
813 is \c false.
814
815 \sa bold
816*/
817
818/*!
819 \qmlproperty real TextStyle::leftPadding
820
821 The left padding around the text. If not set, falls back to
822 \l padding.
823
824 \sa padding, rightPadding, topPadding, bottomPadding
825*/
826
827/*!
828 \qmlproperty real TextStyle::padding
829
830 The uniform padding around the text. Setting this provides a
831 default value for \l leftPadding, \l rightPadding, \l topPadding,
832 and \l bottomPadding. Each side can be overridden individually.
833
834 \sa leftPadding, rightPadding, topPadding, bottomPadding
835*/
836
837/*!
838 \qmlproperty real TextStyle::pointSize
839
840 The point size of the text font.
841*/
842
843/*!
844 \qmlproperty real TextStyle::rightPadding
845
846 The right padding around the text. If not set, falls back to
847 \l padding.
848
849 \sa padding, leftPadding, topPadding, bottomPadding
850*/
851
852/*!
853 \qmlproperty real TextStyle::topPadding
854
855 The top padding around the text. If not set, falls back to
856 \l padding.
857
858 \sa padding, bottomPadding, leftPadding, rightPadding
859*/
860
861// ************* QQStyleKitPropertyGroup ****************
862
863QHash<PropertyPathId_t, QString> QQStyleKitPropertyGroup::s_pathStrings;
864
865QQStyleKitPropertyGroup::QQStyleKitPropertyGroup(QQSK::PropertyGroup, QObject *parent)
866 : QObject(parent)
867{
868}
869
870PropertyPathId QQStyleKitPropertyGroup::propertyPathId(QQSK::Property property, PropertyPathId::Flag flag) const
871{
872 if (flag == PropertyPathId::Flag::IncludeSubtype) {
873 if (m_pathFlags.testFlag(QQSK::PropertyPathFlag::DelegateSubtype1))
874 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype1);
875 else if (m_pathFlags.testFlag(QQSK::PropertyPathFlag::DelegateSubtype2))
876 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype2);
877 }
878 return PropertyPathId(property, m_groupSpace.start, QQSK::PropertyGroup::DelegateSubtype0);
879}
880
882{
883 /* Start from the root of the path and build the path down to this group. This
884 * mirrors how the groups were originally created and avoids rounding issues
885 * that can arise if attempting to reconstruct the path “backwards”.
886 * Note: For each group, m_groupSpace.start is stored relative to the root,
887 * while m_groupSpace.size is relative to the parent group. However, when
888 * calculating the group index, the group-space start must be computed
889 * relative to the parent group.
890 * We cache the requested paths, as the same paths are typically requested
891 * repeatedly. The number of possible paths (and thus leaf groups) is well below
892 * 100, and in practice the cache usually ends up with fewer than 20 entries. */
893 if (s_pathStrings.contains(m_groupSpace.start))
894 return s_pathStrings[m_groupSpace.start];
895
896 constexpr PropertyPathId_t rootGroupsSize = nestedGroupsStartSize / nestedGroupCount;
897 const auto metaEnum = QMetaEnum::fromType<QQSK::PropertyGroup>();
898
899 PropertyPathId_t nestedGroupStart = m_groupSpace.start;
900 PropertyPathId_t nestedGroupSize = rootGroupsSize;
901 PropertyPathId_t nestedGroupIndex = nestedGroupStart / nestedGroupSize;
902 auto groupType = QQSK::PropertyGroup(nestedGroupIndex);
903 if (groupType == QQSK::PropertyGroup::Control)
904 return {};
905
906 QString groupName = QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(groupType)));
907 groupName[0] = groupName[0].toLower();
908 QString pathString = groupName;
909
910 while (true) {
911 nestedGroupStart -= nestedGroupIndex * nestedGroupSize;
912 nestedGroupSize /= nestedGroupCount;
913 nestedGroupIndex = nestedGroupStart / nestedGroupSize;
914 groupType = QQSK::PropertyGroup(nestedGroupIndex);
915 if (groupType == QQSK::PropertyGroup::Control)
916 break;
917
918 QString groupName = QString::fromLatin1(metaEnum.valueToKey(static_cast<int>(groupType)));
919 groupName[0] = groupName[0].toLower();
920 pathString += '.'_L1 + groupName;
921 }
922
923 s_pathStrings.insert(m_groupSpace.start, pathString);
924 return pathString;
925}
926
927QQStyleKitControlProperties *QQStyleKitPropertyGroup::controlProperties() const
928{
930 Q_ASSERT(qobject_cast<const QQStyleKitControlProperties *>(this));
931 auto *self = const_cast<QQStyleKitPropertyGroup *>(this);
932 return static_cast<QQStyleKitControlProperties *>(self);
933 }
934 Q_ASSERT(qobject_cast<const QQStyleKitControlProperties *>(parent()));
935 return static_cast<QQStyleKitControlProperties *>(parent());
936}
937
938template<typename T>
939T *QQStyleKitPropertyGroup::lazyCreateGroup(T * const &ptr, QQSK::PropertyGroup group) const
940{
941 T *nestedGroup = QQSK::lazyCreate(ptr, controlProperties(), group);
942
943 // Nested groups inherit path flags from their parents
944 nestedGroup->m_pathFlags = m_pathFlags;
945
946 if (group == QQSK::PropertyGroup::DelegateSubtype1) {
947 /* Subtypes, like states, are not part of a property's path ID—they belong to the
948 * storage ID instead. They are therefore prefixed later, during lookup, when
949 * propagation determines which value to read.
950 * For now, we simply record which subtype this group (and any nested groups) is
951 * associated with. The subtype will then be taken into account later when reading
952 * properties from the group. Setting aside space for the sub types was already
953 * taken care of during the construction of the root QQStyleKitControlProperties. */
954 nestedGroup->m_pathFlags.setFlag(QQSK::PropertyPathFlag::DelegateSubtype1);
955 nestedGroup->m_groupSpace = m_groupSpace;
956 } else if (group == QQSK::PropertyGroup::DelegateSubtype2) {
957 nestedGroup->m_pathFlags.setFlag(QQSK::PropertyPathFlag::DelegateSubtype2);
958 nestedGroup->m_groupSpace = m_groupSpace;
959 } else {
960 /* Calculate the available property ID space for the nested group. This is done by
961 * dividing the available space inside _this_ group on the number of potential groups
962 * that _this_ group can potentially contain. */
963 const PropertyPathId_t nestedGroupIndex = PropertyPathId_t(group);
964 const PropertyPathId_t nestedGroupSize = m_groupSpace.size / nestedGroupCount;
965 nestedGroup->m_groupSpace.size = nestedGroupSize;
966 nestedGroup->m_groupSpace.start = m_groupSpace.start + (nestedGroupIndex * nestedGroupSize);
967 /* Ensure that we haven’t exhausted the available PropertyPathId space. There must be
968 * enough room remaining to assign IDs for all properties defined in QQSK::Property.
969 * If this assertion triggers, consider switching to a wider PropertyPathId_t type or
970 * optimizing how the space is allocated. For example, certain nested paths (such as
971 * control.handle.indicator) can never occur, yet we currently reserve INNER_GROUP_COUNT
972 * for every nesting level, which is wasteful. */
973 Q_ASSERT(nestedGroupSize >= PropertyPathId_t(QQSK::Property::COUNT));
974 }
975 return nestedGroup;
976}
977
978/* This macro will check if the caller has the same group path as \a GROUP_PATH.
979 * This is needed since a QQSK::Property (e.g Color) can sometimes be a
980 * property in several different subclasses of QQStyleKitPropertyGroup.
981 * For example, both control.background.color and control.indicator.color has a
982 * color property. But the group path differs, so they are in reality two completely
983 * different properties. And in that case, when the former changes value, we want to
984 * emit changes globally only to that property, and not the latter.
985 * The caller of this macro will therefore need to go through all the usages of its
986 * subclass in the API, to figure out which group itself is an instance of. For the
987 * one that is a match, the macro will go through all readers and emit the same
988 * signal for them. */
989#define CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(CONTROL_PROPERTIES, GROUP_PATH) if
990 (this == CONTROL_PROPERTIES -> GROUP_PATH ) {
991 for (QQStyleKitReader *reader : QQStyleKitReader::s_allReaders) {
992 const auto baseTypes = QQStyleKitPropertyResolver::baseTypesForType(reader->controlType());
993 if (reader->controlType() != controlType && !baseTypes.contains(controlType))
994 continue;
995 reader->clearLocalStorage();
996 ((reader-> GROUP_PATH ->*changedSignals)(), ...);
997 }
998 return; \
999}
1000
1001template<typename SUBCLASS>
1002void QQStyleKitPropertyGroup::handleStylePropertyChanged(void (SUBCLASS::*changedSignal)()) {
1003 handleStylePropertiesChanged<SUBCLASS>(changedSignal);
1004}
1005
1006template <typename SUBCLASS, typename... CHANGED_SIGNALS>
1007void QQStyleKitPropertyGroup::handleStylePropertiesChanged(CHANGED_SIGNALS... changedSignals)
1008{
1009 /* This function will check which subclass of QQStyleKitProperties this
1010 * group is (nested) inside. Based on that, it will decide if the signals
1011 * should be emitted locally or not, and if the changed properties affects
1012 * all existing QQStyleKitReaders, and therefore will need to be
1013 * emitted 'globally'. Note that it only makes sense to call this function
1014 * for changed properties that are available from a QQStyleKitReader.
1015 * Properities only available from e.g QQStyleKitControl (such as
1016 * variations), are anyway not readable from a QQStyleKitReader. */
1017 static_assert(std::is_base_of<QQStyleKitPropertyGroup, SUBCLASS>::value,
1018 "SUBCLASS must inherit QQStyleKitPropertyGroup");
1019
1020 auto *group = static_cast<SUBCLASS *>(this);
1021 const QQSK::Subclass objectWrittenTo = controlProperties()->subclass();
1022
1023 if (objectWrittenTo == QQSK::Subclass::QQStyleKitState) {
1024 ((group->*changedSignals)(), ...);
1025
1026 if (shouldEmitGlobally()) {
1027 const QQStyleKitControl *control = controlProperties()->asQQStyleKitState()->control();
1028 const QQStyleKitExtendableControlType type = control->controlType();
1029 group->emitGlobally(type, changedSignals...);
1030 }
1031 return;
1032 }
1033
1034 if (objectWrittenTo == QQSK::Subclass::QQStyleKitReader) {
1035 /* Unless the StyleReader has told us not to emit any signals (because it's only
1036 * syncing it's own local storage with old values before starting a transition), we
1037 * emit the signal like normal. This will cause the control to repaint (perhaps
1038 * using a transition). */
1039 if (shouldEmitLocally()) {
1040 QQStyleKitReader *reader = controlProperties()->asQQStyleKitReader();
1041 /* Readers notify their consumer in two different ways depending on who is
1042 * consuming them. A QML control binds to the reader's change signals, so we
1043 * emit those directly. A widget consumer (m_target set) doesn't listen on
1044 * signals; it repaints in response to a QEvent::StyleAnimationUpdate posted
1045 * to the widget, and only while a transition is actually running. */
1046 if (!reader->m_target)
1047 ((group->*changedSignals)(), ...);
1048 else
1049 QCoreApplication::postEvent(reader->m_target, new QEvent(QEvent::StyleAnimationUpdate));
1050 }
1051 return;
1052 }
1053
1054 Q_UNREACHABLE();
1055}
1056
1058{
1059 /* This function will emit changed signals for all style properties in the
1060 * StyleKit API (for a single QQStyleKitReader), which is needed after
1061 * doing a style-, or theme change. */
1062 const int startIndex = QQStyleKitPropertyGroup::staticMetaObject.propertyOffset();
1063 const QMetaObject* meta = metaObject();
1064 for (int i = startIndex; i < meta->propertyCount(); ++i) {
1065 const QMetaProperty prop = meta->property(i);
1066 const QMetaObject* propMetaObject = QMetaType::fromName(prop.typeName()).metaObject();
1067 if (propMetaObject) {
1068 if (propMetaObject->inherits(&QQStyleKitDelegateProperties::staticMetaObject)) {
1069 /* Skip recursing into QQStyleKitDelegateProperties, because those are lazy
1070 * created when read, and reading them from here would accidentally
1071 * create them. */
1072 continue;
1073 }
1074 if (propMetaObject->inherits(&QQStyleKitPropertyGroup::staticMetaObject)) {
1075 // The property is of type QQStyleKitPropertyGroup, so recurse into it
1076 QObject *childObj = qvariant_cast<QObject *>(property(prop.name()));
1077 if (auto *child = qobject_cast<QQStyleKitPropertyGroup *>(childObj))
1078 child->emitChangedForAllStylePropertiesRecursive(emitFlags);
1079 continue;
1080 }
1081 }
1082
1083 if (!emitFlags.testFlag(EmitFlag::AllProperties)) {
1084 // Only emit for color properties when the Colors flag is set
1085 if (emitFlags.testFlag(EmitFlag::Colors)) {
1086 if (prop.metaType() != QMetaType::fromType<QColor>())
1087 continue;
1088 }
1089 }
1090
1091 // Emit the changed signal for the property
1092 Q_ASSERT(prop.hasNotifySignal());
1093 QMetaMethod notify = prop.notifySignal();
1094 notify.invoke(this, Qt::DirectConnection);
1095 }
1096}
1097
1098bool QQStyleKitPropertyGroup::shouldEmitLocally()
1099{
1100 return !controlProperties()->asQQStyleKitReader()->dontEmitChangedSignals();
1101}
1102
1103bool QQStyleKitPropertyGroup::shouldEmitGlobally()
1104{
1105 QQStyleKitStyle *parentStyle = controlProperties()->style();
1106 if (!parentStyle)
1107 return false;
1108
1109 if (parentStyle->loaded() && !parentStyle->m_isUpdatingPalette) {
1110 /* When a property has changed in the 'global' QQStyleKitStyle itself, it can
1111 * potentially affect all control instances. We therefore need to go through all
1112 * QQStyleKitReaders and inform that their own local property that matches the
1113 * 'global' property needs to be re-read. We emit the signals directly, omitting any
1114 * applied transitions in the QQStyleKitReaders, to optimize for speed. The exception
1115 * is if we're just updating the palette in the Style to match the palette in the current
1116 * control / QQStyleKitReader. Such a change will only affect a single control. */
1117 return parentStyle == QQStyleKitStyle::current();
1118 }
1119 return false;
1120}
1121
1122// ************* QQStyleKitImageProperties ****************
1123
1124QQStyleKitImageProperties::QQStyleKitImageProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1125 : QQStyleKitPropertyGroup(group, parent)
1126{
1127}
1128
1129template <typename... CHANGED_SIGNALS>
1130void QQStyleKitImageProperties::emitGlobally(
1131 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1132{
1133 // Go through all instances of QQStyleKitImageProperties
1134 const QQStyleKitControlProperties *cp = controlProperties();
1135 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->image());
1136 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->image());
1137 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->image());
1138 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->image());
1139}
1140
1141QUrl QQStyleKitImageProperties::source() const
1142{
1143 return styleProperty<QUrl>(QQSK::Property::Source);
1144}
1145
1146void QQStyleKitImageProperties::setSource(const QUrl &source)
1147{
1148 if (setStyleProperty(QQSK::Property::Source, source))
1149 handleStylePropertyChanged(&QQStyleKitImageProperties::sourceChanged);
1150}
1151
1152QColor QQStyleKitImageProperties::color() const
1153{
1154 return styleProperty<QColor>(QQSK::Property::Color);
1155}
1156
1157void QQStyleKitImageProperties::setColor(const QColor &color)
1158{
1159 if (setStyleProperty(QQSK::Property::Color, color))
1160 handleStylePropertyChanged(&QQStyleKitImageProperties::colorChanged);
1161}
1162
1163QQuickImage::FillMode QQStyleKitImageProperties::fillMode() const
1164{
1165 return styleProperty<QQuickImage::FillMode>(QQSK::Property::FillMode);
1166}
1167
1168void QQStyleKitImageProperties::setFillMode(QQuickImage::FillMode fillMode)
1169{
1170 if (setStyleProperty(QQSK::Property::FillMode, fillMode))
1171 handleStylePropertyChanged(&QQStyleKitImageProperties::fillModeChanged);
1172}
1173
1174// ************* QQStyleKitBorderProperties ****************
1175
1176QQStyleKitBorderProperties::QQStyleKitBorderProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1177 : QQStyleKitPropertyGroup(group, parent)
1178{
1179}
1180
1181template <typename... CHANGED_SIGNALS>
1182void QQStyleKitBorderProperties::emitGlobally(
1183 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1184{
1185 // Go through all instances of QQStyleKitBorderProperties
1186 const QQStyleKitControlProperties *cp = controlProperties();
1187 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->border());
1188 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->border());
1189 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->border());
1190 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->border());
1191}
1192
1193qreal QQStyleKitBorderProperties::width() const
1194{
1195 return styleProperty<qreal>(QQSK::Property::Width);
1196}
1197
1198void QQStyleKitBorderProperties::setWidth(qreal width)
1199{
1200 if (setStyleProperty(QQSK::Property::Width, width))
1201 handleStylePropertyChanged(&QQStyleKitBorderProperties::widthChanged);
1202}
1203
1204QColor QQStyleKitBorderProperties::color() const
1205{
1206 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1207}
1208
1209void QQStyleKitBorderProperties::setColor(const QColor &color)
1210{
1211 if (setStyleProperty(QQSK::Property::Color, color))
1212 handleStylePropertyChanged(&QQStyleKitBorderProperties::colorChanged);
1213}
1214
1215// ************* QQStyleKitShadowProperties ****************
1216
1217QQStyleKitShadowProperties::QQStyleKitShadowProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1218 : QQStyleKitPropertyGroup(group, parent)
1219{
1220}
1221
1222template <typename... CHANGED_SIGNALS>
1223void QQStyleKitShadowProperties::emitGlobally(
1224 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1225{
1226 // Go through all instances of QQStyleKitShadowProperties
1227 const QQStyleKitControlProperties *cp = controlProperties();
1228 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, background()->shadow());
1229 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, handle()->shadow());
1230 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->shadow());
1231 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground()->shadow());
1232}
1233
1234QColor QQStyleKitShadowProperties::color() const
1235{
1236 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1237}
1238
1239void QQStyleKitShadowProperties::setColor(QColor color)
1240{
1241 if (setStyleProperty(QQSK::Property::Color, color))
1242 handleStylePropertyChanged(&QQStyleKitShadowProperties::colorChanged);
1243}
1244
1245qreal QQStyleKitShadowProperties::opacity() const
1246{
1247 return styleProperty<qreal>(QQSK::Property::Opacity, 1.0);
1248}
1249
1250void QQStyleKitShadowProperties::setOpacity(qreal opacity)
1251{
1252 if (setStyleProperty(QQSK::Property::Opacity, opacity))
1253 handleStylePropertyChanged(&QQStyleKitShadowProperties::opacityChanged);
1254}
1255
1256qreal QQStyleKitShadowProperties::scale() const
1257{
1258 return styleProperty<qreal>(QQSK::Property::Scale, 1.0);
1259}
1260
1261void QQStyleKitShadowProperties::setScale(qreal scale)
1262{
1263 if (setStyleProperty(QQSK::Property::Scale, scale))
1264 handleStylePropertyChanged(&QQStyleKitShadowProperties::scaleChanged);
1265}
1266
1267qreal QQStyleKitShadowProperties::verticalOffset() const
1268{
1269 return styleProperty<qreal>(QQSK::Property::VOffset);
1270}
1271
1272void QQStyleKitShadowProperties::setVerticalOffset(qreal verticalOffset)
1273{
1274 if (setStyleProperty(QQSK::Property::VOffset, verticalOffset))
1275 handleStylePropertyChanged(&QQStyleKitShadowProperties::verticalOffsetChanged);
1276}
1277
1278qreal QQStyleKitShadowProperties::horizontalOffset() const
1279{
1280 return styleProperty<qreal>(QQSK::Property::HOffset);
1281}
1282
1283void QQStyleKitShadowProperties::setHorizontalOffset(qreal horizontalOffset)
1284{
1285 if (setStyleProperty(QQSK::Property::HOffset, horizontalOffset))
1286 handleStylePropertyChanged(&QQStyleKitShadowProperties::horizontalOffsetChanged);
1287}
1288
1289qreal QQStyleKitShadowProperties::blur() const
1290{
1291 return styleProperty<qreal>(QQSK::Property::Blur, 10.0);
1292}
1293
1294void QQStyleKitShadowProperties::setBlur(qreal blur)
1295{
1296 if (setStyleProperty(QQSK::Property::Blur, blur))
1297 handleStylePropertyChanged(&QQStyleKitShadowProperties::blurChanged);
1298}
1299
1300bool QQStyleKitShadowProperties::visible() const
1301{
1302 return styleProperty<bool>(QQSK::Property::Visible, true);
1303}
1304
1305void QQStyleKitShadowProperties::setVisible(bool visible)
1306{
1307 if (setStyleProperty(QQSK::Property::Visible, visible))
1308 handleStylePropertyChanged(&QQStyleKitShadowProperties::visibleChanged);
1309}
1310
1311QQmlComponent *QQStyleKitShadowProperties::delegate() const
1312{
1313 return styleProperty<QQmlComponent *>(QQSK::Property::Delegate);
1314}
1315
1316void QQStyleKitShadowProperties::setDelegate(QQmlComponent *delegate)
1317{
1318 if (setStyleProperty(QQSK::Property::Delegate, delegate))
1319 handleStylePropertyChanged(&QQStyleKitShadowProperties::delegateChanged);
1320}
1321
1322// ************* QQStyleKitDelegateProperties ****************
1323
1324QQStyleKitDelegateProperties::QQStyleKitDelegateProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1325 : QQStyleKitPropertyGroup(group, parent)
1326{
1327}
1328
1329template <typename... CHANGED_SIGNALS>
1330void QQStyleKitDelegateProperties::emitGlobally(
1331 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1332{
1333 // Go through all instances of QQStyleKitDelegateProperties
1334 const QQStyleKitControlProperties *cp = controlProperties();
1338 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->foreground());
1339}
1340
1341qreal QQStyleKitDelegateProperties::radius() const
1342{
1343 return styleProperty<qreal>(QQSK::Property::Radius);
1344}
1345
1346void QQStyleKitDelegateProperties::setRadius(qreal radius)
1347{
1348 if (setStyleProperty(QQSK::Property::Radius, radius))
1349 handleStylePropertiesChanged<QQStyleKitDelegateProperties>(
1350 &QQStyleKitDelegateProperties::radiusChanged,
1351 &QQStyleKitDelegateProperties::topLeftRadiusChanged,
1352 &QQStyleKitDelegateProperties::topRightRadiusChanged,
1353 &QQStyleKitDelegateProperties::bottomLeftRadiusChanged,
1354 &QQStyleKitDelegateProperties::bottomRightRadiusChanged);
1355}
1356
1357qreal QQStyleKitDelegateProperties::topLeftRadius() const
1358{
1359 return styleProperty<qreal>(QQSK::Property::TopLeftRadius, QQSK::Property::Radius);
1360}
1361
1362void QQStyleKitDelegateProperties::setTopLeftRadius(qreal radius)
1363{
1364 if (setStyleProperty(QQSK::Property::TopLeftRadius, radius))
1365 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topLeftRadiusChanged);
1366}
1367
1368qreal QQStyleKitDelegateProperties::topRightRadius() const
1369{
1370 return styleProperty<qreal>(QQSK::Property::TopRightRadius, QQSK::Property::Radius);
1371}
1372
1373void QQStyleKitDelegateProperties::setTopRightRadius(qreal radius)
1374{
1375 if (setStyleProperty(QQSK::Property::TopRightRadius, radius))
1376 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topRightRadiusChanged);
1377}
1378
1379qreal QQStyleKitDelegateProperties::bottomLeftRadius() const
1380{
1381 return styleProperty<qreal>(QQSK::Property::BottomLeftRadius, QQSK::Property::Radius);
1382}
1383
1384void QQStyleKitDelegateProperties::setBottomLeftRadius(qreal radius)
1385{
1386 if (setStyleProperty(QQSK::Property::BottomLeftRadius, radius))
1387 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomLeftRadiusChanged);
1388}
1389
1390qreal QQStyleKitDelegateProperties::bottomRightRadius() const
1391{
1392 return styleProperty<qreal>(QQSK::Property::BottomRightRadius, QQSK::Property::Radius);
1393}
1394
1395void QQStyleKitDelegateProperties::setBottomRightRadius(qreal radius)
1396{
1397 if (setStyleProperty(QQSK::Property::BottomRightRadius, radius))
1398 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomRightRadiusChanged);
1399}
1400
1401qreal QQStyleKitDelegateProperties::scale() const
1402{
1403 return styleProperty<qreal>(QQSK::Property::Scale, 1.0);
1404}
1405
1406void QQStyleKitDelegateProperties::setScale(qreal scale)
1407{
1408 if (setStyleProperty(QQSK::Property::Scale, scale))
1409 handleStylePropertyChanged(&QQStyleKitDelegateProperties::scaleChanged);
1410}
1411
1412qreal QQStyleKitDelegateProperties::rotation() const
1413{
1414 return styleProperty<qreal>(QQSK::Property::Rotation);
1415}
1416
1417void QQStyleKitDelegateProperties::setRotation(qreal rotation)
1418{
1419 if (setStyleProperty(QQSK::Property::Rotation, rotation))
1420 handleStylePropertyChanged(&QQStyleKitDelegateProperties::rotationChanged);
1421}
1422
1423qreal QQStyleKitDelegateProperties::implicitWidth() const
1424{
1425 return styleProperty<qreal>(QQSK::Property::ImplicitWidth);
1426}
1427
1428void QQStyleKitDelegateProperties::setImplicitWidth(qreal width)
1429{
1430 if (setStyleProperty(QQSK::Property::ImplicitWidth, width))
1431 handleStylePropertyChanged(&QQStyleKitDelegateProperties::implicitWidthChanged);
1432}
1433
1434qreal QQStyleKitDelegateProperties::implicitHeight() const
1435{
1436 return styleProperty<qreal>(QQSK::Property::ImplicitHeight);
1437}
1438
1439void QQStyleKitDelegateProperties::setImplicitHeight(qreal height)
1440{
1441 if (setStyleProperty(QQSK::Property::ImplicitHeight, height))
1442 handleStylePropertyChanged(&QQStyleKitDelegateProperties::implicitHeightChanged);
1443}
1444
1445qreal QQStyleKitDelegateProperties::minimumWidth() const
1446{
1447 return styleProperty<qreal>(QQSK::Property::MinimumWidth);
1448}
1449
1450void QQStyleKitDelegateProperties::setMinimumWidth(qreal width)
1451{
1452 if (setStyleProperty(QQSK::Property::MinimumWidth, width))
1453 handleStylePropertyChanged(&QQStyleKitDelegateProperties::minimumWidthChanged);
1454}
1455
1456qreal QQStyleKitDelegateProperties::margins() const
1457{
1458 return styleProperty<qreal>(QQSK::Property::Margins);
1459}
1460
1461void QQStyleKitDelegateProperties::setMargins(qreal margins)
1462{
1463 if (setStyleProperty(QQSK::Property::Margins, margins))
1464 handleStylePropertiesChanged<QQStyleKitDelegateProperties>(
1465 &QQStyleKitDelegateProperties::marginsChanged,
1466 &QQStyleKitDelegateProperties::leftMarginChanged,
1467 &QQStyleKitDelegateProperties::rightMarginChanged,
1468 &QQStyleKitDelegateProperties::topMarginChanged,
1469 &QQStyleKitDelegateProperties::bottomMarginChanged);
1470}
1471
1472qreal QQStyleKitDelegateProperties::leftMargin() const
1473{
1474 return styleProperty<qreal>(QQSK::Property::LeftMargin, QQSK::Property::Margins);
1475}
1476
1477void QQStyleKitDelegateProperties::setLeftMargin(qreal margin)
1478{
1479 if (setStyleProperty(QQSK::Property::LeftMargin, margin))
1480 handleStylePropertyChanged(&QQStyleKitDelegateProperties::leftMarginChanged);
1481}
1482
1483qreal QQStyleKitDelegateProperties::rightMargin() const
1484{
1485 return styleProperty<qreal>(QQSK::Property::RightMargin, QQSK::Property::Margins);
1486}
1487
1488void QQStyleKitDelegateProperties::setRightMargin(qreal margin)
1489{
1490 if (setStyleProperty(QQSK::Property::RightMargin, margin))
1491 handleStylePropertyChanged(&QQStyleKitDelegateProperties::rightMarginChanged);
1492}
1493
1494qreal QQStyleKitDelegateProperties::topMargin() const
1495{
1496 return styleProperty<qreal>(QQSK::Property::TopMargin, QQSK::Property::Margins);
1497}
1498
1499void QQStyleKitDelegateProperties::setTopMargin(qreal margin)
1500{
1501 if (setStyleProperty(QQSK::Property::TopMargin, margin))
1502 handleStylePropertyChanged(&QQStyleKitDelegateProperties::topMarginChanged);
1503}
1504
1505qreal QQStyleKitDelegateProperties::bottomMargin() const
1506{
1507 return styleProperty<qreal>(QQSK::Property::BottomMargin, QQSK::Property::Margins);
1508}
1509
1510void QQStyleKitDelegateProperties::setBottomMargin(qreal margin)
1511{
1512 if (setStyleProperty(QQSK::Property::BottomMargin, margin))
1513 handleStylePropertyChanged(&QQStyleKitDelegateProperties::bottomMarginChanged);
1514}
1515
1516Qt::Alignment QQStyleKitDelegateProperties::alignment() const
1517{
1518 return styleProperty<Qt::Alignment>(QQSK::Property::Alignment, Qt::AlignLeft | Qt::AlignVCenter);
1519}
1520
1521void QQStyleKitDelegateProperties::setAlignment(Qt::Alignment alignment)
1522{
1523 if (setStyleProperty(QQSK::Property::Alignment, alignment))
1524 handleStylePropertyChanged(&QQStyleKitDelegateProperties::alignmentChanged);
1525}
1526
1527qreal QQStyleKitDelegateProperties::opacity() const
1528{
1529 return styleProperty<qreal>(QQSK::Property::Opacity, 1.0);
1530}
1531
1532void QQStyleKitDelegateProperties::setOpacity(qreal opacity)
1533{
1534 if (setStyleProperty(QQSK::Property::Opacity, opacity))
1535 handleStylePropertyChanged(&QQStyleKitDelegateProperties::opacityChanged);
1536}
1537
1538QColor QQStyleKitDelegateProperties::color() const
1539{
1540 return styleProperty<QColor>(QQSK::Property::Color, Qt::transparent);
1541}
1542
1543void QQStyleKitDelegateProperties::setColor(const QColor &color)
1544{
1545 if (setStyleProperty(QQSK::Property::Color, color))
1546 handleStylePropertyChanged(&QQStyleKitDelegateProperties::colorChanged);
1547}
1548
1549bool QQStyleKitDelegateProperties::visible() const
1550{
1551 return styleProperty<bool>(QQSK::Property::Visible, true);
1552}
1553
1554void QQStyleKitDelegateProperties::setVisible(bool visible)
1555{
1556 if (setStyleProperty(QQSK::Property::Visible, visible))
1557 handleStylePropertyChanged(&QQStyleKitDelegateProperties::visibleChanged);
1558}
1559
1560bool QQStyleKitDelegateProperties::clip() const
1561{
1562 return styleProperty<bool>(QQSK::Property::Clip, false);
1563}
1564
1565void QQStyleKitDelegateProperties::setClip(bool clip)
1566{
1567 if (setStyleProperty(QQSK::Property::Clip, clip))
1568 handleStylePropertyChanged(&QQStyleKitDelegateProperties::clipChanged);
1569}
1570
1571QQuickGradient *QQStyleKitDelegateProperties::gradient() const
1572{
1573 return styleProperty<QQuickGradient *>(QQSK::Property::Gradient);
1574}
1575
1576void QQStyleKitDelegateProperties::setGradient(QQuickGradient *gradient)
1577{
1578 if (setStyleProperty(QQSK::Property::Gradient, gradient))
1579 handleStylePropertyChanged(&QQStyleKitDelegateProperties::gradientChanged);
1580}
1581
1582QObject *QQStyleKitDelegateProperties::data() const
1583{
1584 return styleProperty<QObject *>(QQSK::Property::Data);
1585}
1586
1587void QQStyleKitDelegateProperties::setData(QObject *data)
1588{
1589 if (setStyleProperty(QQSK::Property::Data, data))
1590 handleStylePropertyChanged(&QQStyleKitDelegateProperties::dataChanged);
1591}
1592
1593QQmlComponent *QQStyleKitDelegateProperties::delegate() const
1594{
1595 return styleProperty<QQmlComponent *>(QQSK::Property::Delegate);
1596}
1597
1598void QQStyleKitDelegateProperties::setDelegate(QQmlComponent *delegate)
1599{
1600 if (setStyleProperty(QQSK::Property::Delegate, delegate))
1601 handleStylePropertyChanged(&QQStyleKitDelegateProperties::delegateChanged);
1602}
1603
1604QQStyleKitBorderProperties *QQStyleKitDelegateProperties::border() const
1605{
1606 return lazyCreateGroup(m_border, QQSK::PropertyGroup::Border);
1607}
1608
1609QQStyleKitShadowProperties *QQStyleKitDelegateProperties::shadow() const
1610{
1611 return lazyCreateGroup(m_shadow, QQSK::PropertyGroup::Shadow);
1612}
1613
1614QQStyleKitImageProperties *QQStyleKitDelegateProperties::image() const
1615{
1616 return lazyCreateGroup(m_image, QQSK::PropertyGroup::Image);
1617}
1618
1619// ************* QQStyleKitHandleProperties ****************
1620
1621QQStyleKitHandleProperties::QQStyleKitHandleProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1622 : QQStyleKitDelegateProperties(group, parent)
1623{
1624}
1625
1626QQStyleKitDelegateProperties *QQStyleKitHandleProperties::first() const
1627{
1628 return lazyCreateGroup(m_first, QQSK::PropertyGroup::DelegateSubtype1);
1629}
1630
1631QQStyleKitDelegateProperties *QQStyleKitHandleProperties::second() const
1632{
1633 return lazyCreateGroup(m_second, QQSK::PropertyGroup::DelegateSubtype2);
1634}
1635
1636// ************* QQStyleKitIndicatorProperties ****************
1637
1638QQStyleKitIndicatorProperties::QQStyleKitIndicatorProperties(
1639 QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1640 : QQStyleKitDelegateProperties(group, parent)
1641{
1642}
1643
1644template <typename... CHANGED_SIGNALS>
1646 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1647{
1648 // Go through all instances of QQStyleKitIndicatorProperties
1649 const QQStyleKitControlProperties *cp = controlProperties();
1650 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->up());
1651 CONDITIONALLY_EMIT_SIGNALS_GLOBALLY_FOR(cp, indicator()->down());
1652}
1653
1654QQStyleKitDelegateProperties *QQStyleKitIndicatorProperties::foreground() const
1655{
1656 return lazyCreateGroup(m_foreground, QQSK::PropertyGroup::Foreground);
1657}
1658
1659// ************* QQStyleKitIndicatorWithSubTypes ****************
1660
1661QQStyleKitIndicatorWithSubTypes::QQStyleKitIndicatorWithSubTypes(
1662 QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1663 : QQStyleKitDelegateProperties(group, parent)
1664{
1665}
1666
1667template <typename... CHANGED_SIGNALS>
1669 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1670{
1671 // Go through all instances of QQStyleKitIndicatorWithSubTypes
1672 const QQStyleKitControlProperties *cp = controlProperties();
1674}
1675
1676QQStyleKitDelegateProperties *QQStyleKitIndicatorWithSubTypes::foreground() const
1677{
1678 return lazyCreateGroup(m_foreground, QQSK::PropertyGroup::Foreground);
1679}
1680
1682{
1683 return lazyCreateGroup(m_up, QQSK::PropertyGroup::DelegateSubtype1);
1684}
1685
1687{
1688 return lazyCreateGroup(m_down, QQSK::PropertyGroup::DelegateSubtype2);
1689}
1690
1691// ************* QQStyleKitTextProperties ****************
1692QQStyleKitTextProperties::QQStyleKitTextProperties(QQSK::PropertyGroup group, QQStyleKitControlProperties *parent)
1693 : QQStyleKitPropertyGroup(group, parent)
1694{
1695}
1696
1697template <typename... CHANGED_SIGNALS>
1699 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1700{
1701 const QQStyleKitControlProperties *cp = controlProperties();
1703}
1704
1706{
1707 return styleProperty<QColor>(QQSK::Property::Color);
1708}
1709
1710void QQStyleKitTextProperties::setColor(const QColor &color)
1711{
1712 if (setStyleProperty(QQSK::Property::Color, color))
1713 handleStylePropertyChanged(&QQStyleKitTextProperties::colorChanged);
1714}
1715
1717{
1718 return styleProperty<Qt::Alignment>(QQSK::Property::Alignment);
1719}
1720
1721void QQStyleKitTextProperties::setAlignment(Qt::Alignment alignment)
1722{
1723 if (setStyleProperty(QQSK::Property::Alignment, alignment))
1724 handleStylePropertyChanged(&QQStyleKitTextProperties::alignmentChanged);
1725}
1726
1728{
1729 return styleProperty<bool>(QQSK::Property::Bold, false);
1730}
1731
1733{
1734 if (setStyleProperty(QQSK::Property::Bold, bold))
1735 handleStylePropertyChanged(&QQStyleKitTextProperties::boldChanged);
1736}
1737
1739{
1740 return styleProperty<bool>(QQSK::Property::Italic, false);
1741}
1742
1744{
1745 if (setStyleProperty(QQSK::Property::Italic, italic))
1746 handleStylePropertyChanged(&QQStyleKitTextProperties::italicChanged);
1747}
1748
1750{
1751 return styleProperty<qreal>(QQSK::Property::PointSize);
1752}
1753
1755{
1756 if (setStyleProperty(QQSK::Property::PointSize, pointSize))
1757 handleStylePropertyChanged(&QQStyleKitTextProperties::pointSizeChanged);
1758}
1759
1761{
1762 return styleProperty<qreal>(QQSK::Property::Padding);
1763}
1764
1775
1777{
1778 return styleProperty<qreal>(QQSK::Property::LeftPadding, QQSK::Property::Padding);
1779}
1780
1782{
1783 if (setStyleProperty(QQSK::Property::LeftPadding, padding))
1784 handleStylePropertyChanged(&QQStyleKitTextProperties::leftPaddingChanged);
1785}
1786
1788{
1789 return styleProperty<qreal>(QQSK::Property::RightPadding, QQSK::Property::Padding);
1790}
1791
1793{
1794 if (setStyleProperty(QQSK::Property::RightPadding, padding))
1795 handleStylePropertyChanged(&QQStyleKitTextProperties::rightPaddingChanged);
1796}
1797
1799{
1800 return styleProperty<qreal>(QQSK::Property::TopPadding, QQSK::Property::Padding);
1801}
1802
1804{
1805 if (setStyleProperty(QQSK::Property::TopPadding, padding))
1806 handleStylePropertyChanged(&QQStyleKitTextProperties::topPaddingChanged);
1807}
1808
1810{
1811 return styleProperty<qreal>(QQSK::Property::BottomPadding, QQSK::Property::Padding);
1812}
1813
1815{
1816 if (setStyleProperty(QQSK::Property::BottomPadding, padding))
1817 handleStylePropertyChanged(&QQStyleKitTextProperties::bottomPaddingChanged);
1818}
1819
1820// ************* QQStyleKitControlProperties ****************
1821
1822QQStyleKitControlProperties::QQStyleKitControlProperties(QQSK::PropertyGroup group, QObject *parent)
1823 : QQStyleKitPropertyGroup(group, parent)
1824{
1825 /* Calculate the free space storage ID space that can accommodate all unique style
1826 * properties that may be applied to a control. Since we'll prepend different states
1827 * and subtypes during the property propagation lookup phase later, we need to reserve
1828 * ID space for them both already now. More docs about the property space is written in
1829 * the implementation of PropertyPathId. */
1830 m_groupSpace.size = nestedGroupsStartSize;
1831 m_groupSpace.start = 0;
1832
1833 if (group == QQSK::PropertyGroup::GlobalFlag) {
1834 /* A property path may include pseudo-groups that offers a convenient API for
1835 * reading properties with specific options applied. The 'global' group is one such
1836 * pseudo-group. When it is prefixed to a property path, it indicates that the property
1837 * should be read directly from the style, bypassing any active transitions that might
1838 * otherwise affect its value.
1839 * Note: The global group should be ignored when computing a PropertyPathId_t, as it
1840 * only affect _where_ the property should be read from, not its ID. */
1841 m_pathFlags.setFlag(QQSK::PropertyPathFlag::Global);
1842 }
1843}
1844
1845QQStyleKitStyle *QQStyleKitControlProperties::style() const
1846{
1847 if (subclass() == QQSK::Subclass::QQStyleKitState) {
1848 /* A QQStyleKitControlState (and its subclasses) should always be a (grand)child of a
1849 * QQStyleKitStyle. And it belongs to that style, even it that style is not the
1850 * currently active application style. This is opposed to a QQStyleKitReader,
1851 * that normally belongs / communicates with the currently active style.
1852 * NOTE: a style can also be a fallback style for another style (which can be recursive,
1853 * meaning that a fallback style can also have its own fallback style, and so on). But
1854 * this function will return the nearest style, and not the root style */
1855 QObject *obj = parent();
1856 while (obj && !obj->metaObject()->inherits(&QQStyleKitStyle::staticMetaObject))
1857 obj = obj->parent();
1858 return obj ? static_cast<QQStyleKitStyle *>(obj) : nullptr;
1859 }
1860
1861 if (subclass() == QQSK::Subclass::QQStyleKitReader) {
1862 const auto *reader = static_cast<const QQStyleKitReader *>(this);
1863 if (reader->m_explicitStyle)
1864 return reader->m_explicitStyle;
1865 }
1866
1867 // For a QQStyleKitReader without an explicit style, we return the currently active style for now
1868 return QQStyleKitStyle::current();
1869}
1870
1871QQSK::Subclass QQStyleKitControlProperties::subclass() const
1872{
1873 /* QQStyleKitControlProperties is subclassed by several different classes in this
1874 * framework. As such, it's basically just an interface because it only declares the
1875 * different properties that can be read or written to in a QQStyleKitStyle, such as
1876 * hovered.background.color or pressed.indicator.foreground.color. It says nothing
1877 * about how those properties are stored, instead that is up to each individual
1878 * subclass to decide */
1879 if (metaObject()->inherits(&QQStyleKitReader::staticMetaObject))
1880 return QQSK::Subclass::QQStyleKitReader;
1881 if (metaObject()->inherits(&QQStyleKitControlState::staticMetaObject))
1882 return QQSK::Subclass::QQStyleKitState;
1883 Q_UNREACHABLE();
1884}
1885
1886QQStyleKitReader *QQStyleKitControlProperties::asQQStyleKitReader() const
1887{
1888 Q_ASSERT(subclass() == QQSK::Subclass::QQStyleKitReader);
1889 return static_cast<QQStyleKitReader *>(const_cast<QQStyleKitControlProperties *>(this));
1890}
1891
1892QQStyleKitControlState *QQStyleKitControlProperties::asQQStyleKitState() const
1893{
1894 Q_ASSERT(subclass() == QQSK::Subclass::QQStyleKitState);
1895 Q_ASSERT(metaObject()->inherits(&QQStyleKitControlState::staticMetaObject));
1896 return static_cast<QQStyleKitControlState *>(const_cast<QQStyleKitControlProperties *>(this));
1897}
1898
1899void QQStyleKitControlProperties::forEachUsedDelegate(
1900 std::function<void (QQStyleKitDelegateProperties *, QQSK::Delegate, const QString &)> f)
1901{
1902 // If adding more delegates here, remember to keep StyleAnimation.qml in sync
1903 if (m_background)
1904 f(m_background, QQSK::Delegate::Background, "background"_L1);
1905
1906 if (m_indicator) {
1907 f(m_indicator, QQSK::Delegate::Indicator, "indicator"_L1);
1908 if (m_indicator->m_foreground)
1909 f(m_indicator->m_foreground, QQSK::Delegate::IndicatorForeground, "indicator.foreground"_L1);
1910 if (m_indicator->m_up) {
1911 f(m_indicator->m_up, QQSK::Delegate::IndicatorUp, "indicator.up"_L1);
1912 if (m_indicator->m_up->m_foreground)
1913 f(m_indicator->m_up->m_foreground, QQSK::Delegate::IndicatorUpForeground, "indicator.up.foreground"_L1);
1914 }
1915 if (m_indicator->m_down) {
1916 f(m_indicator->m_down, QQSK::Delegate::IndicatorDown, "indicator.down"_L1);
1917 if (m_indicator->m_down->m_foreground)
1918 f(m_indicator->m_down->m_foreground, QQSK::Delegate::IndicatorDownForeground, "indicator.down.foreground"_L1);
1919 }
1920 }
1921
1922 if (m_handle) {
1923 f(m_handle, QQSK::Delegate::Handle, "handle"_L1);
1924 if (m_handle->m_first)
1925 f(m_handle->m_first, QQSK::Delegate::HandleFirst, "handle.first"_L1);
1926 if (m_handle->m_second)
1927 f(m_handle->m_second, QQSK::Delegate::HandleSecond, "handle.second"_L1);
1928 }
1929}
1930
1931void QQStyleKitControlProperties::emitChangedForAllStyleProperties(EmitFlags emitFlags)
1932{
1933 /* This brute-force function will emit update signals for _all_ style properties
1934 * in the QQStyleKitStyle API. Doing so is typically needed after a style-, or theme
1935 * change, as we don't know which properties are affected by such a big change. */
1936 if (emitFlags.testFlag(EmitFlag::AllProperties)) {
1937 emit leftPaddingChanged();
1938 emit rightPaddingChanged();
1939 emit topPaddingChanged();
1940 emit bottomPaddingChanged();
1941 emit spacingChanged();
1942 emit transitionChanged();
1943 emit textChanged();
1944 }
1945
1946 forEachUsedDelegate([=](QQStyleKitDelegateProperties *delegate, QQSK::Delegate, const QString &){
1947 delegate->emitChangedForAllStylePropertiesRecursive(emitFlags);
1948 });
1949}
1950
1951template <typename... CHANGED_SIGNALS>
1952void QQStyleKitControlProperties::emitGlobally(
1953 QQStyleKitExtendableControlType controlType, CHANGED_SIGNALS... changedSignals) const
1954{
1955 for (QQStyleKitReader *reader : QQStyleKitReader::s_allReaders) {
1956 if (reader->controlType() != controlType)
1957 continue;
1958 ((reader->*changedSignals)(), ...);
1959 }
1960}
1961
1962qreal QQStyleKitControlProperties::spacing() const
1963{
1964 return styleProperty<qreal>(QQSK::Property::Spacing);
1965}
1966
1967void QQStyleKitControlProperties::setSpacing(qreal spacing)
1968{
1969 if (setStyleProperty(QQSK::Property::Spacing, spacing))
1970 handleStylePropertyChanged(&QQStyleKitControlProperties::spacingChanged);
1971}
1972
1973qreal QQStyleKitControlProperties::padding() const
1974{
1975 return styleProperty<qreal>(QQSK::Property::Padding);
1976}
1977
1978void QQStyleKitControlProperties::setPadding(qreal padding)
1979{
1980 if (setStyleProperty(QQSK::Property::Padding, padding))
1981 handleStylePropertiesChanged<QQStyleKitControlProperties>(
1982 &QQStyleKitControlProperties::paddingChanged,
1983 &QQStyleKitControlProperties::leftPaddingChanged,
1984 &QQStyleKitControlProperties::rightPaddingChanged,
1985 &QQStyleKitControlProperties::topPaddingChanged,
1986 &QQStyleKitControlProperties::bottomPaddingChanged);
1987}
1988
1989qreal QQStyleKitControlProperties::leftPadding() const
1990{
1991 return styleProperty<qreal>(QQSK::Property::LeftPadding, QQSK::Property::Padding);
1992}
1993
1994void QQStyleKitControlProperties::setLeftPadding(qreal leftPadding)
1995{
1996 if (setStyleProperty(QQSK::Property::LeftPadding, leftPadding))
1997 handleStylePropertyChanged(&QQStyleKitControlProperties::leftPaddingChanged);
1998}
1999
2000qreal QQStyleKitControlProperties::rightPadding() const
2001{
2002 return styleProperty<qreal>(QQSK::Property::RightPadding, QQSK::Property::Padding);
2003}
2004
2005void QQStyleKitControlProperties::setRightPadding(qreal rightPadding)
2006{
2007 if (setStyleProperty(QQSK::Property::RightPadding, rightPadding))
2008 handleStylePropertyChanged(&QQStyleKitControlProperties::rightPaddingChanged);
2009}
2010
2011qreal QQStyleKitControlProperties::topPadding() const
2012{
2013 return styleProperty<qreal>(QQSK::Property::TopPadding, QQSK::Property::Padding);
2014}
2015
2016void QQStyleKitControlProperties::setTopPadding(qreal topPadding)
2017{
2018 if (setStyleProperty(QQSK::Property::TopPadding, topPadding))
2019 handleStylePropertyChanged(&QQStyleKitControlProperties::topPaddingChanged);
2020}
2021
2022qreal QQStyleKitControlProperties::bottomPadding() const
2023{
2024 return styleProperty<qreal>(QQSK::Property::BottomPadding, QQSK::Property::Padding);
2025}
2026
2027void QQStyleKitControlProperties::setBottomPadding(qreal bottomPadding)
2028{
2029 if (setStyleProperty(QQSK::Property::BottomPadding, bottomPadding))
2030 handleStylePropertyChanged(&QQStyleKitControlProperties::bottomPaddingChanged);
2031}
2032
2033QQuickTransition *QQStyleKitControlProperties::transition() const
2034{
2035 return styleProperty<QQuickTransition *>(QQSK::Property::Transition);
2036}
2037
2038void QQStyleKitControlProperties::setTransition(QQuickTransition *transition)
2039{
2040 if (setStyleProperty(QQSK::Property::Transition, transition))
2041 handleStylePropertyChanged(&QQStyleKitControlProperties::transitionChanged);
2042}
2043
2044QQStyleKitTextProperties *QQStyleKitControlProperties::text() const
2045{
2046 return lazyCreateGroup(m_text, QQSK::PropertyGroup::Text);
2047}
2048
2049QQStyleKitDelegateProperties *QQStyleKitControlProperties::background() const
2050{
2051 return lazyCreateGroup(m_background, QQSK::PropertyGroup::Background);
2052}
2053
2054QQStyleKitHandleProperties *QQStyleKitControlProperties::handle() const
2055{
2056 return lazyCreateGroup(m_handle, QQSK::PropertyGroup::Handle);
2057}
2058
2059QQStyleKitIndicatorWithSubTypes *QQStyleKitControlProperties::indicator() const
2060{
2061 return lazyCreateGroup(m_indicator, QQSK::PropertyGroup::Indicator);
2062}
2063
2064QT_END_NAMESPACE
2065
2066#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
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)