1// Copyright (C) 2017 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
4#include "qquickcontrol_p.h"
5#include "qquickcontrol_p_p.h"
6
7#include <QtGui/qstylehints.h>
8#include <QtGui/qguiapplication.h>
9#include "qquicklabel_p.h"
10#include "qquicklabel_p_p.h"
11#include "qquicktemplatesutils_p.h"
12#include "qquicktextarea_p.h"
13#include "qquicktextarea_p_p.h"
14#include "qquicktextfield_p.h"
15#include "qquicktextfield_p_p.h"
16#include "qquickpopup_p.h"
17#include "qquickpopupitem_p_p.h"
18#include "qquickapplicationwindow_p.h"
19#include "qquickapplicationwindow_p_p.h"
20#include "qquickdeferredexecute_p_p.h"
21#include "qquickcontentitem_p.h"
22
23#if QT_CONFIG(accessibility)
24#include <QtQuick/private/qquickaccessibleattached_p.h>
25#endif
26
27QT_BEGIN_NAMESPACE
28
29Q_LOGGING_CATEGORY(lcItemManagement, "qt.quick.controls.control.itemmanagement")
30
31/*!
32 \qmltype Control
33 \inherits Item
34//! \nativetype QQuickControl
35 \inqmlmodule QtQuick.Controls
36 \since 5.7
37 \brief Abstract base type providing functionality common to all controls.
38
39 Control is the base type of user interface controls. It receives input
40 events from the window system, and paints a representation of itself on
41 the screen.
42
43 \section1 Control Layout
44
45 The following diagram illustrates the layout of a typical control:
46
47 \image qtquickcontrols-control.png
48
49 The \l {Item::}{implicitWidth} and \l {Item::}{implicitHeight} of a control
50 are typically based on the implicit sizes of the background and the content
51 item plus any insets and paddings. These properties determine how large
52 the control will be when no explicit \l {Item::}{width} or
53 \l {Item::}{height} is specified.
54
55 The geometry of the \l {Control::}{contentItem} is determined by the padding.
56 The following example reserves 10px padding between the boundaries of the
57 control and its content:
58
59 \code
60 Control {
61 padding: 10
62
63 contentItem: Text {
64 text: "Content"
65 }
66 }
67 \endcode
68
69 The \l {Control::}{background} item fills the entire width and height of the
70 control, unless insets or an explicit size have been given for it. Background
71 insets are useful for extending the touchable/interactive area of a control
72 without affecting its visual size. This is often used on touch devices to
73 ensure that a control is not too small to be interacted with by the user.
74 Insets affect the size of the control, and hence will affect how much space
75 they take up in a layout, for example.
76
77 Negative insets can be used to make the background larger than the control.
78 The following example uses negative insets to place a shadow outside the
79 control's boundaries:
80
81 \code
82 Control {
83 topInset: -2
84 leftInset: -2
85 rightInset: -6
86 bottomInset: -6
87
88 background: BorderImage {
89 source: ":/images/shadowed-background.png"
90 }
91 }
92 \endcode
93
94 \section1 Event Handling
95
96 All controls, except non-interactive indicators, do not let clicks and
97 touches through to items below them. For example, the \c console.log()
98 call in the example below will never be executed when clicking on the
99 Pane, because the \l MouseArea is below it in the scene:
100
101 \code
102 MouseArea {
103 anchors.fill: parent
104 onClicked: console.log("MouseArea was clicked")
105
106 Pane {
107 anchors.fill: parent
108 }
109 }
110 \endcode
111
112 Wheel events are consumed by controls if \l wheelEnabled is \c true.
113
114 \sa ApplicationWindow, Container, {Using Qt Quick Controls types in
115 property declarations}
116*/
117
118const QQuickItemPrivate::ChangeTypes QQuickControlPrivate::ImplicitSizeChanges = QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed;
119
120static bool isKeyFocusReason(Qt::FocusReason reason)
121{
122 return reason == Qt::TabFocusReason || reason == Qt::BacktabFocusReason || reason == Qt::ShortcutFocusReason;
123}
124
125QQuickControlPrivate::QQuickControlPrivate()
126{
127#if QT_CONFIG(accessibility)
128 QAccessible::installActivationObserver(this);
129#endif
130}
131
132QQuickControlPrivate::~QQuickControlPrivate()
133{
134}
135
136void QQuickControlPrivate::init()
137{
138 Q_Q(QQuickControl);
139 QObject::connect(sender: q, signal: &QQuickItem::baselineOffsetChanged, context: q, slot: &QQuickControl::baselineOffsetChanged);
140}
141
142#if QT_CONFIG(quicktemplates2_multitouch)
143bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point)
144{
145 if (point.id() == touchId)
146 return true;
147
148 if (touchId == -1 && point.state() == QEventPoint::Pressed) {
149 touchId = point.id();
150 return true;
151 }
152
153 return false;
154}
155#endif
156
157bool QQuickControlPrivate::handlePress(const QPointF &, ulong)
158{
159 return true;
160}
161
162bool QQuickControlPrivate::handleMove(const QPointF &point, ulong)
163{
164#if QT_CONFIG(quicktemplates2_hover)
165 Q_Q(QQuickControl);
166 q->setHovered(hoverEnabled && q->contains(point));
167#else
168 Q_UNUSED(point);
169#endif
170 return true;
171}
172
173bool QQuickControlPrivate::handleRelease(const QPointF &, ulong)
174{
175 touchId = -1;
176 return true;
177}
178
179void QQuickControlPrivate::handleUngrab()
180{
181 touchId = -1;
182}
183
184void QQuickControlPrivate::mirrorChange()
185{
186 Q_Q(QQuickControl);
187 q->mirrorChange();
188}
189
190void QQuickControlPrivate::setTopPadding(qreal value, bool reset)
191{
192 Q_Q(QQuickControl);
193 const QMarginsF oldPadding = getPadding();
194 extra.value().topPadding = value;
195 extra.value().hasTopPadding = !reset;
196 if ((!reset && !qFuzzyCompare(p1: oldPadding.top(), p2: value)) || (reset && !qFuzzyCompare(p1: oldPadding.top(), p2: getVerticalPadding()))) {
197 emit q->topPaddingChanged();
198 emit q->availableHeightChanged();
199 q->paddingChange(newPadding: getPadding(), oldPadding);
200 }
201}
202
203void QQuickControlPrivate::setLeftPadding(qreal value, bool reset)
204{
205 Q_Q(QQuickControl);
206 const QMarginsF oldPadding = getPadding();
207 extra.value().leftPadding = value;
208 extra.value().hasLeftPadding = !reset;
209 if ((!reset && !qFuzzyCompare(p1: oldPadding.left(), p2: value)) || (reset && !qFuzzyCompare(p1: oldPadding.left(), p2: getHorizontalPadding()))) {
210 emit q->leftPaddingChanged();
211 emit q->availableWidthChanged();
212 q->paddingChange(newPadding: getPadding(), oldPadding);
213 }
214}
215
216void QQuickControlPrivate::setRightPadding(qreal value, bool reset)
217{
218 Q_Q(QQuickControl);
219 const QMarginsF oldPadding = getPadding();
220 extra.value().rightPadding = value;
221 extra.value().hasRightPadding = !reset;
222 if ((!reset && !qFuzzyCompare(p1: oldPadding.right(), p2: value)) || (reset && !qFuzzyCompare(p1: oldPadding.right(), p2: getHorizontalPadding()))) {
223 emit q->rightPaddingChanged();
224 emit q->availableWidthChanged();
225 q->paddingChange(newPadding: getPadding(), oldPadding);
226 }
227}
228
229void QQuickControlPrivate::setBottomPadding(qreal value, bool reset)
230{
231 Q_Q(QQuickControl);
232 const QMarginsF oldPadding = getPadding();
233 extra.value().bottomPadding = value;
234 extra.value().hasBottomPadding = !reset;
235 if ((!reset && !qFuzzyCompare(p1: oldPadding.bottom(), p2: value)) || (reset && !qFuzzyCompare(p1: oldPadding.bottom(), p2: getVerticalPadding()))) {
236 emit q->bottomPaddingChanged();
237 emit q->availableHeightChanged();
238 q->paddingChange(newPadding: getPadding(), oldPadding);
239 }
240}
241
242void QQuickControlPrivate::setHorizontalPadding(qreal value, bool reset)
243{
244 Q_Q(QQuickControl);
245 const QMarginsF oldPadding = getPadding();
246 const qreal oldHorizontalPadding = getHorizontalPadding();
247 horizontalPadding = value;
248 hasHorizontalPadding = !reset;
249 if ((!reset && !qFuzzyCompare(p1: oldHorizontalPadding, p2: value)) || (reset && !qFuzzyCompare(p1: oldHorizontalPadding, p2: padding))) {
250 const QMarginsF newPadding = getPadding();
251 if (!qFuzzyCompare(p1: newPadding.left(), p2: oldPadding.left()))
252 emit q->leftPaddingChanged();
253 if (!qFuzzyCompare(p1: newPadding.right(), p2: oldPadding.right()))
254 emit q->rightPaddingChanged();
255 emit q->horizontalPaddingChanged();
256 emit q->availableWidthChanged();
257 q->paddingChange(newPadding, oldPadding);
258 }
259}
260
261void QQuickControlPrivate::setVerticalPadding(qreal value, bool reset)
262{
263 Q_Q(QQuickControl);
264 const QMarginsF oldPadding = getPadding();
265 const qreal oldVerticalPadding = getVerticalPadding();
266 verticalPadding = value;
267 hasVerticalPadding = !reset;
268 if ((!reset && !qFuzzyCompare(p1: oldVerticalPadding, p2: value)) || (reset && !qFuzzyCompare(p1: oldVerticalPadding, p2: padding))) {
269 const QMarginsF newPadding = getPadding();
270 if (!qFuzzyCompare(p1: newPadding.top(), p2: oldPadding.top()))
271 emit q->topPaddingChanged();
272 if (!qFuzzyCompare(p1: newPadding.bottom(), p2: oldPadding.bottom()))
273 emit q->bottomPaddingChanged();
274 emit q->verticalPaddingChanged();
275 emit q->availableHeightChanged();
276 q->paddingChange(newPadding, oldPadding);
277 }
278}
279
280void QQuickControlPrivate::setTopInset(qreal value, bool reset)
281{
282 Q_Q(QQuickControl);
283 const QMarginsF oldInset = getInset();
284 extra.value().topInset = value;
285 extra.value().hasTopInset = !reset;
286 if (!qFuzzyCompare(p1: oldInset.top(), p2: value)) {
287 emit q->topInsetChanged();
288 q->insetChange(newInset: getInset(), oldInset);
289 }
290}
291
292void QQuickControlPrivate::setLeftInset(qreal value, bool reset)
293{
294 Q_Q(QQuickControl);
295 const QMarginsF oldInset = getInset();
296 extra.value().leftInset = value;
297 extra.value().hasLeftInset = !reset;
298 if (!qFuzzyCompare(p1: oldInset.left(), p2: value)) {
299 emit q->leftInsetChanged();
300 q->insetChange(newInset: getInset(), oldInset);
301 }
302}
303
304void QQuickControlPrivate::setRightInset(qreal value, bool reset)
305{
306 Q_Q(QQuickControl);
307 const QMarginsF oldInset = getInset();
308 extra.value().rightInset = value;
309 extra.value().hasRightInset = !reset;
310 if (!qFuzzyCompare(p1: oldInset.right(), p2: value)) {
311 emit q->rightInsetChanged();
312 q->insetChange(newInset: getInset(), oldInset);
313 }
314}
315
316void QQuickControlPrivate::setBottomInset(qreal value, bool reset)
317{
318 Q_Q(QQuickControl);
319 const QMarginsF oldInset = getInset();
320 extra.value().bottomInset = value;
321 extra.value().hasBottomInset = !reset;
322 if (!qFuzzyCompare(p1: oldInset.bottom(), p2: value)) {
323 emit q->bottomInsetChanged();
324 q->insetChange(newInset: getInset(), oldInset);
325 }
326}
327
328void QQuickControlPrivate::resizeBackground()
329{
330 if (!background)
331 return;
332
333 resizingBackground = true;
334
335 QQuickItemPrivate *p = QQuickItemPrivate::get(item: background);
336 bool changeWidth = false;
337 bool changeHeight = false;
338 if (((!p->widthValid() || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(d: background->x()))
339 || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
340 const auto leftInset = getLeftInset();
341 if (!qt_is_nan(d: leftInset) && p->x.valueBypassingBindings() != leftInset) {
342 // We bypass the binding here to prevent it from being removed
343 p->x.setValueBypassingBindings(leftInset);
344 p->dirty(DirtyType::Position);
345 }
346 changeWidth = !p->width.hasBinding();
347 }
348 if (((!p->heightValid() || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(d: background->y()))
349 || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
350 const auto topInset = getTopInset();
351 if (!qt_is_nan(d: topInset) && p->y.valueBypassingBindings() != topInset) {
352 // We bypass the binding here to prevent it from being removed
353 p->y.setValueBypassingBindings(topInset);
354 p->dirty(DirtyType::Position);
355 }
356 changeHeight = !p->height.hasBinding();
357 }
358 if (changeHeight || changeWidth) {
359 auto newWidth = changeWidth ?
360 width.valueBypassingBindings() - getLeftInset() - getRightInset() :
361 p->width.valueBypassingBindings();
362 auto newHeight = changeHeight ?
363 height.valueBypassingBindings() - getTopInset() - getBottomInset() :
364 p->height.valueBypassingBindings();
365 background->setSize({newWidth, newHeight});
366 }
367
368 resizingBackground = false;
369}
370
371void QQuickControlPrivate::resizeContent()
372{
373 Q_Q(QQuickControl);
374 if (contentItem) {
375 contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding()));
376 contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight()));
377 }
378}
379
380QQuickItem *QQuickControlPrivate::getContentItem()
381{
382 if (!contentItem)
383 executeContentItem();
384 return contentItem;
385}
386
387void QQuickControlPrivate::setContentItem_helper(QQuickItem *item, bool notify)
388{
389 Q_Q(QQuickControl);
390 if (contentItem == item)
391 return;
392
393 if (notify)
394 warnIfCustomizationNotSupported(control: q, item, QStringLiteral("contentItem"));
395
396 if (!contentItem.isExecuting())
397 cancelContentItem();
398
399 QQuickItem *oldContentItem = contentItem;
400 if (oldContentItem) {
401 disconnect(sender: oldContentItem, signal: &QQuickItem::baselineOffsetChanged, receiverPrivate: this, slot: &QQuickControlPrivate::updateBaselineOffset);
402 QQuickItemPrivate::get(item: oldContentItem)->removeItemChangeListener(this, types: QQuickControlPrivate::Focus);
403 removeImplicitSizeListener(item: oldContentItem);
404 }
405
406 contentItem = item;
407 q->contentItemChange(newItem: item, oldItem: oldContentItem);
408 QQuickControlPrivate::hideOldItem(item: oldContentItem);
409
410 if (item) {
411 connect(sender: contentItem.data(), signal: &QQuickItem::baselineOffsetChanged, receiverPrivate: this, slot: &QQuickControlPrivate::updateBaselineOffset);
412 // We need to update the control's focusReason when the contentItem receives or loses focus. Since focusPolicy
413 // (or other properties impacting focus handling, like QQuickItem::activeFocusOnTab) might change later, and
414 // since the content item might also change focus programmatically, we always have to listen for those events.
415 QQuickItemPrivate::get(item)->addItemChangeListener(listener: this, types: QQuickControlPrivate::Focus);
416 if (!item->parentItem())
417 item->setParentItem(q);
418 if (componentComplete)
419 resizeContent();
420 addImplicitSizeListener(item: contentItem);
421 }
422
423 updateImplicitContentSize();
424 updateBaselineOffset();
425
426 if (notify && !contentItem.isExecuting())
427 emit q->contentItemChanged();
428}
429
430qreal QQuickControlPrivate::getContentWidth() const
431{
432 return contentItem ? contentItem->implicitWidth() : 0;
433}
434
435qreal QQuickControlPrivate::getContentHeight() const
436{
437 return contentItem ? contentItem->implicitHeight() : 0;
438}
439
440void QQuickControlPrivate::updateImplicitContentWidth()
441{
442 Q_Q(QQuickControl);
443 const qreal oldWidth = implicitContentWidth;
444 implicitContentWidth = getContentWidth();
445 if (!qFuzzyCompare(p1: implicitContentWidth, p2: oldWidth))
446 emit q->implicitContentWidthChanged();
447}
448
449void QQuickControlPrivate::updateImplicitContentHeight()
450{
451 Q_Q(QQuickControl);
452 const qreal oldHeight = implicitContentHeight;
453 implicitContentHeight = getContentHeight();
454 if (!qFuzzyCompare(p1: implicitContentHeight, p2: oldHeight))
455 emit q->implicitContentHeightChanged();
456}
457
458void QQuickControlPrivate::updateImplicitContentSize()
459{
460 Q_Q(QQuickControl);
461 const qreal oldWidth = implicitContentWidth;
462 const qreal oldHeight = implicitContentHeight;
463 implicitContentWidth = getContentWidth();
464 implicitContentHeight = getContentHeight();
465 if (!qFuzzyCompare(p1: implicitContentWidth, p2: oldWidth))
466 emit q->implicitContentWidthChanged();
467 if (!qFuzzyCompare(p1: implicitContentHeight, p2: oldHeight))
468 emit q->implicitContentHeightChanged();
469}
470
471QPalette QQuickControlPrivate::defaultPalette() const
472{
473 return QQuickTheme::palette(scope: QQuickTheme::System);
474}
475
476#if QT_CONFIG(accessibility)
477void QQuickControlPrivate::accessibilityActiveChanged(bool active)
478{
479 Q_Q(QQuickControl);
480 return q->accessibilityActiveChanged(active);
481}
482
483QAccessible::Role QQuickControlPrivate::accessibleRole() const
484{
485 Q_Q(const QQuickControl);
486 return q->accessibleRole();
487}
488
489QQuickAccessibleAttached *QQuickControlPrivate::accessibleAttached(const QObject *object)
490{
491 if (!QAccessible::isActive())
492 return nullptr;
493 return QQuickAccessibleAttached::attachedProperties(obj: object);
494}
495#endif
496
497/*!
498 \internal
499
500 Returns the font that the control \a item inherits from its ancestors and
501 QGuiApplication::font.
502*/
503QFont QQuickControlPrivate::parentFont(const QQuickItem *item)
504{
505 QQuickItem *p = item->parentItem();
506 while (p) {
507 if (QQuickControl *control = qobject_cast<QQuickControl *>(object: p))
508 return QQuickControlPrivate::get(control)->resolvedFont;
509 else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(object: p))
510 return label->QQuickText::font();
511 else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(object: p))
512 return textField->QQuickTextInput::font();
513 else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(object: p))
514 return textArea->QQuickTextEdit::font();
515
516 p = p->parentItem();
517 }
518
519 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: item->window()))
520 return window->font();
521
522 return QQuickTheme::font(scope: QQuickTheme::System);
523}
524
525/*!
526 \internal
527
528 Determine which font is implicitly imposed on this control by its ancestors
529 and QGuiApplication::font, resolve this against its own font (attributes from
530 the implicit font are copied over). Then propagate this font to this
531 control's children.
532*/
533void QQuickControlPrivate::resolveFont()
534{
535 Q_Q(QQuickControl);
536 inheritFont(font: parentFont(item: q));
537}
538
539void QQuickControlPrivate::inheritFont(const QFont &font)
540{
541 Q_Q(QQuickControl);
542 QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
543 parentFont.setResolveMask(extra.isAllocated() ? extra->requestedFont.resolveMask() | font.resolveMask() : font.resolveMask());
544
545 const QFont defaultFont = q->defaultFont();
546 QFont resolvedFont = parentFont.resolve(defaultFont);
547
548 setFont_helper(resolvedFont);
549}
550
551/*!
552 \internal
553
554 Assign \a font to this control, and propagate it to all children.
555*/
556void QQuickControlPrivate::updateFont(const QFont &font)
557{
558 Q_Q(QQuickControl);
559 QFont oldFont = resolvedFont;
560 resolvedFont = font;
561
562 if (oldFont != font)
563 q->fontChange(newFont: font, oldFont);
564
565 QQuickControlPrivate::updateFontRecur(item: q, font);
566
567 if (oldFont != font)
568 emit q->fontChanged();
569}
570
571void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &font)
572{
573 const auto childItems = item->childItems();
574 for (QQuickItem *child : childItems) {
575 if (QQuickControl *control = qobject_cast<QQuickControl *>(object: child))
576 QQuickControlPrivate::get(control)->inheritFont(font);
577 else if (QQuickLabel *label = qobject_cast<QQuickLabel *>(object: child))
578 QQuickLabelPrivate::get(item: label)->inheritFont(font);
579 else if (QQuickTextArea *textArea = qobject_cast<QQuickTextArea *>(object: child))
580 QQuickTextAreaPrivate::get(item: textArea)->inheritFont(font);
581 else if (QQuickTextField *textField = qobject_cast<QQuickTextField *>(object: child))
582 QQuickTextFieldPrivate::get(item: textField)->inheritFont(font);
583 else
584 QQuickControlPrivate::updateFontRecur(item: child, font);
585 }
586}
587
588QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item)
589{
590 for (const QQuickItem *p = item; p; p = p->parentItem())
591 if (const QQuickControl *control = qobject_cast<const QQuickControl *>(object: p))
592 return control->locale();
593
594 if (item)
595 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: item->window()))
596 return window->locale();
597
598 return QLocale();
599}
600
601/*!
602 \internal
603
604 Warns if \a control has a \c __notCustomizable property which is set to \c true,
605 unless \a item has an \c __ignoreNotCustomizable property.
606
607 If \c __notCustomizable is \c true, it means that the style that provides the
608 control does not support customization. If \c __ignoreNotCustomizable is true,
609 it means that the item is an internal implementation detail and shouldn't be
610 subject to the warning.
611
612 We take a QObject for \c control instead of QQuickControl or QQuickItem
613 because not all relevant types derive from QQuickControl - e.g. TextField,
614 TextArea, QQuickIndicatorButton, etc.
615*/
616void QQuickControlPrivate::warnIfCustomizationNotSupported(QObject *control, QQuickItem *item, const QString &propertyName)
617{
618 static const bool ignoreWarnings = [](){
619 return qEnvironmentVariableIntValue(varName: "QT_QUICK_CONTROLS_IGNORE_CUSTOMIZATION_WARNINGS");
620 }();
621 if (ignoreWarnings)
622 return;
623
624 if (!control->property(name: "__notCustomizable").toBool()
625 || (item && item->property(name: "__ignoreNotCustomizable").toBool()))
626 return;
627
628 qmlWarning(me: item ? item : control).nospace() << "The current style does not support customization of this control "
629 << "(property: " << propertyName << " item: " << item << "). "
630 "Please customize a non-native style (such as Basic, Fusion, Material, etc). For more information, see: "
631 "https://doc.qt.io/qt-6/qtquickcontrols2-customize.html#customization-reference";
632}
633
634void QQuickControlPrivate::updateLocale(const QLocale &l, bool e)
635{
636 Q_Q(QQuickControl);
637 if (!e && hasLocale)
638 return;
639
640 QLocale old = q->locale();
641 hasLocale = e;
642 if (old != l) {
643 locale = l;
644 q->localeChange(newLocale: l, oldLocale: old);
645 QQuickControlPrivate::updateLocaleRecur(item: q, l);
646 emit q->localeChanged();
647 }
648}
649
650void QQuickControlPrivate::updateLocaleRecur(QQuickItem *item, const QLocale &l)
651{
652 const auto childItems = item->childItems();
653 for (QQuickItem *child : childItems) {
654 if (QQuickControl *control = qobject_cast<QQuickControl *>(object: child))
655 QQuickControlPrivate::get(control)->updateLocale(l, e: false);
656 else
657 updateLocaleRecur(item: child, l);
658 }
659}
660
661#if QT_CONFIG(quicktemplates2_hover)
662void QQuickControlPrivate::updateHoverEnabled(bool enabled, bool xplicit)
663{
664 Q_Q(QQuickControl);
665 if (!xplicit && explicitHoverEnabled)
666 return;
667
668 bool wasEnabled = q->isHoverEnabled();
669 explicitHoverEnabled = xplicit;
670 if (wasEnabled != enabled) {
671 q->setAcceptHoverEvents(enabled);
672 QQuickControlPrivate::updateHoverEnabledRecur(item: q, enabled);
673 emit q->hoverEnabledChanged();
674 }
675}
676
677void QQuickControlPrivate::updateHoverEnabledRecur(QQuickItem *item, bool enabled)
678{
679 const auto childItems = item->childItems();
680 for (QQuickItem *child : childItems) {
681 if (QQuickControl *control = qobject_cast<QQuickControl *>(object: child))
682 QQuickControlPrivate::get(control)->updateHoverEnabled(enabled, xplicit: false);
683 else
684 updateHoverEnabledRecur(item: child, enabled);
685 }
686}
687
688bool QQuickControlPrivate::calcHoverEnabled(const QQuickItem *item)
689{
690 const QQuickItem *p = item;
691 while (p) {
692 // QQuickPopupItem accepts hover events to avoid leaking them through.
693 // Don't inherit that to the children of the popup, but fallback to the
694 // environment variable or style hint.
695 if (qobject_cast<const QQuickPopupItem *>(object: p))
696 break;
697
698 auto *applicationWindow = qobject_cast<QQuickApplicationWindow *>(object: p->window());
699 if (applicationWindow) {
700 const auto *applicationWindowPrivate = QQuickApplicationWindowPrivate::get(window: applicationWindow);
701 if (p == applicationWindowPrivate->control) {
702 // Don't let the next check get hit, because it will return
703 // false since it's a plain QQuickControl. Instead, skip to the
704 // global flags.
705 break;
706 }
707 }
708
709 if (QQuickTemplatesUtils::isInteractiveControlType(item: p)) {
710 const QVariant hoverEnabledProperty = p->property(name: "hoverEnabled");
711 Q_ASSERT(hoverEnabledProperty.isValid());
712 Q_ASSERT(hoverEnabledProperty.userType() == QMetaType::Bool);
713 return hoverEnabledProperty.toBool();
714 }
715
716 p = p->parentItem();
717 }
718
719 bool ok = false;
720 int env = qEnvironmentVariableIntValue(varName: "QT_QUICK_CONTROLS_HOVER_ENABLED", ok: &ok);
721 if (ok)
722 return env != 0;
723
724 // TODO: QQuickApplicationWindow::isHoverEnabled()
725
726 return QGuiApplication::styleHints()->useHoverEffects();
727}
728#endif
729
730static inline QString contentItemName() { return QStringLiteral("contentItem"); }
731
732void QQuickControlPrivate::cancelContentItem()
733{
734 Q_Q(QQuickControl);
735 quickCancelDeferred(object: q, property: contentItemName());
736}
737
738void QQuickControlPrivate::executeContentItem(bool complete)
739{
740 Q_Q(QQuickControl);
741 if (contentItem.wasExecuted())
742 return;
743
744 if (!contentItem || complete)
745 quickBeginDeferred(object: q, property: contentItemName(), delegate&: contentItem);
746 if (complete)
747 quickCompleteDeferred(object: q, property: contentItemName(), delegate&: contentItem);
748}
749
750void QQuickControlPrivate::cancelBackground()
751{
752 Q_Q(QQuickControl);
753 quickCancelDeferred(object: q, property: backgroundName());
754}
755
756void QQuickControlPrivate::executeBackground(bool complete)
757{
758 Q_Q(QQuickControl);
759 if (background.wasExecuted())
760 return;
761
762 if (!background || complete)
763 quickBeginDeferred(object: q, property: backgroundName(), delegate&: background);
764 if (complete)
765 quickCompleteDeferred(object: q, property: backgroundName(), delegate&: background);
766}
767
768/*
769 \internal
770
771 Hides an item that was replaced by a newer one, rather than
772 deleting it, as the item is typically created in QML and hence
773 we don't own it.
774*/
775void QQuickControlPrivate::hideOldItem(QQuickItem *item)
776{
777 if (!item)
778 return;
779
780 qCDebug(lcItemManagement) << "hiding old item" << item;
781
782 item->setVisible(false);
783 item->setParentItem(nullptr);
784
785#if QT_CONFIG(accessibility)
786 // Remove the item from the accessibility tree.
787 QQuickAccessibleAttached *accessible = accessibleAttached(object: item);
788 if (accessible)
789 accessible->setIgnored(true);
790#endif
791}
792
793/*
794 \internal
795
796 Named "unhide" because it's used for cases where an item
797 that was previously hidden by \l hideOldItem() wants to be
798 shown by a control again, such as a ScrollBar in ScrollView.
799
800 \a visibility controls the visibility of \a item, as there
801 may have been bindings that controlled visibility, such as
802 with a typical ScrollBar.qml implementation:
803
804 \code
805 visible: control.policy !== T.ScrollBar.AlwaysOff
806 \endcode
807
808 In the future we could try to save the binding for the visible
809 property (using e.g. QQmlAnyBinding::takeFrom), but for now we
810 keep it simple and just allow restoring an equivalent literal value.
811*/
812void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item, UnhideVisibility visibility)
813{
814 Q_ASSERT(item);
815 qCDebug(lcItemManagement) << "unhiding old item" << item;
816
817 item->setVisible(visibility == UnhideVisibility::Show);
818 item->setParentItem(control);
819
820#if QT_CONFIG(accessibility)
821 // Add the item back in to the accessibility tree.
822 QQuickAccessibleAttached *accessible = accessibleAttached(object: item);
823 if (accessible)
824 accessible->setIgnored(false);
825#endif
826}
827
828void QQuickControlPrivate::updateBaselineOffset()
829{
830 Q_Q(QQuickControl);
831 if (extra.isAllocated() && extra.value().hasBaselineOffset)
832 return;
833
834 if (!contentItem)
835 q->QQuickItem::setBaselineOffset(0);
836 else
837 q->QQuickItem::setBaselineOffset(getTopPadding() + contentItem->baselineOffset());
838}
839
840void QQuickControlPrivate::addImplicitSizeListener(QQuickItem *item, ChangeTypes changes)
841{
842 addImplicitSizeListener(item, listener: this, changes);
843}
844
845void QQuickControlPrivate::removeImplicitSizeListener(QQuickItem *item, ChangeTypes changes)
846{
847 removeImplicitSizeListener(item, listener: this, changes);
848}
849
850void QQuickControlPrivate::addImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes)
851{
852 if (!item || !listener)
853 return;
854 QQuickItemPrivate::get(item)->addItemChangeListener(listener, types: changes);
855}
856
857void QQuickControlPrivate::removeImplicitSizeListener(QQuickItem *item, QQuickItemChangeListener *listener, ChangeTypes changes)
858{
859 if (!item || !listener)
860 return;
861 QQuickItemPrivate::get(item)->removeItemChangeListener(listener, types: changes);
862}
863
864void QQuickControlPrivate::itemImplicitWidthChanged(QQuickItem *item)
865{
866 Q_Q(QQuickControl);
867 if (item == background)
868 emit q->implicitBackgroundWidthChanged();
869 else if (item == contentItem)
870 updateImplicitContentWidth();
871}
872
873void QQuickControlPrivate::itemImplicitHeightChanged(QQuickItem *item)
874{
875 Q_Q(QQuickControl);
876 if (item == background)
877 emit q->implicitBackgroundHeightChanged();
878 else if (item == contentItem)
879 updateImplicitContentHeight();
880}
881
882void QQuickControlPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
883{
884 Q_UNUSED(diff);
885 if (resizingBackground || item != background || !change.sizeChange())
886 return;
887
888 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
889 // Only set hasBackgroundWidth/Height if it was a width/height change,
890 // otherwise we're prevented from setting a width/height in the future.
891 if (change.widthChange())
892 extra.value().hasBackgroundWidth = p->widthValid();
893 if (change.heightChange())
894 extra.value().hasBackgroundHeight = p->heightValid();
895 resizeBackground();
896}
897
898void QQuickControlPrivate::itemDestroyed(QQuickItem *item)
899{
900 Q_Q(QQuickControl);
901 if (item == background) {
902 background = nullptr;
903 emit q->implicitBackgroundWidthChanged();
904 emit q->implicitBackgroundHeightChanged();
905 } else if (item == contentItem) {
906 contentItem = nullptr;
907 updateImplicitContentSize();
908 }
909}
910
911void QQuickControlPrivate::itemFocusChanged(QQuickItem *item, Qt::FocusReason reason)
912{
913 Q_Q(QQuickControl);
914 if (item == contentItem || item == q)
915 setLastFocusChangeReason(reason);
916}
917
918bool QQuickControlPrivate::setLastFocusChangeReason(Qt::FocusReason reason)
919{
920 Q_Q(QQuickControl);
921 Qt::FocusReason oldReason = static_cast<Qt::FocusReason>(focusReason);
922 const auto focusReasonChanged = QQuickItemPrivate::setLastFocusChangeReason(reason);
923 if (focusReasonChanged)
924 emit q->focusReasonChanged();
925 if (isKeyFocusReason(reason: oldReason) != isKeyFocusReason(reason))
926 emit q->visualFocusChanged();
927
928 return focusReasonChanged;
929}
930
931QQuickControl::QQuickControl(QQuickItem *parent)
932 : QQuickItem(*(new QQuickControlPrivate), parent)
933{
934 Q_D(QQuickControl);
935 d->init();
936}
937
938QQuickControl::QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent)
939 : QQuickItem(dd, parent)
940{
941 Q_D(QQuickControl);
942 d->init();
943}
944
945QQuickControl::~QQuickControl()
946{
947 Q_D(QQuickControl);
948 d->removeImplicitSizeListener(item: d->background, changes: QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
949 d->removeImplicitSizeListener(item: d->contentItem);
950 if (d->contentItem)
951 QQuickItemPrivate::get(item: d->contentItem)->removeItemChangeListener(d, types: QQuickItemPrivate::Focus);
952#if QT_CONFIG(accessibility)
953 QAccessible::removeActivationObserver(d);
954#endif
955}
956
957void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
958{
959 Q_D(QQuickControl);
960 QQuickItem::itemChange(change, value);
961 switch (change) {
962 case ItemEnabledHasChanged:
963 enabledChange();
964 break;
965 case ItemVisibleHasChanged:
966#if QT_CONFIG(quicktemplates2_hover)
967 if (!value.boolValue)
968 setHovered(false);
969#endif
970 break;
971 case ItemSceneChange:
972 case ItemParentHasChanged:
973 if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
974 d->resolveFont();
975 if (!d->hasLocale)
976 d->updateLocale(l: QQuickControlPrivate::calcLocale(item: d->parentItem), e: false); // explicit=false
977#if QT_CONFIG(quicktemplates2_hover)
978 if (!d->explicitHoverEnabled)
979 d->updateHoverEnabled(enabled: QQuickControlPrivate::calcHoverEnabled(item: d->parentItem), xplicit: false); // explicit=false
980#endif
981 }
982 break;
983 case ItemActiveFocusHasChanged:
984 if (isKeyFocusReason(reason: static_cast<Qt::FocusReason>(d->focusReason)))
985 emit visualFocusChanged();
986 break;
987 default:
988 break;
989 }
990}
991
992/*!
993 \qmlproperty font QtQuick.Controls::Control::font
994
995 This property holds the font currently set for the control.
996
997 This property describes the control's requested font. The font is used by the control's
998 style when rendering standard components, and is available as a means to ensure that custom
999 controls can maintain consistency with the native platform's native look and feel. It's common
1000 that different platforms, or different styles, define different fonts for an application.
1001
1002 The default font depends on the system environment. ApplicationWindow maintains a system/theme
1003 font which serves as a default for all controls. There may also be special font defaults for
1004 certain types of controls. You can also set the default font for controls by either:
1005
1006 \list
1007 \li passing a custom font to QGuiApplication::setFont(), before loading the QML; or
1008 \li specifying the fonts in the \l {Qt Quick Controls 2 Configuration File}{qtquickcontrols2.conf file}.
1009 \endlist
1010
1011 Finally, the font is matched against Qt's font database to find the best match.
1012
1013 Control propagates explicit font properties from parent to children. If you change a specific
1014 property on a control's font, that property propagates to all of the control's children,
1015 overriding any system defaults for that property.
1016
1017 \code
1018 Page {
1019 font.family: "Courier"
1020
1021 Column {
1022 Label {
1023 text: qsTr("This will use Courier...")
1024 }
1025
1026 Switch {
1027 text: qsTr("... and so will this")
1028 }
1029 }
1030 }
1031 \endcode
1032
1033 For the full list of available font properties, see the
1034 \l [QtQuick]{font}{font QML Value Type} documentation.
1035*/
1036QFont QQuickControl::font() const
1037{
1038 Q_D(const QQuickControl);
1039 QFont font = d->resolvedFont;
1040 // The resolveMask should inherit from the requestedFont
1041 font.setResolveMask(d->extra.value().requestedFont.resolveMask());
1042 return font;
1043}
1044
1045void QQuickControl::setFont(const QFont &font)
1046{
1047 Q_D(QQuickControl);
1048 if (d->extra.value().requestedFont.resolveMask() == font.resolveMask() && d->extra.value().requestedFont == font)
1049 return;
1050
1051 d->extra.value().requestedFont = font;
1052 d->resolveFont();
1053}
1054
1055void QQuickControl::resetFont()
1056{
1057 setFont(QFont());
1058}
1059
1060/*!
1061 \qmlproperty real QtQuick.Controls::Control::availableWidth
1062 \readonly
1063
1064 This property holds the width available to the \l contentItem after
1065 deducting horizontal padding from the \l {Item::}{width} of the control.
1066
1067 \sa {Control Layout}, padding, leftPadding, rightPadding
1068*/
1069qreal QQuickControl::availableWidth() const
1070{
1071 return qMax<qreal>(a: 0.0, b: width() - leftPadding() - rightPadding());
1072}
1073
1074/*!
1075 \qmlproperty real QtQuick.Controls::Control::availableHeight
1076 \readonly
1077
1078 This property holds the height available to the \l contentItem after
1079 deducting vertical padding from the \l {Item::}{height} of the control.
1080
1081 \sa {Control Layout}, padding, topPadding, bottomPadding
1082*/
1083qreal QQuickControl::availableHeight() const
1084{
1085 return qMax<qreal>(a: 0.0, b: height() - topPadding() - bottomPadding());
1086}
1087
1088/*!
1089 \qmlproperty real QtQuick.Controls::Control::padding
1090
1091 This property holds the default padding.
1092
1093 Padding adds a space between each edge of the content item and the
1094 background item, effectively controlling the size of the content item. To
1095 specify a padding value for a specific edge of the control, set its
1096 relevant property:
1097
1098 \list
1099 \li \l {Control::}{leftPadding}
1100 \li \l {Control::}{rightPadding}
1101 \li \l {Control::}{topPadding}
1102 \li \l {Control::}{bottomPadding}
1103 \endlist
1104
1105 \note Different styles may specify the default padding for certain controls
1106 in different ways, and these ways may change over time as the design
1107 guidelines that the style is based on evolve. To ensure that these changes
1108 don't affect the padding values you have specified, it is best to use the
1109 most specific properties available. For example, rather than setting
1110 the \l padding property:
1111
1112 \code
1113 padding: 0
1114 \endcode
1115
1116 set each specific property instead:
1117
1118 \code
1119 leftPadding: 0
1120 rightPadding: 0
1121 topPadding: 0
1122 bottomPadding: 0
1123 \endcode
1124
1125 \sa {Control Layout}, availableWidth, availableHeight, topPadding, leftPadding, rightPadding, bottomPadding
1126*/
1127qreal QQuickControl::padding() const
1128{
1129 Q_D(const QQuickControl);
1130 return d->padding;
1131}
1132
1133void QQuickControl::setPadding(qreal padding)
1134{
1135 Q_D(QQuickControl);
1136 if (qFuzzyCompare(p1: d->padding, p2: padding))
1137 return;
1138
1139 const QMarginsF oldPadding = d->getPadding();
1140 const qreal oldVerticalPadding = d->getVerticalPadding();
1141 const qreal oldHorizontalPadding = d->getHorizontalPadding();
1142
1143 d->padding = padding;
1144 emit paddingChanged();
1145
1146 const QMarginsF newPadding = d->getPadding();
1147 const qreal newVerticalPadding = d->getVerticalPadding();
1148 const qreal newHorizontalPadding = d->getHorizontalPadding();
1149
1150 if (!qFuzzyCompare(p1: newPadding.top(), p2: oldPadding.top()))
1151 emit topPaddingChanged();
1152 if (!qFuzzyCompare(p1: newPadding.left(), p2: oldPadding.left()))
1153 emit leftPaddingChanged();
1154 if (!qFuzzyCompare(p1: newPadding.right(), p2: oldPadding.right()))
1155 emit rightPaddingChanged();
1156 if (!qFuzzyCompare(p1: newPadding.bottom(), p2: oldPadding.bottom()))
1157 emit bottomPaddingChanged();
1158 if (!qFuzzyCompare(p1: newVerticalPadding, p2: oldVerticalPadding))
1159 emit verticalPaddingChanged();
1160 if (!qFuzzyCompare(p1: newHorizontalPadding, p2: oldHorizontalPadding))
1161 emit horizontalPaddingChanged();
1162 if (!qFuzzyCompare(p1: newPadding.top(), p2: oldPadding.top()) || !qFuzzyCompare(p1: newPadding.bottom(), p2: oldPadding.bottom()))
1163 emit availableHeightChanged();
1164 if (!qFuzzyCompare(p1: newPadding.left(), p2: oldPadding.left()) || !qFuzzyCompare(p1: newPadding.right(), p2: oldPadding.right()))
1165 emit availableWidthChanged();
1166
1167 paddingChange(newPadding, oldPadding);
1168}
1169
1170void QQuickControl::resetPadding()
1171{
1172 setPadding(0);
1173}
1174
1175/*!
1176 \qmlproperty real QtQuick.Controls::Control::topPadding
1177
1178 This property holds the top padding. Unless explicitly set, the value
1179 is equal to \c verticalPadding.
1180
1181 \sa {Control Layout}, padding, bottomPadding, verticalPadding, availableHeight
1182*/
1183qreal QQuickControl::topPadding() const
1184{
1185 Q_D(const QQuickControl);
1186 return d->getTopPadding();
1187}
1188
1189void QQuickControl::setTopPadding(qreal padding)
1190{
1191 Q_D(QQuickControl);
1192 d->setTopPadding(value: padding);
1193}
1194
1195void QQuickControl::resetTopPadding()
1196{
1197 Q_D(QQuickControl);
1198 d->setTopPadding(value: 0, reset: true);
1199}
1200
1201/*!
1202 \qmlproperty real QtQuick.Controls::Control::leftPadding
1203
1204 This property holds the left padding. Unless explicitly set, the value
1205 is equal to \c horizontalPadding.
1206
1207 \sa {Control Layout}, padding, rightPadding, horizontalPadding, availableWidth
1208*/
1209qreal QQuickControl::leftPadding() const
1210{
1211 Q_D(const QQuickControl);
1212 return d->getLeftPadding();
1213}
1214
1215void QQuickControl::setLeftPadding(qreal padding)
1216{
1217 Q_D(QQuickControl);
1218 d->setLeftPadding(value: padding);
1219}
1220
1221void QQuickControl::resetLeftPadding()
1222{
1223 Q_D(QQuickControl);
1224 d->setLeftPadding(value: 0, reset: true);
1225}
1226
1227/*!
1228 \qmlproperty real QtQuick.Controls::Control::rightPadding
1229
1230 This property holds the right padding. Unless explicitly set, the value
1231 is equal to \c horizontalPadding.
1232
1233 \sa {Control Layout}, padding, leftPadding, horizontalPadding, availableWidth
1234*/
1235qreal QQuickControl::rightPadding() const
1236{
1237 Q_D(const QQuickControl);
1238 return d->getRightPadding();
1239}
1240
1241void QQuickControl::setRightPadding(qreal padding)
1242{
1243 Q_D(QQuickControl);
1244 d->setRightPadding(value: padding);
1245}
1246
1247void QQuickControl::resetRightPadding()
1248{
1249 Q_D(QQuickControl);
1250 d->setRightPadding(value: 0, reset: true);
1251}
1252
1253/*!
1254 \qmlproperty real QtQuick.Controls::Control::bottomPadding
1255
1256 This property holds the bottom padding. Unless explicitly set, the value
1257 is equal to \c verticalPadding.
1258
1259 \sa {Control Layout}, padding, topPadding, verticalPadding, availableHeight
1260*/
1261qreal QQuickControl::bottomPadding() const
1262{
1263 Q_D(const QQuickControl);
1264 return d->getBottomPadding();
1265}
1266
1267void QQuickControl::setBottomPadding(qreal padding)
1268{
1269 Q_D(QQuickControl);
1270 d->setBottomPadding(value: padding);
1271}
1272
1273void QQuickControl::resetBottomPadding()
1274{
1275 Q_D(QQuickControl);
1276 d->setBottomPadding(value: 0, reset: true);
1277}
1278
1279/*!
1280 \qmlproperty real QtQuick.Controls::Control::spacing
1281
1282 This property holds the spacing.
1283
1284 Spacing is useful for controls that have multiple or repetitive building
1285 blocks. For example, some styles use spacing to determine the distance
1286 between the text and indicator of \l CheckBox. Spacing is not enforced by
1287 Control, so each style may interpret it differently, and some may ignore it
1288 altogether.
1289*/
1290qreal QQuickControl::spacing() const
1291{
1292 Q_D(const QQuickControl);
1293 return d->spacing;
1294}
1295
1296void QQuickControl::setSpacing(qreal spacing)
1297{
1298 Q_D(QQuickControl);
1299 if (qFuzzyCompare(p1: d->spacing, p2: spacing))
1300 return;
1301
1302 qreal oldSpacing = d->spacing;
1303 d->spacing = spacing;
1304 emit spacingChanged();
1305 spacingChange(newSpacing: spacing, oldSpacing);
1306}
1307
1308void QQuickControl::resetSpacing()
1309{
1310 setSpacing(0);
1311}
1312
1313/*!
1314 \qmlproperty Locale QtQuick.Controls::Control::locale
1315
1316 This property holds the locale of the control.
1317
1318 It contains locale specific properties for formatting data and numbers.
1319 Unless a special locale has been set, this is either the parent's locale
1320 or the default locale.
1321
1322 Control propagates the locale from parent to children. If you change the
1323 control's locale, that locale propagates to all of the control's children,
1324 overriding the system default locale.
1325
1326 \sa mirrored
1327*/
1328QLocale QQuickControl::locale() const
1329{
1330 Q_D(const QQuickControl);
1331 return d->locale;
1332}
1333
1334void QQuickControl::setLocale(const QLocale &locale)
1335{
1336 Q_D(QQuickControl);
1337 if (d->hasLocale && d->locale == locale)
1338 return;
1339
1340 d->updateLocale(l: locale, e: true); // explicit=true
1341}
1342
1343void QQuickControl::resetLocale()
1344{
1345 Q_D(QQuickControl);
1346 if (!d->hasLocale)
1347 return;
1348
1349 d->hasLocale = false;
1350 d->updateLocale(l: QQuickControlPrivate::calcLocale(item: d->parentItem), e: false); // explicit=false
1351}
1352
1353/*!
1354 \qmlproperty bool QtQuick.Controls::Control::mirrored
1355 \readonly
1356
1357 This property holds whether the control is mirrored.
1358
1359 This property is provided for convenience. A control is considered mirrored
1360 when its visual layout direction is right-to-left; that is, when
1361 \l {LayoutMirroring::enabled}{LayoutMirroring.enabled} is \c true.
1362
1363 As of Qt 6.2, the \l locale property no longer affects this property.
1364
1365 \sa {LayoutMirroring}{LayoutMirroring}, {Right-to-left User Interfaces}
1366*/
1367bool QQuickControl::isMirrored() const
1368{
1369 Q_D(const QQuickControl);
1370 return d->isMirrored();
1371}
1372
1373// ### Qt 7: replace with signal parameter: QTBUG-117596
1374/*!
1375 \qmlproperty enumeration QtQuick.Controls::Control::focusReason
1376
1377 This property holds the reason of the last focus change.
1378
1379 The value of this property is modified by Qt whenever focus is transferred,
1380 and you should never have to set this property yourself.
1381
1382 \note This property does not indicate whether the item has \l {Item::activeFocus}
1383 {active focus}, but the reason why the item either gained or lost focus.
1384
1385 \value Qt.MouseFocusReason A mouse action occurred.
1386 \value Qt.TabFocusReason The Tab key was pressed.
1387 \value Qt.BacktabFocusReason A Backtab occurred. The input for this may include the Shift or Control keys; e.g. Shift+Tab.
1388 \value Qt.ActiveWindowFocusReason The window system made this window either active or inactive.
1389 \value Qt.PopupFocusReason The application opened/closed a pop-up that grabbed/released the keyboard focus.
1390 \value Qt.ShortcutFocusReason The user typed a label's buddy shortcut
1391 \value Qt.MenuBarFocusReason The menu bar took focus.
1392 \value Qt.OtherFocusReason Another reason, usually application-specific.
1393
1394 \sa Item::activeFocus
1395
1396 \sa visualFocus
1397*/
1398Qt::FocusReason QQuickControl::focusReason() const
1399{
1400 Q_D(const QQuickControl);
1401 return d->lastFocusChangeReason();
1402}
1403
1404void QQuickControl::setFocusReason(Qt::FocusReason reason)
1405{
1406 Q_D(QQuickControl);
1407 d->setLastFocusChangeReason(reason);
1408}
1409
1410/*!
1411 \qmlproperty bool QtQuick.Controls::Control::visualFocus
1412 \readonly
1413
1414 This property holds whether the control has visual focus. This property
1415 is \c true when the control has active focus and the focus reason is either
1416 \c Qt.TabFocusReason, \c Qt.BacktabFocusReason, or \c Qt.ShortcutFocusReason.
1417
1418 In general, for visualizing key focus, this property is preferred over
1419 \l Item::activeFocus. This ensures that key focus is only visualized when
1420 interacting with keys - not when interacting via touch or mouse.
1421
1422 \sa focusReason, Item::activeFocus
1423*/
1424bool QQuickControl::hasVisualFocus() const
1425{
1426 Q_D(const QQuickControl);
1427 return d->activeFocus && isKeyFocusReason(reason: static_cast<Qt::FocusReason>(d->focusReason));
1428}
1429
1430/*!
1431 \qmlproperty bool QtQuick.Controls::Control::hovered
1432 \readonly
1433
1434 This property holds whether the control is hovered.
1435
1436 \sa hoverEnabled
1437*/
1438bool QQuickControl::isHovered() const
1439{
1440#if QT_CONFIG(quicktemplates2_hover)
1441 Q_D(const QQuickControl);
1442 return d->hovered;
1443#else
1444 return false;
1445#endif
1446}
1447
1448void QQuickControl::setHovered(bool hovered)
1449{
1450#if QT_CONFIG(quicktemplates2_hover)
1451 Q_D(QQuickControl);
1452 if (hovered == d->hovered)
1453 return;
1454
1455 d->hovered = hovered;
1456 emit hoveredChanged();
1457 hoverChange();
1458#else
1459 Q_UNUSED(hovered);
1460#endif
1461}
1462
1463/*!
1464 \qmlproperty bool QtQuick.Controls::Control::hoverEnabled
1465
1466 This property determines whether the control accepts hover events. The default value
1467 is \c Application.styleHints.useHoverEffects.
1468
1469 Setting this property propagates the value to all child controls that do not have
1470 \c hoverEnabled explicitly set.
1471
1472 You can also enable or disable hover effects for all Qt Quick Controls applications
1473 by setting the \c QT_QUICK_CONTROLS_HOVER_ENABLED \l {Supported Environment Variables
1474 in Qt Quick Controls}{environment variable}.
1475
1476 \sa hovered
1477*/
1478bool QQuickControl::isHoverEnabled() const
1479{
1480#if QT_CONFIG(quicktemplates2_hover)
1481 Q_D(const QQuickControl);
1482 return d->hoverEnabled;
1483#else
1484 return false;
1485#endif
1486}
1487
1488void QQuickControl::setHoverEnabled(bool enabled)
1489{
1490#if QT_CONFIG(quicktemplates2_hover)
1491 Q_D(QQuickControl);
1492 if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
1493 return;
1494
1495 d->updateHoverEnabled(enabled, xplicit: true); // explicit=true
1496#else
1497 Q_UNUSED(enabled);
1498#endif
1499}
1500
1501void QQuickControl::resetHoverEnabled()
1502{
1503#if QT_CONFIG(quicktemplates2_hover)
1504 Q_D(QQuickControl);
1505 if (!d->explicitHoverEnabled)
1506 return;
1507
1508 d->explicitHoverEnabled = false;
1509 d->updateHoverEnabled(enabled: QQuickControlPrivate::calcHoverEnabled(item: d->parentItem), xplicit: false); // explicit=false
1510#endif
1511}
1512
1513/*!
1514 \qmlproperty bool QtQuick.Controls::Control::wheelEnabled
1515
1516 This property determines whether the control handles wheel events. The default value is \c false.
1517
1518 \note Care must be taken when enabling wheel events for controls within scrollable items such
1519 as \l Flickable, as the control will consume the events and hence interrupt scrolling of the
1520 Flickable.
1521*/
1522bool QQuickControl::isWheelEnabled() const
1523{
1524 Q_D(const QQuickControl);
1525 return d->wheelEnabled;
1526}
1527
1528void QQuickControl::setWheelEnabled(bool enabled)
1529{
1530 Q_D(QQuickControl);
1531 if (d->wheelEnabled == enabled)
1532 return;
1533
1534 d->wheelEnabled = enabled;
1535 emit wheelEnabledChanged();
1536}
1537
1538/*!
1539 \qmlproperty Item QtQuick.Controls::Control::background
1540
1541 This property holds the background item.
1542
1543 \code
1544 Button {
1545 id: control
1546 text: qsTr("Button")
1547 background: Rectangle {
1548 implicitWidth: 100
1549 implicitHeight: 40
1550 opacity: enabled ? 1 : 0.3
1551 color: control.down ? "#d0d0d0" : "#e0e0e0"
1552 }
1553 }
1554 \endcode
1555
1556 \input qquickcontrol-background.qdocinc notes
1557
1558 \sa {Control Layout}
1559*/
1560QQuickItem *QQuickControl::background() const
1561{
1562 QQuickControlPrivate *d = const_cast<QQuickControlPrivate *>(d_func());
1563 if (!d->background)
1564 d->executeBackground();
1565 return d->background;
1566}
1567
1568void QQuickControl::setBackground(QQuickItem *background)
1569{
1570 Q_D(QQuickControl);
1571 if (d->background == background)
1572 return;
1573
1574 QQuickControlPrivate::warnIfCustomizationNotSupported(control: this, item: background, QStringLiteral("background"));
1575
1576 if (!d->background.isExecuting())
1577 d->cancelBackground();
1578
1579 const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
1580 const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();
1581
1582 if (d->extra.isAllocated()) {
1583 d->extra.value().hasBackgroundWidth = false;
1584 d->extra.value().hasBackgroundHeight = false;
1585 }
1586
1587 d->removeImplicitSizeListener(item: d->background, changes: QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
1588 QQuickControlPrivate::hideOldItem(item: d->background);
1589 d->background = background;
1590
1591 if (background) {
1592 background->setParentItem(this);
1593 if (qFuzzyIsNull(d: background->z()))
1594 background->setZ(-1);
1595 QQuickItemPrivate *p = QQuickItemPrivate::get(item: background);
1596 if (p->widthValid() || p->heightValid()) {
1597 d->extra.value().hasBackgroundWidth = p->widthValid();
1598 d->extra.value().hasBackgroundHeight = p->heightValid();
1599 }
1600 if (isComponentComplete())
1601 d->resizeBackground();
1602 d->addImplicitSizeListener(item: background, changes: QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
1603 }
1604
1605 if (!qFuzzyCompare(p1: oldImplicitBackgroundWidth, p2: implicitBackgroundWidth()))
1606 emit implicitBackgroundWidthChanged();
1607 if (!qFuzzyCompare(p1: oldImplicitBackgroundHeight, p2: implicitBackgroundHeight()))
1608 emit implicitBackgroundHeightChanged();
1609 if (!d->background.isExecuting())
1610 emit backgroundChanged();
1611}
1612
1613/*!
1614 \qmlproperty Item QtQuick.Controls::Control::contentItem
1615
1616 This property holds the visual content item.
1617
1618 \code
1619 Button {
1620 id: control
1621 text: qsTr("Button")
1622 contentItem: Label {
1623 text: control.text
1624 verticalAlignment: Text.AlignVCenter
1625 }
1626 }
1627 \endcode
1628
1629 \note The content item is automatically positioned and resized to fit
1630 within the \l padding of the control. Bindings to the
1631 \l[QtQuick]{Item::}{x}, \l[QtQuick]{Item::}{y},
1632 \l[QtQuick]{Item::}{width}, and \l[QtQuick]{Item::}{height}
1633 properties of the contentItem are not respected.
1634
1635 \note Most controls use the implicit size of the content item to calculate
1636 the implicit size of the control itself. If you replace the content item
1637 with a custom one, you should also consider providing a sensible implicit
1638 size for it (unless it is an item like \l Text which has its own implicit
1639 size).
1640
1641 \sa {Control Layout}, padding
1642*/
1643QQuickItem *QQuickControl::contentItem() const
1644{
1645 QQuickControlPrivate *d = const_cast<QQuickControlPrivate *>(d_func());
1646 if (!d->contentItem)
1647 d->setContentItem_helper(item: d->getContentItem(), notify: false);
1648 return d->contentItem;
1649}
1650
1651void QQuickControl::setContentItem(QQuickItem *item)
1652{
1653 Q_D(QQuickControl);
1654 d->setContentItem_helper(item, notify: true);
1655}
1656
1657qreal QQuickControl::baselineOffset() const
1658{
1659 Q_D(const QQuickControl);
1660 return d->baselineOffset;
1661}
1662
1663void QQuickControl::setBaselineOffset(qreal offset)
1664{
1665 Q_D(QQuickControl);
1666 d->extra.value().hasBaselineOffset = true;
1667 QQuickItem::setBaselineOffset(offset);
1668}
1669
1670void QQuickControl::resetBaselineOffset()
1671{
1672 Q_D(QQuickControl);
1673 if (!d->extra.isAllocated() || !d->extra.value().hasBaselineOffset)
1674 return;
1675
1676 if (d->extra.isAllocated())
1677 d->extra.value().hasBaselineOffset = false;
1678 d->updateBaselineOffset();
1679}
1680
1681/*!
1682 \since QtQuick.Controls 2.5 (Qt 5.12)
1683 \qmlproperty real QtQuick.Controls::Control::horizontalPadding
1684
1685 This property holds the horizontal padding. Unless explicitly set, the value
1686 is equal to \c padding.
1687
1688 \sa {Control Layout}, padding, leftPadding, rightPadding, verticalPadding
1689*/
1690qreal QQuickControl::horizontalPadding() const
1691{
1692 Q_D(const QQuickControl);
1693 return d->getHorizontalPadding();
1694}
1695
1696void QQuickControl::setHorizontalPadding(qreal padding)
1697{
1698 Q_D(QQuickControl);
1699 d->setHorizontalPadding(value: padding);
1700}
1701
1702void QQuickControl::resetHorizontalPadding()
1703{
1704 Q_D(QQuickControl);
1705 d->setHorizontalPadding(value: 0, reset: true);
1706}
1707
1708/*!
1709 \since QtQuick.Controls 2.5 (Qt 5.12)
1710 \qmlproperty real QtQuick.Controls::Control::verticalPadding
1711
1712 This property holds the vertical padding. Unless explicitly set, the value
1713 is equal to \c padding.
1714
1715 \sa {Control Layout}, padding, topPadding, bottomPadding, horizontalPadding
1716*/
1717qreal QQuickControl::verticalPadding() const
1718{
1719 Q_D(const QQuickControl);
1720 return d->getVerticalPadding();
1721}
1722
1723void QQuickControl::setVerticalPadding(qreal padding)
1724{
1725 Q_D(QQuickControl);
1726 d->setVerticalPadding(value: padding);
1727}
1728
1729void QQuickControl::resetVerticalPadding()
1730{
1731 Q_D(QQuickControl);
1732 d->setVerticalPadding(value: 0, reset: true);
1733}
1734
1735/*!
1736 \since QtQuick.Controls 2.5 (Qt 5.12)
1737 \qmlproperty real QtQuick.Controls::Control::implicitContentWidth
1738 \readonly
1739
1740 This property holds the implicit content width.
1741
1742 For basic controls, the value is equal to \c {contentItem ? contentItem.implicitWidth : 0}.
1743 For types that inherit Container or Pane, the value is calculated based on the content children.
1744
1745 This is typically used, together with \l implicitBackgroundWidth, to calculate
1746 the \l {Item::}{implicitWidth}:
1747
1748 \code
1749 Control {
1750 implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
1751 implicitContentWidth + leftPadding + rightPadding)
1752 }
1753 \endcode
1754
1755 \sa implicitContentHeight, implicitBackgroundWidth
1756*/
1757qreal QQuickControl::implicitContentWidth() const
1758{
1759 Q_D(const QQuickControl);
1760
1761 if (auto *safeArea = static_cast<QQuickSafeArea*>(
1762 qmlAttachedPropertiesObject<QQuickSafeArea>(obj: this, create: false))) {
1763 // If the control's padding is tied to the safe area we may in
1764 // some cases end up with a binding loop if the implicit size
1765 // moves the control further into the non-safe area. Detect this
1766 // and break the binding loop by returning a constrained content
1767 // size based on an earlier known good implicit size.
1768 static constexpr auto kLastKnownGoodImplicitWidth = "_q_lastKnownGoodImplicitWidth";
1769 if (safeArea->detectedPossibleBindingLoop) {
1770 const auto lastImplicitWidth = safeArea->property(name: kLastKnownGoodImplicitWidth).value<int>();
1771 return lastImplicitWidth - leftPadding() - rightPadding();
1772 } else {
1773 safeArea->setProperty(name: kLastKnownGoodImplicitWidth, value: implicitWidth());
1774 }
1775 }
1776
1777 return d->implicitContentWidth;
1778}
1779
1780/*!
1781 \since QtQuick.Controls 2.5 (Qt 5.12)
1782 \qmlproperty real QtQuick.Controls::Control::implicitContentHeight
1783 \readonly
1784
1785 This property holds the implicit content height.
1786
1787 For basic controls, the value is equal to \c {contentItem ? contentItem.implicitHeight : 0}.
1788 For types that inherit Container or Pane, the value is calculated based on the content children.
1789
1790 This is typically used, together with \l implicitBackgroundHeight, to calculate
1791 the \l {Item::}{implicitHeight}:
1792
1793 \code
1794 Control {
1795 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
1796 implicitContentHeight + topPadding + bottomPadding)
1797 }
1798 \endcode
1799
1800 \sa implicitContentWidth, implicitBackgroundHeight
1801*/
1802qreal QQuickControl::implicitContentHeight() const
1803{
1804 Q_D(const QQuickControl);
1805
1806 if (auto *safeArea = static_cast<QQuickSafeArea*>(
1807 qmlAttachedPropertiesObject<QQuickSafeArea>(obj: this, create: false))) {
1808 // If the control's padding is tied to the safe area we may in
1809 // some cases end up with a binding loop if the implicit size
1810 // moves the control further into the non-safe area. Detect this
1811 // and break the binding loop by returning a constrained content
1812 // size based on an earlier known good implicit size.
1813 static constexpr auto kLastKnownGoodImplicitHeight = "_q_lastKnownGoodImplicitHeight";
1814 if (safeArea->detectedPossibleBindingLoop) {
1815 const auto lastImplicitHeight = safeArea->property(name: kLastKnownGoodImplicitHeight).value<int>();
1816 return lastImplicitHeight - topPadding() - bottomPadding();
1817 } else {
1818 safeArea->setProperty(name: kLastKnownGoodImplicitHeight, value: implicitHeight());
1819 }
1820 }
1821
1822 return d->implicitContentHeight;
1823}
1824
1825/*!
1826 \since QtQuick.Controls 2.5 (Qt 5.12)
1827 \qmlproperty real QtQuick.Controls::Control::implicitBackgroundWidth
1828 \readonly
1829
1830 This property holds the implicit background width.
1831
1832 The value is equal to \c {background ? background.implicitWidth : 0}.
1833
1834 This is typically used, together with \l implicitContentWidth, to calculate
1835 the \l {Item::}{implicitWidth}:
1836
1837 \code
1838 Control {
1839 implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
1840 implicitContentWidth + leftPadding + rightPadding)
1841 }
1842 \endcode
1843
1844 \sa implicitBackgroundHeight, implicitContentWidth
1845*/
1846qreal QQuickControl::implicitBackgroundWidth() const
1847{
1848 Q_D(const QQuickControl);
1849 if (!d->background)
1850 return 0;
1851 return d->background->implicitWidth();
1852}
1853
1854/*!
1855 \since QtQuick.Controls 2.5 (Qt 5.12)
1856 \qmlproperty real QtQuick.Controls::Control::implicitBackgroundHeight
1857 \readonly
1858
1859 This property holds the implicit background height.
1860
1861 The value is equal to \c {background ? background.implicitHeight : 0}.
1862
1863 This is typically used, together with \l implicitContentHeight, to calculate
1864 the \l {Item::}{implicitHeight}:
1865
1866 \code
1867 Control {
1868 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
1869 implicitContentHeight + topPadding + bottomPadding)
1870 }
1871 \endcode
1872
1873 \sa implicitBackgroundWidth, implicitContentHeight
1874*/
1875qreal QQuickControl::implicitBackgroundHeight() const
1876{
1877 Q_D(const QQuickControl);
1878 if (!d->background)
1879 return 0;
1880 return d->background->implicitHeight();
1881}
1882
1883/*!
1884 \since QtQuick.Controls 2.5 (Qt 5.12)
1885 \qmlproperty real QtQuick.Controls::Control::topInset
1886
1887 This property holds the top inset for the background.
1888
1889 \sa {Control Layout}, bottomInset
1890*/
1891qreal QQuickControl::topInset() const
1892{
1893 Q_D(const QQuickControl);
1894 return d->getTopInset();
1895}
1896
1897void QQuickControl::setTopInset(qreal inset)
1898{
1899 Q_D(QQuickControl);
1900 d->setTopInset(value: inset);
1901}
1902
1903void QQuickControl::resetTopInset()
1904{
1905 Q_D(QQuickControl);
1906 d->setTopInset(value: 0, reset: true);
1907}
1908
1909/*!
1910 \since QtQuick.Controls 2.5 (Qt 5.12)
1911 \qmlproperty real QtQuick.Controls::Control::leftInset
1912
1913 This property holds the left inset for the background.
1914
1915 \sa {Control Layout}, rightInset
1916*/
1917qreal QQuickControl::leftInset() const
1918{
1919 Q_D(const QQuickControl);
1920 return d->getLeftInset();
1921}
1922
1923void QQuickControl::setLeftInset(qreal inset)
1924{
1925 Q_D(QQuickControl);
1926 d->setLeftInset(value: inset);
1927}
1928
1929void QQuickControl::resetLeftInset()
1930{
1931 Q_D(QQuickControl);
1932 d->setLeftInset(value: 0, reset: true);
1933}
1934
1935/*!
1936 \since QtQuick.Controls 2.5 (Qt 5.12)
1937 \qmlproperty real QtQuick.Controls::Control::rightInset
1938
1939 This property holds the right inset for the background.
1940
1941 \sa {Control Layout}, leftInset
1942*/
1943qreal QQuickControl::rightInset() const
1944{
1945 Q_D(const QQuickControl);
1946 return d->getRightInset();
1947}
1948
1949void QQuickControl::setRightInset(qreal inset)
1950{
1951 Q_D(QQuickControl);
1952 d->setRightInset(value: inset);
1953}
1954
1955void QQuickControl::resetRightInset()
1956{
1957 Q_D(QQuickControl);
1958 d->setRightInset(value: 0, reset: true);
1959}
1960
1961/*!
1962 \since QtQuick.Controls 2.5 (Qt 5.12)
1963 \qmlproperty real QtQuick.Controls::Control::bottomInset
1964
1965 This property holds the bottom inset for the background.
1966
1967 \sa {Control Layout}, topInset
1968*/
1969qreal QQuickControl::bottomInset() const
1970{
1971 Q_D(const QQuickControl);
1972 return d->getBottomInset();
1973}
1974
1975void QQuickControl::setBottomInset(qreal inset)
1976{
1977 Q_D(QQuickControl);
1978 d->setBottomInset(value: inset);
1979}
1980
1981void QQuickControl::resetBottomInset()
1982{
1983 Q_D(QQuickControl);
1984 d->setBottomInset(value: 0, reset: true);
1985}
1986
1987void QQuickControl::classBegin()
1988{
1989 Q_D(QQuickControl);
1990 QQuickItem::classBegin();
1991 d->resolveFont();
1992}
1993
1994void QQuickControl::componentComplete()
1995{
1996 Q_D(QQuickControl);
1997 d->executeBackground(complete: true);
1998 d->executeContentItem(complete: true);
1999 QQuickItem::componentComplete();
2000 d->resizeBackground();
2001 d->resizeContent();
2002 d->updateBaselineOffset();
2003 if (!d->hasLocale)
2004 d->locale = QQuickControlPrivate::calcLocale(item: d->parentItem);
2005#if QT_CONFIG(quicktemplates2_hover)
2006 if (!d->explicitHoverEnabled)
2007 setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(item: d->parentItem));
2008#endif
2009#if QT_CONFIG(accessibility)
2010 if (QAccessible::isActive())
2011 accessibilityActiveChanged(active: true);
2012#endif
2013}
2014
2015QFont QQuickControl::defaultFont() const
2016{
2017 return QQuickTheme::font(scope: QQuickTheme::System);
2018}
2019
2020void QQuickControl::focusInEvent(QFocusEvent *event)
2021{
2022 QQuickItem::focusInEvent(event);
2023}
2024
2025void QQuickControl::focusOutEvent(QFocusEvent *event)
2026{
2027 QQuickItem::focusOutEvent(event);
2028}
2029
2030#if QT_CONFIG(quicktemplates2_hover)
2031void QQuickControl::hoverEnterEvent(QHoverEvent *event)
2032{
2033 Q_D(QQuickControl);
2034 setHovered(d->hoverEnabled);
2035 event->ignore();
2036}
2037
2038void QQuickControl::hoverMoveEvent(QHoverEvent *event)
2039{
2040 Q_D(QQuickControl);
2041 setHovered(d->hoverEnabled && contains(point: event->position()));
2042 event->ignore();
2043}
2044
2045void QQuickControl::hoverLeaveEvent(QHoverEvent *event)
2046{
2047 setHovered(false);
2048 event->ignore();
2049}
2050#endif
2051
2052void QQuickControl::mousePressEvent(QMouseEvent *event)
2053{
2054 Q_D(QQuickControl);
2055 event->setAccepted(d->handlePress(event->position(), event->timestamp()));
2056}
2057
2058void QQuickControl::mouseMoveEvent(QMouseEvent *event)
2059{
2060 Q_D(QQuickControl);
2061 event->setAccepted(d->handleMove(point: event->position(), event->timestamp()));
2062}
2063
2064void QQuickControl::mouseReleaseEvent(QMouseEvent *event)
2065{
2066 Q_D(QQuickControl);
2067 event->setAccepted(d->handleRelease(event->position(), event->timestamp()));
2068}
2069
2070void QQuickControl::mouseUngrabEvent()
2071{
2072 Q_D(QQuickControl);
2073 d->handleUngrab();
2074}
2075
2076#if QT_CONFIG(quicktemplates2_multitouch)
2077void QQuickControl::touchEvent(QTouchEvent *event)
2078{
2079 Q_D(QQuickControl);
2080 switch (event->type()) {
2081 case QEvent::TouchBegin:
2082 case QEvent::TouchUpdate:
2083 case QEvent::TouchEnd:
2084 for (const QTouchEvent::TouchPoint &point : event->points()) {
2085 if (!d->acceptTouch(point))
2086 continue;
2087
2088 switch (point.state()) {
2089 case QEventPoint::Pressed:
2090 d->handlePress(point.position(), event->timestamp());
2091 break;
2092 case QEventPoint::Updated:
2093 d->handleMove(point: point.position(), event->timestamp());
2094 break;
2095 case QEventPoint::Released:
2096 d->handleRelease(point.position(), event->timestamp());
2097 break;
2098 default:
2099 break;
2100 }
2101 }
2102 break;
2103
2104 case QEvent::TouchCancel:
2105 d->handleUngrab();
2106 break;
2107
2108 default:
2109 QQuickItem::touchEvent(event);
2110 break;
2111 }
2112}
2113
2114void QQuickControl::touchUngrabEvent()
2115{
2116 Q_D(QQuickControl);
2117 d->handleUngrab();
2118}
2119#endif
2120
2121#if QT_CONFIG(wheelevent)
2122void QQuickControl::wheelEvent(QWheelEvent *event)
2123{
2124 Q_D(QQuickControl);
2125 event->setAccepted(d->wheelEnabled);
2126}
2127#endif
2128
2129void QQuickControl::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
2130{
2131 Q_D(QQuickControl);
2132 QQuickItem::geometryChange(newGeometry, oldGeometry);
2133 d->resizeBackground();
2134 d->resizeContent();
2135 if (!qFuzzyCompare(p1: newGeometry.width(), p2: oldGeometry.width()))
2136 emit availableWidthChanged();
2137 if (!qFuzzyCompare(p1: newGeometry.height(), p2: oldGeometry.height()))
2138 emit availableHeightChanged();
2139}
2140
2141void QQuickControl::enabledChange()
2142{
2143}
2144
2145void QQuickControl::fontChange(const QFont &newFont, const QFont &oldFont)
2146{
2147 Q_UNUSED(newFont);
2148 Q_UNUSED(oldFont);
2149}
2150
2151#if QT_CONFIG(quicktemplates2_hover)
2152void QQuickControl::hoverChange()
2153{
2154}
2155#endif
2156
2157void QQuickControl::mirrorChange()
2158{
2159 emit mirroredChanged();
2160}
2161
2162void QQuickControl::spacingChange(qreal newSpacing, qreal oldSpacing)
2163{
2164 Q_UNUSED(newSpacing);
2165 Q_UNUSED(oldSpacing);
2166}
2167
2168void QQuickControl::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
2169{
2170 Q_D(QQuickControl);
2171 Q_UNUSED(newPadding);
2172 Q_UNUSED(oldPadding);
2173 d->resizeContent();
2174 d->updateBaselineOffset();
2175}
2176
2177void QQuickControl::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
2178{
2179 Q_UNUSED(newItem);
2180 Q_UNUSED(oldItem);
2181}
2182
2183void QQuickControl::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
2184{
2185 Q_UNUSED(newLocale);
2186 Q_UNUSED(oldLocale);
2187}
2188
2189void QQuickControl::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
2190{
2191 Q_D(QQuickControl);
2192 Q_UNUSED(newInset);
2193 Q_UNUSED(oldInset);
2194 d->resizeBackground();
2195}
2196
2197#if QT_CONFIG(accessibility)
2198QAccessible::Role QQuickControl::accessibleRole() const
2199{
2200 return QAccessible::NoRole;
2201}
2202
2203void QQuickControl::accessibilityActiveChanged(bool active)
2204{
2205 Q_D(QQuickControl);
2206 if (!active)
2207 return;
2208
2209 QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(object: qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj: this, create: true));
2210 Q_ASSERT(accessibleAttached);
2211 accessibleAttached->setRole(d->effectiveAccessibleRole());
2212}
2213#endif
2214
2215QString QQuickControl::accessibleName() const
2216{
2217#if QT_CONFIG(accessibility)
2218 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(object: this))
2219 return accessibleAttached->name();
2220#endif
2221 return QString();
2222}
2223
2224void QQuickControl::maybeSetAccessibleName(const QString &name)
2225{
2226#if QT_CONFIG(accessibility)
2227 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(object: this)) {
2228 if (!accessibleAttached->wasNameExplicitlySet())
2229 accessibleAttached->setNameImplicitly(name);
2230 }
2231#else
2232 Q_UNUSED(name);
2233#endif
2234}
2235
2236QVariant QQuickControl::accessibleProperty(const char *propertyName)
2237{
2238#if QT_CONFIG(accessibility)
2239 if (QAccessible::isActive())
2240 return QQuickAccessibleAttached::property(object: this, propertyName);
2241#endif
2242 Q_UNUSED(propertyName);
2243 return QVariant();
2244}
2245
2246bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value)
2247{
2248#if QT_CONFIG(accessibility)
2249 if (QAccessible::isActive())
2250 return QQuickAccessibleAttached::setProperty(object: this, propertyName, value);
2251#endif
2252 Q_UNUSED(propertyName);
2253 Q_UNUSED(value);
2254 return false;
2255}
2256
2257QT_END_NAMESPACE
2258
2259#include "moc_qquickcontrol_p.cpp"
2260

source code of qtdeclarative/src/quicktemplates/qquickcontrol.cpp