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