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