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
qqstylekitcontrols.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
7
9
10/*!
11 \qmltype AbstractStylableControls
12 \inqmlmodule Qt.labs.StyleKit
13 \brief Abstract base type containing the control types that can be styled.
14
15 AbstractControls is an abstract base type. It contains a \l ControlStyle for
16 each control type that can be styled by a \l Style, \l Theme, or \l StyleVariation.
17
18 The control types form a hierarchy where properties set on a base type
19 propagate down to the more specific ones. For example, assigning a radius
20 of four to \c abstractButton.background.radius will cause all button
21 types, such as \l button, \l checkBox, and \l radioButton, to get a radius
22 of four.
23
24 The snippets on this page illustrate a few of the key properties that can be
25 used to style each control type, but they are by no means exhaustive. Many other properties
26 are available, as documented in the \l ControlStyle and \l DelegateStyle documentation.
27 In practice, some of them can also be omitted because the
28 \l {Style::fallbackStyle}{fallback style} already supplies sensible defaults.
29 This means that if you simply remove a property from one of the snippets, it
30 might not actually affect its appearance, since it will just be read from the
31 fallback style instead.
32
33 \sa {StyleKit Property Resolution}
34
35 \labs
36*/
37
38/*!
39 \qmlproperty ControlStyle AbstractStylableControls::control
40
41 Grouped property for styling all controls.
42
43 \c control is the base type in the control hierarchy, and properties set here
44 serve as defaults for all other control types. For example, setting
45 \c{control.implicitWidth: 200} makes \e all controls 200 pixels wide,
46 including buttons, scroll indicators and every other control.
47 It also overrides any values inherited from a higher level in the style
48 hierarchy (the \l Style for a \l Theme, or the
49 \l {Style::fallbackStyle}{fallbackStyle} for a \l Style), \e including hover
50 effects and other state-based behavior. Use \c{control} sparingly, and
51 prefer more specific base types like \l abstractButton or \l pane when
52 possible.
53
54 \snippet ControlsSnippets.qml control
55*/
56
57/*!
58 \qmlproperty ControlStyle AbstractStylableControls::abstractButton
59
60 Grouped property for styling all button-like controls, including
61 \l [QtQuickControls]{Button}, \l [QtQuickControls]{CheckBox},
62 \l [QtQuickControls]{RadioButton}, \l [QtQuickControls]{Switch}
63 and \l [QtQuickControls]{RoundButton}.
64 Unset properties fall back to \l control.
65
66 \snippet ControlsSnippets.qml abstractButton
67
68 \sa {Qt Labs StyleKit}{Control Types}
69*/
70
71/*!
72 \qmlproperty ControlStyle AbstractStylableControls::applicationWindow
73
74 Grouped property for styling \l [QtQuickControls] ApplicationWindow.
75
76 Unset properties fall back to \l control.
77
78 Use \c applicationWindow to set the background color of the window:
79
80 \snippet ControlsSnippets.qml applicationWindow
81
82 \note The application needs to use ApplicationWindow, not Window, for this to take effect.
83*/
84
85/*!
86 \qmlproperty ControlStyle AbstractStylableControls::button
87
88 Grouped property for styling \l [QtQuickControls]{Button}.
89
90 Unset properties fall back to \l abstractButton.
91
92 \snippet ControlsSnippets.qml button
93*/
94
95/*!
96 \qmlproperty ControlStyle AbstractStylableControls::checkBox
97
98 Grouped property for styling \l [QtQuickControls]{CheckBox}.
99
100 Unset properties fall back to \l abstractButton.
101
102 \snippet ControlsSnippets.qml checkBox
103*/
104
105/*!
106 \qmlproperty ControlStyle AbstractStylableControls::comboBox
107
108 Grouped property for styling \l [QtQuickControls]{ComboBox}.
109
110 Unset properties fall back to \l control.
111
112 \snippet ControlsSnippets.qml comboBox
113*/
114
115/*!
116 \qmlproperty ControlStyle AbstractStylableControls::flatButton
117
118 Grouped property for styling flat buttons (buttons with no visible
119 background in their normal state). The styling will take effect for
120 a \l [QtQuickControls]{Button} if \l [QtQuickControls]{Button::flat}{Button.flat} is set to \c true.
121
122 Unset properties fall back to \l abstractButton.
123
124 \snippet ControlsSnippets.qml flatButton
125*/
126
127/*!
128 \qmlproperty ControlStyle AbstractStylableControls::frame
129
130 Grouped property for styling \l [QtQuickControls]{Frame}.
131
132 Unset properties fall back to \l pane.
133
134 \snippet ControlsSnippets.qml frame
135*/
136
137/*!
138 \qmlproperty ControlStyle AbstractStylableControls::groupBox
139
140 Grouped property for styling \l [QtQuickControls]{GroupBox}.
141
142 Unset properties fall back to \l frame.
143
144 \snippet ControlsSnippets.qml groupBox
145*/
146
147/*!
148 \qmlproperty ControlStyle AbstractStylableControls::itemDelegate
149
150 Grouped property for styling \l [QtQuickControls]{ItemDelegate}.
151
152 Unset properties fall back to \l control.
153
154 \note In Qt Quick Controls, \l [QtQuickControls]{ItemDelegate} inherits from
155 \l [QtQuickControls]{AbstractButton}. In StyleKit, however, \c itemDelegate
156 falls back to \l control rather than \l abstractButton, since delegates are
157 typically \e styled very differently from buttons (flat, no borders or drop shadows, etc.).
158
159 \snippet ControlsSnippets.qml itemDelegate
160*/
161
162/*!
163 \qmlproperty ControlStyle AbstractStylableControls::label
164
165 Grouped property for styling \l [QtQuickControls]{Label}.
166
167 Unset properties fall back to \l control.
168
169 \snippet ControlsSnippets.qml label
170*/
171
172/*!
173 \qmlproperty ControlStyle AbstractStylableControls::menu
174
175 Grouped property for styling \l [QtQuickControls]{Menu}.
176
177 Unset properties fall back to \l popup.
178
179 \snippet ControlsSnippets.qml menu
180*/
181
182/*
183 \qmlproperty ControlStyle AbstractStylableControls::menuItem
184
185 Grouped property for styling \l [QtQuickControls]{MenuItem}.
186
187 Unset properties fall back to \l control.
188
189 \note In Qt Quick Controls, a \l [QtQuickControls]{MenuItem} inherits from
190    \l [QtQuickControls]{AbstractButton}. In StyleKit, however, \c menuItem
191 falls back to \l control instead of \l abstractButton, since menu items are
192 typically \e styled very differently from regular buttons
193 (flat, no borders or drop shadows, etc.).
194
195 \snippet ControlsSnippets.qml menuItem
196*/
197
198/*!
199 \qmlproperty ControlStyle AbstractStylableControls::menuBar
200
201 Grouped property for styling \l [QtQuickControls]{MenuBar}.
202
203 Unset properties fall back to \l control.
204
205 \note Styling \l [QtQuickControls]{MenuBar}, \l [QtQuickControls]{MenuBarItem},
206 and \l [QtQuickControls]{MenuSeparator} normally only affects non-native
207 menu bars. When a MenuBar is implemented as a native menu bar, its delegates
208 are not used for rendering, so StyleKit style properties may have no visual
209 effect. See \l {MenuBar QML Type} {Native Menu Bars} for details.
210
211 \snippet ControlsSnippets.qml menuBar
212*/
213
214/*
215 \qmlproperty ControlStyle AbstractStylableControls::menuBarItem
216
217 Grouped property for styling menu items in a \l [QtQuickControls]{MenuBar}.
218
219 Unset properties fall back to \l control.
220
221 \note In Qt Quick Controls, a \l [QtQuickControls]{MenuBarItem} inherits from
222 \l [QtQuickControls]{AbstractButton}. In StyleKit, however, \c menuBarItem is a
223 separate control type that falls back to \l control instead of \l abstractButton,
224 since menu bar items are typically styled very differently from regular buttons
225 (flat, no borders or drop shadows, etc.).
226
227 \snippet ControlsSnippets.qml menuBarItem
228*/
229
230/*
231 \qmlproperty ControlStyle AbstractStylableControls::menuSeparator
232
233 Grouped property for styling \l [QtQuickControls]{MenuSeparator}.
234
235 Unset properties fall back to \l control.
236
237 \snippet ControlsSnippets.qml menuSeparator
238*/
239
240/*!
241 \qmlproperty ControlStyle AbstractStylableControls::page
242
243 Grouped property for styling \l [QtQuickControls]{Page}.
244
245 Unset properties fall back to \l pane.
246
247 Note that the \l [QtQuickControls]{Page::header}{header} and
248 \l [QtQuickControls]{Page::footer}{footer} of a \l [QtQuickControls]{Page} are
249 typically set by the application to a \l [QtQuickControls]{ToolBar} or
250 \l [QtQuickControls]{TabBar}, and those controls are styled separately.
251 To give a \l [QtQuickControls]{ToolBar} alternative styling when used inside
252 a \l [QtQuickControls]{Page}, use a \l StyleVariation:
253
254 \snippet ControlsSnippets.qml page
255*/
256
257/*!
258 \qmlproperty ControlStyle AbstractStylableControls::pane
259
260 Grouped property for styling \l [QtQuickControls]{Pane}.
261
262 Unset properties fall back to \l control.
263
264 \snippet ControlsSnippets.qml pane
265*/
266
267/*!
268 \qmlproperty ControlStyle AbstractStylableControls::popup
269
270 Grouped property for styling \l [QtQuickControls]{Popup}.
271
272 Unset properties fall back to \l control.
273
274 \snippet ControlsSnippets.qml popup
275*/
276
277/*!
278 \qmlproperty ControlStyle AbstractStylableControls::progressBar
279
280 Grouped property for styling \l [QtQuickControls]{ProgressBar}.
281 For a progress bar, the groove is styled through the indicator, while the progress
282 track is styled through the indicator's foreground.
283
284 Unset properties fall back to \l control.
285
286 \snippet ControlsSnippets.qml progressBar
287
288 StyleKit doesn't provide a dedicated property to style the indeterminate animation
289 of a progress bar. To change the animation, you need to implement a custom indicator
290 foreground \l {DelegateStyle::}{delegate} instead:
291
292 \snippet ControlsSnippets.qml progressBar indeterminate
293*/
294
295/*!
296 \qmlproperty ControlStyle AbstractStylableControls::radioButton
297
298 Grouped property for styling \l [QtQuickControls]{RadioButton}.
299
300 Unset properties fall back to \l abstractButton.
301
302 \snippet ControlsSnippets.qml radioButton
303*/
304
305/*!
306 \qmlproperty ControlStyle AbstractStylableControls::roundButton
307
308 Grouped property for styling \l [QtQuickControls]{RoundButton}.
309
310 Unset properties fall back to \l abstractButton.
311
312 \snippet ControlsSnippets.qml roundButton
313*/
314
315/*!
316 \qmlproperty ControlStyle AbstractStylableControls::scrollBar
317
318 Grouped property for styling \l [QtQuickControls]{ScrollBar}.
319 The groove is styled through \l {ControlStyleProperties::}{background}, and the
320 handle through \l {ControlStyleProperties::}{indicator}.
321
322 Unset properties fall back to \l control.
323
324 \snippet ControlsSnippets.qml scrollBar
325*/
326
327/*!
328 \qmlproperty ControlStyle AbstractStylableControls::scrollIndicator
329
330 Grouped property for styling \l [QtQuickControls]{ScrollIndicator}.
331 The groove is styled through \l {ControlStyleProperties::}{background}, and the
332 handle through \l {ControlStyleProperties::}{indicator}.
333
334 Unset properties fall back to \l control.
335
336 \snippet ControlsSnippets.qml scrollIndicator
337*/
338
339/*!
340 \qmlproperty ControlStyle AbstractStylableControls::scrollView
341
342 Grouped property for styling \l [QtQuickControls]{ScrollView}.
343
344 ScrollView itself has no visual delegates to style. Its scroll bars can be
345 styled separately through the \l scrollBar property. But you can use
346 \l {ControlStateStyle::padding}{padding} to control the space between
347 the scroll bars and the content area.
348
349 Unset properties fall back to \l control.
350
351 \snippet ControlsSnippets.qml scrollView
352*/
353
354/*
355 \qmlproperty ControlStyle AbstractStylableControls::searchField
356
357 Grouped property for styling \l [QtQuickControls]{SearchField}.
358
359 Unset properties fall back to \l control.
360
361 \snippet ControlsSnippets.qml searchfield
362*/
363
364/*!
365 \qmlproperty ControlStyle AbstractStylableControls::slider
366
367 Grouped property for styling \l [QtQuickControls]{Slider}.
368 For a slider bar, the groove is styled through the indicator, while the progress
369 track is styled through the indicator's foreground.
370 Unset properties fall back to \l control.
371
372 For vertical sliders, swap the \l {DelegateStyle::implicitWidth}{implicitWidth}
373 and \l {DelegateStyle::implicitHeight}{implicitHeight} of the relevant delegates
374 so that the control is taller than it is wide, as shown in the snippet below.
375
376 \snippet ControlsSnippets.qml slider
377*/
378
379/*!
380 \qmlproperty ControlStyle AbstractStylableControls::spinBox
381
382 Grouped property for styling \l [QtQuickControls]{SpinBox}.
383
384 Unset properties fall back to \l control.
385
386 \snippet ControlsSnippets.qml spinBox
387
388 \note It's currently only possible to position the up and down buttons to
389 be on the left or right side of the control, but not on top of each other.
390*/
391
392/*!
393 \qmlproperty ControlStyle AbstractStylableControls::switchControl
394
395 Grouped property for styling \l [QtQuickControls]{Switch}.
396
397 Unset properties fall back to \l abstractButton.
398
399 \snippet ControlsSnippets.qml switchControl
400*/
401
402/*!
403 \qmlproperty ControlStyle AbstractStylableControls::tabBar
404
405 Grouped property for styling \l [QtQuickControls]{TabBar}.
406
407 Unset properties fall back to \l pane.
408
409 \snippet ControlsSnippets.qml tabBar
410*/
411
412/*!
413 \qmlproperty ControlStyle AbstractStylableControls::tabButton
414
415 Grouped property for styling \l [QtQuickControls]{TabButton}.
416
417 Unset properties fall back to \l abstractButton.
418
419 \snippet ControlsSnippets.qml tabButton
420*/
421
422/*!
423 \qmlproperty ControlStyle AbstractStylableControls::textArea
424
425 Grouped property for styling \l [QtQuickControls]{TextArea}.
426
427 Unset properties fall back to \l textInput.
428
429 \snippet ControlsSnippets.qml textArea
430*/
431
432/*!
433 \qmlproperty ControlStyle AbstractStylableControls::textField
434
435 Grouped property for styling \l [QtQuickControls]{TextField}.
436
437 Unset properties fall back to \l textInput.
438
439 \snippet ControlsSnippets.qml textField
440*/
441
442/*!
443 \qmlproperty ControlStyle AbstractStylableControls::textInput
444
445 Grouped property for styling all text input controls, including
446 \l [QtQuickControls]{TextField} and \l [QtQuickControls]{TextArea}.
447
448 Unset properties fall back to \l control.
449
450 \snippet ControlsSnippets.qml textInput
451*/
452
453/*!
454 \qmlproperty ControlStyle AbstractStylableControls::toolBar
455
456 Grouped property for styling \l [QtQuickControls]{ToolBar}.
457
458 Unset properties fall back to \l pane.
459
460 \snippet ControlsSnippets.qml toolBar
461*/
462
463/*!
464 \qmlproperty ControlStyle AbstractStylableControls::toolButton
465
466 Grouped property for styling \l [QtQuickControls]{ToolButton}.
467
468 Unset properties fall back to \l abstractButton.
469
470 \snippet ControlsSnippets.qml toolButton
471*/
472
473/*!
474 \qmlproperty ControlStyle AbstractStylableControls::toolSeparator
475
476 Grouped property for styling \l [QtQuickControls]{ToolSeparator}.
477
478 Unset properties fall back to \l control.
479
480 For vertical separators, swap the \l {DelegateStyle::implicitWidth}{implicitWidth}
481 and \l {DelegateStyle::implicitHeight}{implicitHeight} of the relevant delegates
482 so that the control is taller than it is wide, as shown in the snippet below.
483
484 \snippet ControlsSnippets.qml toolSeparator
485*/
486
487using namespace Qt::StringLiterals;
488
489QQStyleKitControls::QQStyleKitControls(QObject *parent)
490 : QObject(parent)
491{
492}
493
495{
496 return QQmlListProperty<QObject>(this, &m_data);
497}
498
500{
501 return m_data;
502}
503
504/* Lazy-create the controls that the style is actually using, when accessed
505 * from the style/application (e.g from Style or Theme). We don't lazy
506 * create any controls while resolving style properties, as undefined controls would
507 * anyway not contain any property overrides. The properties have setters too, to
508 * allow the style/application to share custom ControlStyle the classical
509 * way, e.g button: ControlStyle { id: button }. */
510QQStyleKitControl* QQStyleKitControls::getControl(QQStyleKitExtendableControlType controlType) const
511{
512 return m_controls.value(controlType, nullptr);
513}
514
515#define IMPLEMENT_ACCESSORS(NAME, TYPE) QQStyleKitControl
516 *QQStyleKitControls::NAME() const \
517{
518 if (!m_controls.contains(TYPE)) {
519 auto *self = const_cast<QQStyleKitControls *>(this);
520 auto *control = new QQStyleKitControl(self);
521 self->m_controls.insert(TYPE, control);
522 }
523 return m_controls[TYPE]; \
524}void
525 QQStyleKitControls::set_ ## NAME(QQStyleKitControl *control) \
526{
527 m_controls.insert(TYPE, control); \
528}
529
530
531IMPLEMENT_ACCESSORS(abstractButton, QQStyleKitReader::ControlType::AbstractButton)
532IMPLEMENT_ACCESSORS(applicationWindow, QQStyleKitReader::ControlType::ApplicationWindow)
533IMPLEMENT_ACCESSORS(control, QQStyleKitReader::ControlType::Control)
534IMPLEMENT_ACCESSORS(button, QQStyleKitReader::ControlType::Button)
535IMPLEMENT_ACCESSORS(flatButton, QQStyleKitReader::ControlType::FlatButton)
536IMPLEMENT_ACCESSORS(checkBox, QQStyleKitReader::ControlType::CheckBox)
537IMPLEMENT_ACCESSORS(comboBox, QQStyleKitReader::ControlType::ComboBox)
538IMPLEMENT_ACCESSORS(progressBar, QQStyleKitReader::ControlType::ProgressBar)
539IMPLEMENT_ACCESSORS(scrollBar, QQStyleKitReader::ControlType::ScrollBar)
540IMPLEMENT_ACCESSORS(scrollIndicator, QQStyleKitReader::ControlType::ScrollIndicator)
541IMPLEMENT_ACCESSORS(scrollView, QQStyleKitReader::ControlType::ScrollView)
542IMPLEMENT_ACCESSORS(searchField, QQStyleKitReader::SearchField)
543IMPLEMENT_ACCESSORS(slider, QQStyleKitReader::ControlType::Slider)
544IMPLEMENT_ACCESSORS(spinBox, QQStyleKitReader::ControlType::SpinBox)
545IMPLEMENT_ACCESSORS(switchControl, QQStyleKitReader::ControlType::SwitchControl)
546IMPLEMENT_ACCESSORS(tabBar, QQStyleKitReader::ControlType::TabBar)
547IMPLEMENT_ACCESSORS(tabButton, QQStyleKitReader::ControlType::TabButton)
548IMPLEMENT_ACCESSORS(textField, QQStyleKitReader::ControlType::TextField)
549IMPLEMENT_ACCESSORS(textInput, QQStyleKitReader::ControlType::TextInput)
550IMPLEMENT_ACCESSORS(toolBar, QQStyleKitReader::ControlType::ToolBar)
551IMPLEMENT_ACCESSORS(toolButton, QQStyleKitReader::ControlType::ToolButton)
552IMPLEMENT_ACCESSORS(toolSeparator, QQStyleKitReader::ControlType::ToolSeparator)
553IMPLEMENT_ACCESSORS(radioButton, QQStyleKitReader::ControlType::RadioButton)
554IMPLEMENT_ACCESSORS(roundButton, QQStyleKitReader::ControlType::RoundButton)
555IMPLEMENT_ACCESSORS(itemDelegate, QQStyleKitReader::ControlType::ItemDelegate)
556IMPLEMENT_ACCESSORS(popup, QQStyleKitReader::ControlType::Popup)
557IMPLEMENT_ACCESSORS(pane, QQStyleKitReader::ControlType::Pane)
558IMPLEMENT_ACCESSORS(page, QQStyleKitReader::ControlType::Page)
559IMPLEMENT_ACCESSORS(frame, QQStyleKitReader::ControlType::Frame)
560IMPLEMENT_ACCESSORS(label, QQStyleKitReader::ControlType::Label)
561IMPLEMENT_ACCESSORS(groupBox, QQStyleKitReader::ControlType::GroupBox)
562IMPLEMENT_ACCESSORS(textArea, QQStyleKitReader::ControlType::TextArea)
563IMPLEMENT_ACCESSORS(menu, QQStyleKitReader::ControlType::Menu)
564IMPLEMENT_ACCESSORS(menuBar, QQStyleKitReader::ControlType::MenuBar)
565IMPLEMENT_ACCESSORS(menuBarItem, QQStyleKitReader::ControlType::MenuBarItem)
566IMPLEMENT_ACCESSORS(menuItem, QQStyleKitReader::ControlType::MenuItem)
567IMPLEMENT_ACCESSORS(menuSeparator, QQStyleKitReader::ControlType::MenuSeparator)
568
569#undef IMPLEMENT_ACCESSORS
570
572{
573 for (auto *obj : children()) {
574 if (auto *customControl = qobject_cast<QQStyleKitCustomControl *>(obj)) {
575 const QQStyleKitExtendableControlType type = customControl->controlType();
576 const QQStyleKitExtendableControlType reserved
577 = QQStyleKitExtendableControlType(QQStyleKitReader::ControlType::Unspecified);
578 if (type >= reserved)
579 qmlWarning(this) << "CustomControls must use a controlType less than " << reserved;
580 if (m_controls.contains(type))
581 qmlWarning(this) << "CustomControl registered more than once: " << type;
582 m_controls.insert(type, customControl);
583 }
584 }
585}
586
587QT_END_NAMESPACE
588
589#include "moc_qqstylekitcontrols_p.cpp"
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
const QList< QObject * > children() const
QQmlListProperty< QObject > data()
Combined button and popup list for selecting options.
#define IMPLEMENT_ACCESSORS(NAME, TYPE)