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