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 "qquickpopup_p.h"
5#include "qquickpopup_p_p.h"
6#include "qquickpopupanchors_p.h"
7#include "qquickpopupitem_p_p.h"
8#include "qquickpopuppositioner_p_p.h"
9#include "qquickapplicationwindow_p.h"
10#include "qquickoverlay_p_p.h"
11#include "qquickcontrol_p_p.h"
12#include "qquickdialog_p.h"
13
14#include <QtCore/qloggingcategory.h>
15#include <QtQml/qqmlinfo.h>
16#include <QtQuick/qquickitem.h>
17#include <QtQuick/private/qquickaccessibleattached_p.h>
18#include <QtQuick/private/qquicktransition_p.h>
19#include <QtQuick/private/qquickitem_p.h>
20
21QT_BEGIN_NAMESPACE
22
23Q_LOGGING_CATEGORY(lcDimmer, "qt.quick.controls.popup.dimmer")
24Q_LOGGING_CATEGORY(lcPopup, "qt.quick.controls.popup")
25
26/*!
27 \qmltype Popup
28 \inherits QtObject
29//! \instantiates QQuickPopup
30 \inqmlmodule QtQuick.Controls
31 \since 5.7
32 \ingroup qtquickcontrols-popups
33 \ingroup qtquickcontrols-focusscopes
34 \brief Base type of popup-like user interface controls.
35
36 Popup is the base type of popup-like user interface controls. It can be
37 used with \l Window or \l ApplicationWindow.
38
39 \qml
40 import QtQuick.Window 2.2
41 import QtQuick.Controls 2.12
42
43 ApplicationWindow {
44 id: window
45 width: 400
46 height: 400
47 visible: true
48
49 Button {
50 text: "Open"
51 onClicked: popup.open()
52 }
53
54 Popup {
55 id: popup
56 x: 100
57 y: 100
58 width: 200
59 height: 300
60 modal: true
61 focus: true
62 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
63 }
64 }
65 \endqml
66
67 In order to ensure that a popup is displayed above other items in the
68 scene, it is recommended to use ApplicationWindow. ApplicationWindow also
69 provides background dimming effects.
70
71 Popup does not provide a layout of its own, but requires you to position
72 its contents, for instance by creating a \l RowLayout or a \l ColumnLayout.
73
74 Items declared as children of a Popup are automatically parented to the
75 Popups's \l contentItem. Items created dynamically need to be explicitly
76 parented to the contentItem.
77
78 \section1 Popup Layout
79
80 The following diagram illustrates the layout of a popup within a window:
81
82 \image qtquickcontrols-popup.png
83
84 The \l implicitWidth and \l implicitHeight of a popup are typically based
85 on the implicit sizes of the background and the content item plus any insets
86 and paddings. These properties determine how large the popup will be when no
87 explicit \l width or \l height is specified.
88
89 The geometry of the \l contentItem is determined by the padding. The following
90 example reserves 10px padding between the boundaries of the popup and its content:
91
92 \code
93 Popup {
94 padding: 10
95
96 contentItem: Text {
97 text: "Content"
98 }
99 }
100 \endcode
101
102 The \l background item fills the entire width and height of the popup,
103 unless insets or an explicit size have been given for it.
104
105 Negative insets can be used to make the background larger than the popup.
106 The following example uses negative insets to place a shadow outside the
107 popup's boundaries:
108
109 \code
110 Popup {
111 topInset: -2
112 leftInset: -2
113 rightInset: -6
114 bottomInset: -6
115
116 background: BorderImage {
117 source: ":/images/shadowed-background.png"
118 }
119 }
120 \endcode
121
122 \section1 Popup Sizing
123
124 If only a single item is used within a Popup, it will resize to fit the
125 implicit size of its contained item. This makes it particularly suitable
126 for use together with layouts.
127
128 \code
129 Popup {
130 ColumnLayout {
131 anchors.fill: parent
132 CheckBox { text: qsTr("E-mail") }
133 CheckBox { text: qsTr("Calendar") }
134 CheckBox { text: qsTr("Contacts") }
135 }
136 }
137 \endcode
138
139 Sometimes there might be two items within the popup:
140
141 \code
142 Popup {
143 SwipeView {
144 // ...
145 }
146 PageIndicator {
147 anchors.horizontalCenter: parent.horizontalCenter
148 anchors.bottom: parent.bottom
149 }
150 }
151 \endcode
152
153 In this case, Popup cannot calculate a sensible implicit size. Since we're
154 anchoring the \l PageIndicator over the \l SwipeView, we can simply set the
155 content size to the view's implicit size:
156
157 \code
158 Popup {
159 contentWidth: view.implicitWidth
160 contentHeight: view.implicitHeight
161
162 SwipeView {
163 id: view
164 // ...
165 }
166 PageIndicator {
167 anchors.horizontalCenter: parent.horizontalCenter
168 anchors.bottom: parent.bottom
169 }
170 }
171 \endcode
172
173 \note The popup's \l{contentItem}{content item} gets parented to the
174 \l{Overlay::overlay}{overlay}, and does not live within the popup's parent.
175 Because of that, a \l{Item::scale}{scale} applied to the tree in which
176 the popup lives does not apply to the visual popup. To make the popup
177 of e.g. a \l{ComboBox} follow the scale of the combobox, apply the same scale
178 to the \l{Overlay::overlay}{overlay} as well:
179
180 \code
181 Window {
182 property double scaleFactor: 2.0
183
184 Scale {
185 id: scale
186 xScale: scaleFactor
187 yScale: scaleFactor
188 }
189 Item {
190 id: scaledContent
191 transform: scale
192
193 ComboBox {
194 id: combobox
195 // ...
196 }
197 }
198
199 Overlay.overlay.transform: scale
200 }
201 \endcode
202
203 \section1 Popup Positioning
204
205 Similar to items in Qt Quick, Popup's \l x and \l y coordinates are
206 relative to its parent. This means that opening a popup that is a
207 child of a \l Button, for example, will cause the popup to be positioned
208 relative to the button.
209
210 \include qquickoverlay-popup-parent.qdocinc
211
212 Another way to center a popup in the window regardless of its parent item
213 is to use \l {anchors.centerIn}:
214
215 \snippet qtquickcontrols-popup.qml centerIn
216
217 To ensure that the popup is positioned within the bounds of the enclosing
218 window, the \l margins property can be set to a non-negative value.
219
220 \section1 Popup Transitions
221
222 Since Qt 5.15.3 the following properties are restored to their original values from before
223 the enter transition after the exit transition is completed.
224
225 \list
226 \li \l opacity
227 \li \l scale
228 \endlist
229
230 This allows the built-in styles to animate on these properties without losing any explicitly
231 defined value.
232
233 \section1 Back/Escape Event Handling
234
235 By default, a Popup will close if:
236 \list
237 \li It has \l activeFocus,
238 \li Its \l closePolicy is \c {Popup.CloseOnEscape}, and
239 \li The user presses the key sequence for QKeySequence::Cancel (typically
240 the Escape key)
241 \endlist
242
243 To prevent this from happening, either:
244
245 \list
246 \li Don't give the popup \l focus.
247 \li Set the popup's \l closePolicy to a value that does not include
248 \c {Popup.CloseOnEscape}.
249 \li Handle \l {Keys}' \l {Keys::}{escapePressed} signal in a child item of
250 the popup so that it gets the event before the Popup.
251 \endlist
252
253 \sa {Popup Controls}, {Customizing Popup}, ApplicationWindow
254
255 \section1 Property Propagation
256
257 Popup inherits fonts, palettes and attached properties through its parent
258 window, not its \l {Visual Parent}{object or visual parent}:
259
260 \snippet qtquickcontrols-popup-property-propagation.qml file
261
262 \image qtquickcontrols-basic-popup-property-propagation.png
263
264 In addition, popups do not propagate their properties to child popups. This
265 behavior is modelled on Qt Widgets, where a \c Qt::Popup widget is a
266 top-level window. Top-level windows do not propagate their properties to
267 child windows.
268
269 Certain derived types like ComboBox are typically implemented in such a way
270 that the popup is considered an integral part of the control, and as such,
271 may inherit things like attached properties. For example, in the
272 \l {Material Style}{Material style} ComboBox, the theme and other attached
273 properties are explicitly inherited by the Popup from the ComboBox itself:
274
275 \code
276 popup: T.Popup {
277 // ...
278
279 Material.theme: control.Material.theme
280 Material.accent: control.Material.accent
281 Material.primary: control.Material.primary
282 }
283 \endcode
284
285 So, to ensure that a child popup has the same property values as its parent
286 popup, explicitly set those properties:
287
288 \code
289 Popup {
290 id: parentPopup
291 // ...
292
293 Popup {
294 palette: parentPopup.palette
295 }
296 }
297 \endcode
298*/
299
300/*!
301 \qmlsignal void QtQuick.Controls::Popup::opened()
302
303 This signal is emitted when the popup is opened.
304
305 \sa aboutToShow()
306*/
307
308/*!
309 \qmlsignal void QtQuick.Controls::Popup::closed()
310
311 This signal is emitted when the popup is closed.
312
313 \sa aboutToHide()
314*/
315
316/*!
317 \qmlsignal void QtQuick.Controls::Popup::aboutToShow()
318
319 This signal is emitted when the popup is about to show.
320
321 \sa opened()
322*/
323
324/*!
325 \qmlsignal void QtQuick.Controls::Popup::aboutToHide()
326
327 This signal is emitted when the popup is about to hide.
328
329 \sa closed()
330*/
331
332const QQuickPopup::ClosePolicy QQuickPopupPrivate::DefaultClosePolicy = QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside;
333
334QQuickPopupPrivate::QQuickPopupPrivate()
335 : transitionManager(this)
336{
337}
338
339void QQuickPopupPrivate::init()
340{
341 Q_Q(QQuickPopup);
342 popupItem = new QQuickPopupItem(q);
343 popupItem->setVisible(false);
344 q->setParentItem(qobject_cast<QQuickItem *>(o: parent));
345 QObject::connect(sender: popupItem, signal: &QQuickControl::paddingChanged, context: q, slot: &QQuickPopup::paddingChanged);
346 QObject::connect(sender: popupItem, signal: &QQuickControl::backgroundChanged, context: q, slot: &QQuickPopup::backgroundChanged);
347 QObject::connect(sender: popupItem, signal: &QQuickControl::contentItemChanged, context: q, slot: &QQuickPopup::contentItemChanged);
348 QObject::connect(sender: popupItem, signal: &QQuickControl::implicitContentWidthChanged, context: q, slot: &QQuickPopup::implicitContentWidthChanged);
349 QObject::connect(sender: popupItem, signal: &QQuickControl::implicitContentHeightChanged, context: q, slot: &QQuickPopup::implicitContentHeightChanged);
350 QObject::connect(sender: popupItem, signal: &QQuickControl::implicitBackgroundWidthChanged, context: q, slot: &QQuickPopup::implicitBackgroundWidthChanged);
351 QObject::connect(sender: popupItem, signal: &QQuickControl::implicitBackgroundHeightChanged, context: q, slot: &QQuickPopup::implicitBackgroundHeightChanged);
352}
353
354void QQuickPopupPrivate::closeOrReject()
355{
356 Q_Q(QQuickPopup);
357 if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(object: q))
358 dialog->reject();
359 else
360 q->close();
361 touchId = -1;
362}
363
364bool QQuickPopupPrivate::tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags)
365{
366 if (!interactive)
367 return false;
368
369 static const QQuickPopup::ClosePolicy outsideFlags = QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnReleaseOutside;
370 static const QQuickPopup::ClosePolicy outsideParentFlags = QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent;
371
372 const bool onOutside = closePolicy & (flags & outsideFlags);
373 const bool onOutsideParent = closePolicy & (flags & outsideParentFlags);
374
375 if ((onOutside && outsidePressed) || (onOutsideParent && outsideParentPressed)) {
376 if (!contains(scenePos: pos) && (!dimmer || dimmer->contains(point: dimmer->mapFromScene(point: pos)))) {
377 if (!onOutsideParent || !parentItem || !parentItem->contains(point: parentItem->mapFromScene(point: pos))) {
378 closeOrReject();
379 return true;
380 }
381 }
382 }
383 return false;
384}
385
386bool QQuickPopupPrivate::contains(const QPointF &scenePos) const
387{
388 return popupItem->contains(point: popupItem->mapFromScene(point: scenePos));
389}
390
391#if QT_CONFIG(quicktemplates2_multitouch)
392bool QQuickPopupPrivate::acceptTouch(const QTouchEvent::TouchPoint &point)
393{
394 if (point.id() == touchId)
395 return true;
396
397 if (touchId == -1 && point.state() != QEventPoint::Released) {
398 touchId = point.id();
399 return true;
400 }
401
402 return false;
403}
404#endif
405
406bool QQuickPopupPrivate::blockInput(QQuickItem *item, const QPointF &point) const
407{
408 // don't propagate events within the popup beyond the overlay
409 if (popupItem->contains(point: popupItem->mapFromScene(point))
410 && item == QQuickOverlay::overlay(window)) {
411 return true;
412 }
413
414 // don't block presses and releases
415 // a) outside a non-modal popup,
416 // b) to popup children/content, or
417 // b) outside a modal popups's background dimming
418 return modal && ((popupItem != item) && !popupItem->isAncestorOf(child: item)) && (!dimmer || dimmer->contains(point: dimmer->mapFromScene(point)));
419}
420
421bool QQuickPopupPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp)
422{
423 Q_UNUSED(timestamp);
424 pressPoint = point;
425 outsidePressed = !contains(scenePos: point);
426 outsideParentPressed = outsidePressed && parentItem && !parentItem->contains(point: parentItem->mapFromScene(point));
427 tryClose(pos: point, flags: QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
428 return blockInput(item, point);
429}
430
431bool QQuickPopupPrivate::handleMove(QQuickItem *item, const QPointF &point, ulong timestamp)
432{
433 Q_UNUSED(timestamp);
434 return blockInput(item, point);
435}
436
437bool QQuickPopupPrivate::handleRelease(QQuickItem *item, const QPointF &point, ulong timestamp)
438{
439 Q_UNUSED(timestamp);
440 if (item != popupItem && !contains(scenePos: pressPoint))
441 tryClose(pos: point, flags: QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
442 pressPoint = QPointF();
443 outsidePressed = false;
444 outsideParentPressed = false;
445 touchId = -1;
446 return blockInput(item, point);
447}
448
449void QQuickPopupPrivate::handleUngrab()
450{
451 Q_Q(QQuickPopup);
452 QQuickOverlay *overlay = QQuickOverlay::overlay(window);
453 if (overlay) {
454 QQuickOverlayPrivate *p = QQuickOverlayPrivate::get(overlay);
455 if (p->mouseGrabberPopup == q)
456 p->mouseGrabberPopup = nullptr;
457 }
458 pressPoint = QPointF();
459 touchId = -1;
460}
461
462bool QQuickPopupPrivate::handleMouseEvent(QQuickItem *item, QMouseEvent *event)
463{
464 switch (event->type()) {
465 case QEvent::MouseButtonPress:
466 return handlePress(item, point: event->scenePosition(), timestamp: event->timestamp());
467 case QEvent::MouseMove:
468 return handleMove(item, point: event->scenePosition(), timestamp: event->timestamp());
469 case QEvent::MouseButtonRelease:
470 return handleRelease(item, point: event->scenePosition(), timestamp: event->timestamp());
471 default:
472 Q_UNREACHABLE_RETURN(false);
473 }
474}
475
476bool QQuickPopupPrivate::handleHoverEvent(QQuickItem *item, QHoverEvent *event)
477{
478 switch (event->type()) {
479 case QEvent::HoverEnter:
480 case QEvent::HoverMove:
481 case QEvent::HoverLeave:
482 return blockInput(item, point: event->scenePosition());
483 default:
484 Q_UNREACHABLE_RETURN(false);
485 }
486}
487
488#if QT_CONFIG(quicktemplates2_multitouch)
489bool QQuickPopupPrivate::handleTouchEvent(QQuickItem *item, QTouchEvent *event)
490{
491 switch (event->type()) {
492 case QEvent::TouchBegin:
493 case QEvent::TouchUpdate:
494 case QEvent::TouchEnd:
495 for (const QTouchEvent::TouchPoint &point : event->points()) {
496 if (event->type() != QEvent::TouchEnd && !acceptTouch(point))
497 return blockInput(item, point: point.position());
498
499 switch (point.state()) {
500 case QEventPoint::Pressed:
501 return handlePress(item, point: item->mapToScene(point: point.position()), timestamp: event->timestamp());
502 case QEventPoint::Updated:
503 return handleMove(item, point: item->mapToScene(point: point.position()), timestamp: event->timestamp());
504 case QEventPoint::Released:
505 return handleRelease(item, point: item->mapToScene(point: point.position()), timestamp: event->timestamp());
506 default:
507 break;
508 }
509 }
510 break;
511
512 case QEvent::TouchCancel:
513 handleUngrab();
514 break;
515
516 default:
517 break;
518 }
519
520 return false;
521}
522#endif
523
524bool QQuickPopupPrivate::prepareEnterTransition()
525{
526 Q_Q(QQuickPopup);
527 if (!window) {
528 qmlWarning(me: q) << "cannot find any window to open popup in.";
529 return false;
530 }
531
532 if (transitionState == EnterTransition && transitionManager.isRunning())
533 return false;
534
535 if (transitionState != EnterTransition) {
536 QQuickOverlay *overlay = QQuickOverlay::overlay(window);
537 const auto popupStack = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
538 popupItem->setParentItem(overlay);
539 // if there is a stack of popups, and the current top popup item belongs to an
540 // ancestor of this popup, then make sure that this popup's item is at the top
541 // of the stack.
542 const QQuickPopup *topPopup = popupStack.isEmpty() ? nullptr : popupStack.first();
543 const QObject *ancestor = q;
544 while (ancestor && topPopup) {
545 if (ancestor == topPopup)
546 break;
547 ancestor = ancestor->parent();
548 }
549 if (topPopup && topPopup != q && ancestor) {
550 QQuickItem *topPopupItem = popupStack.first()->popupItem();
551 popupItem->stackAfter(topPopupItem);
552 // If the popup doesn't have an explicit z value set, set it to be at least as
553 // high as the current top popup item so that later opened popups are on top.
554 if (!hasZ)
555 popupItem->setZ(qMax(a: topPopupItem->z(), b: popupItem->z()));
556 }
557 if (dim)
558 createOverlay();
559 showOverlay();
560 emit q->aboutToShow();
561 visible = true;
562 transitionState = EnterTransition;
563 popupItem->setVisible(true);
564 getPositioner()->setParentItem(parentItem);
565 emit q->visibleChanged();
566
567 auto *overlayPrivate = QQuickOverlayPrivate::get(overlay);
568 if (overlayPrivate->lastActiveFocusItem.isNull())
569 overlayPrivate->lastActiveFocusItem = window->activeFocusItem();
570
571 if (focus)
572 popupItem->setFocus(focus: true, reason: Qt::PopupFocusReason);
573 }
574 return true;
575}
576
577bool QQuickPopupPrivate::prepareExitTransition()
578{
579 Q_Q(QQuickPopup);
580 if (transitionState == ExitTransition && transitionManager.isRunning())
581 return false;
582
583 // We need to cache the original scale and opacity values so we can reset it after
584 // the exit transition is done so they have the original values again
585 prevScale = popupItem->scale();
586 prevOpacity = popupItem->opacity();
587
588 if (transitionState != ExitTransition) {
589 // The setFocus(false) call below removes any active focus before we're
590 // able to check it in finalizeExitTransition.
591 if (!hadActiveFocusBeforeExitTransition)
592 hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus();
593 if (focus)
594 popupItem->setFocus(focus: false, reason: Qt::PopupFocusReason);
595 transitionState = ExitTransition;
596 hideOverlay();
597 emit q->aboutToHide();
598 emit q->openedChanged();
599 }
600 return true;
601}
602
603void QQuickPopupPrivate::finalizeEnterTransition()
604{
605 Q_Q(QQuickPopup);
606 transitionState = NoTransition;
607 getPositioner()->reposition();
608 emit q->openedChanged();
609 opened();
610}
611
612void QQuickPopupPrivate::finalizeExitTransition()
613{
614 Q_Q(QQuickPopup);
615 getPositioner()->setParentItem(nullptr);
616 if (popupItem) {
617 popupItem->setParentItem(nullptr);
618 popupItem->setVisible(false);
619 }
620 destroyOverlay();
621
622 if (hadActiveFocusBeforeExitTransition && window) {
623 // restore focus to the next popup in chain, or to the window content if there are no other popups open
624 QQuickPopup *nextFocusPopup = nullptr;
625 if (QQuickOverlay *overlay = QQuickOverlay::overlay(window)) {
626 const auto stackingOrderPopups = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
627 for (auto popup : stackingOrderPopups) {
628 if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition
629 && popup->hasFocus()) {
630 nextFocusPopup = popup;
631 break;
632 }
633 }
634 }
635 if (nextFocusPopup) {
636 nextFocusPopup->forceActiveFocus(reason: Qt::PopupFocusReason);
637 } else {
638 auto *appWindow = qobject_cast<QQuickApplicationWindow*>(object: window);
639 auto *contentItem = appWindow ? appWindow->contentItem() : window->contentItem();
640 auto *overlay = QQuickOverlay::overlay(window);
641 auto *overlayPrivate = QQuickOverlayPrivate::get(overlay);
642 if (!contentItem->scopedFocusItem()
643 && !overlayPrivate->lastActiveFocusItem.isNull()) {
644 overlayPrivate->lastActiveFocusItem->setFocus(focus: true, reason: Qt::OtherFocusReason);
645 } else {
646 contentItem->setFocus(focus: true, reason: Qt::PopupFocusReason);
647 }
648 overlayPrivate->lastActiveFocusItem = nullptr;
649 }
650 }
651
652 visible = false;
653 transitionState = NoTransition;
654 hadActiveFocusBeforeExitTransition = false;
655 emit q->visibleChanged();
656 emit q->closed();
657 if (popupItem) {
658 popupItem->setScale(prevScale);
659 popupItem->setOpacity(prevOpacity);
660 }
661}
662
663void QQuickPopupPrivate::opened()
664{
665 Q_Q(QQuickPopup);
666 emit q->opened();
667}
668
669QMarginsF QQuickPopupPrivate::getMargins() const
670{
671 Q_Q(const QQuickPopup);
672 return QMarginsF(q->leftMargin(), q->topMargin(), q->rightMargin(), q->bottomMargin());
673}
674
675void QQuickPopupPrivate::setTopMargin(qreal value, bool reset)
676{
677 Q_Q(QQuickPopup);
678 qreal oldMargin = q->topMargin();
679 topMargin = value;
680 hasTopMargin = !reset;
681 if ((!reset && !qFuzzyCompare(p1: oldMargin, p2: value)) || (reset && !qFuzzyCompare(p1: oldMargin, p2: margins))) {
682 emit q->topMarginChanged();
683 q->marginsChange(newMargins: QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
684 oldMargins: QMarginsF(leftMargin, oldMargin, rightMargin, bottomMargin));
685 }
686}
687
688void QQuickPopupPrivate::setLeftMargin(qreal value, bool reset)
689{
690 Q_Q(QQuickPopup);
691 qreal oldMargin = q->leftMargin();
692 leftMargin = value;
693 hasLeftMargin = !reset;
694 if ((!reset && !qFuzzyCompare(p1: oldMargin, p2: value)) || (reset && !qFuzzyCompare(p1: oldMargin, p2: margins))) {
695 emit q->leftMarginChanged();
696 q->marginsChange(newMargins: QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
697 oldMargins: QMarginsF(oldMargin, topMargin, rightMargin, bottomMargin));
698 }
699}
700
701void QQuickPopupPrivate::setRightMargin(qreal value, bool reset)
702{
703 Q_Q(QQuickPopup);
704 qreal oldMargin = q->rightMargin();
705 rightMargin = value;
706 hasRightMargin = !reset;
707 if ((!reset && !qFuzzyCompare(p1: oldMargin, p2: value)) || (reset && !qFuzzyCompare(p1: oldMargin, p2: margins))) {
708 emit q->rightMarginChanged();
709 q->marginsChange(newMargins: QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
710 oldMargins: QMarginsF(leftMargin, topMargin, oldMargin, bottomMargin));
711 }
712}
713
714void QQuickPopupPrivate::setBottomMargin(qreal value, bool reset)
715{
716 Q_Q(QQuickPopup);
717 qreal oldMargin = q->bottomMargin();
718 bottomMargin = value;
719 hasBottomMargin = !reset;
720 if ((!reset && !qFuzzyCompare(p1: oldMargin, p2: value)) || (reset && !qFuzzyCompare(p1: oldMargin, p2: margins))) {
721 emit q->bottomMarginChanged();
722 q->marginsChange(newMargins: QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
723 oldMargins: QMarginsF(leftMargin, topMargin, rightMargin, oldMargin));
724 }
725}
726
727/*!
728 \since QtQuick.Controls 2.5 (Qt 5.12)
729 \qmlproperty Item QtQuick.Controls::Popup::anchors.centerIn
730
731 Anchors provide a way to position an item by specifying its
732 relationship with other items.
733
734 A common use case is to center a popup within its parent. One way to do
735 this is with the \l[QtQuick]{Item::}{x} and \l[QtQuick]{Item::}{y} properties. Anchors offer
736 a more convenient approach:
737
738 \qml
739 Pane {
740 // ...
741
742 Popup {
743 anchors.centerIn: parent
744 }
745 }
746 \endqml
747
748 It is also possible to center the popup in the window by using \l Overlay:
749
750 \snippet qtquickcontrols-popup.qml centerIn
751
752 This makes it easy to center a popup in the window from any component.
753
754 \note Popups can only be centered within their immediate parent or
755 the window overlay; trying to center in other items will produce a warning.
756
757 \sa {Popup Positioning}, {Item::}{anchors}, {Using Qt Quick Controls types
758 in property declarations}
759*/
760QQuickPopupAnchors *QQuickPopupPrivate::getAnchors()
761{
762 Q_Q(QQuickPopup);
763 if (!anchors)
764 anchors = new QQuickPopupAnchors(q);
765 return anchors;
766}
767
768QQuickPopupPositioner *QQuickPopupPrivate::getPositioner()
769{
770 Q_Q(QQuickPopup);
771 if (!positioner)
772 positioner = new QQuickPopupPositioner(q);
773 return positioner;
774}
775
776void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
777{
778 Q_Q(QQuickPopup);
779 if (window == newWindow)
780 return;
781
782 if (window) {
783 QQuickOverlay *overlay = QQuickOverlay::overlay(window);
784 if (overlay)
785 QQuickOverlayPrivate::get(overlay)->removePopup(popup: q);
786 }
787
788 window = newWindow;
789
790 if (newWindow) {
791 QQuickOverlay *overlay = QQuickOverlay::overlay(window: newWindow);
792 if (overlay)
793 QQuickOverlayPrivate::get(overlay)->addPopup(popup: q);
794
795 QQuickControlPrivate *p = QQuickControlPrivate::get(control: popupItem);
796 p->resolveFont();
797 if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(object: newWindow))
798 p->updateLocale(l: appWindow->locale(), e: false); // explicit=false
799 }
800
801 emit q->windowChanged(window: newWindow);
802
803 if (complete && visible && window)
804 transitionManager.transitionEnter();
805}
806
807void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
808{
809 Q_Q(QQuickPopup);
810 if (item == parentItem)
811 q->setParentItem(nullptr);
812}
813
814void QQuickPopupPrivate::reposition()
815{
816 getPositioner()->reposition();
817}
818
819QPalette QQuickPopupPrivate::defaultPalette() const
820{
821 return QQuickTheme::palette(scope: QQuickTheme::System);
822}
823
824static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent)
825{
826 QQuickItem *item = nullptr;
827 if (component) {
828 QQmlContext *context = component->creationContext();
829 if (!context)
830 context = qmlContext(popup);
831 item = qobject_cast<QQuickItem*>(o: component->beginCreate(context));
832 }
833
834 // when there is no overlay component available (with plain QQuickWindow),
835 // use a plain QQuickItem as a fallback to block hover events
836 if (!item && popup->isModal())
837 item = new QQuickItem;
838
839 if (item) {
840 item->setOpacity(popup->isVisible() ? 1.0 : 0.0);
841 item->setParentItem(parent);
842 item->stackBefore(popup->popupItem());
843 item->setZ(popup->z());
844 // needed for the virtual keyboard to set a containment mask on the dimmer item
845 qCDebug(lcDimmer) << "dimmer" << item << "registered with" << parent;
846 parent->setProperty(name: "_q_dimmerItem", value: QVariant::fromValue<QQuickItem*>(value: item));
847 if (popup->isModal()) {
848 item->setAcceptedMouseButtons(Qt::AllButtons);
849#if QT_CONFIG(cursor)
850 item->setCursor(Qt::ArrowCursor);
851#endif
852#if QT_CONFIG(quicktemplates2_hover)
853 // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
854 item->setAcceptHoverEvents(true);
855 // item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
856 // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
857#endif
858 }
859 if (component)
860 component->completeCreate();
861 }
862 qCDebug(lcDimmer) << "finished creating dimmer from component" << component
863 << "for popup" << popup << "with parent" << parent << "- item is:" << item;
864 return item;
865}
866
867void QQuickPopupPrivate::createOverlay()
868{
869 Q_Q(QQuickPopup);
870 QQuickOverlay *overlay = QQuickOverlay::overlay(window);
871 if (!overlay)
872 return;
873
874 QQmlComponent *component = nullptr;
875 QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(object: qmlAttachedPropertiesObject<QQuickOverlay>(obj: q, create: false));
876 if (overlayAttached)
877 component = modal ? overlayAttached->modal() : overlayAttached->modeless();
878
879 if (!component)
880 component = modal ? overlay->modal() : overlay->modeless();
881
882 if (!dimmer)
883 dimmer = createDimmer(component, popup: q, parent: overlay);
884 resizeOverlay();
885}
886
887void QQuickPopupPrivate::destroyOverlay()
888{
889 if (dimmer) {
890 qCDebug(lcDimmer) << "destroying dimmer" << dimmer;
891 if (QObject *dimmerParentItem = dimmer->parentItem()) {
892 if (dimmerParentItem->property(name: "_q_dimmerItem").value<QQuickItem*>() == dimmer)
893 dimmerParentItem->setProperty(name: "_q_dimmerItem", value: QVariant());
894 }
895 dimmer->setParentItem(nullptr);
896 dimmer->deleteLater();
897 dimmer = nullptr;
898 }
899}
900
901void QQuickPopupPrivate::toggleOverlay()
902{
903 destroyOverlay();
904 if (dim)
905 createOverlay();
906}
907
908void QQuickPopupPrivate::updateContentPalettes(const QPalette& parentPalette)
909{
910 // Inherit parent palette to all child objects
911 inheritPalette(parentPalette);
912
913 // Inherit parent palette to items within popup (such as headers and footers)
914 QQuickItemPrivate::get(item: popupItem)->updateChildrenPalettes(parentPalette);
915}
916
917void QQuickPopupPrivate::showOverlay()
918{
919 // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
920 if (dim && dimmer)
921 QQmlProperty::write(dimmer, QStringLiteral("opacity"), 1.0);
922}
923
924void QQuickPopupPrivate::hideOverlay()
925{
926 // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
927 if (dim && dimmer)
928 QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0);
929}
930
931void QQuickPopupPrivate::resizeOverlay()
932{
933 if (!dimmer)
934 return;
935
936 qreal w = window ? window->width() : 0;
937 qreal h = window ? window->height() : 0;
938 dimmer->setSize(QSizeF(w, h));
939}
940
941QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
942 : popup(popup)
943{
944}
945
946void QQuickPopupTransitionManager::transitionEnter()
947{
948 if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
949 cancel();
950
951 if (!popup->prepareEnterTransition())
952 return;
953
954 if (popup->window)
955 transition(popup->enterActions, transition: popup->enter, defaultTarget: popup->q_func());
956 else
957 finished();
958}
959
960void QQuickPopupTransitionManager::transitionExit()
961{
962 if (!popup->prepareExitTransition())
963 return;
964
965 if (popup->window)
966 transition(popup->exitActions, transition: popup->exit, defaultTarget: popup->q_func());
967 else
968 finished();
969}
970
971void QQuickPopupTransitionManager::finished()
972{
973 if (popup->transitionState == QQuickPopupPrivate::EnterTransition)
974 popup->finalizeEnterTransition();
975 else if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
976 popup->finalizeExitTransition();
977}
978
979QQuickPopup::QQuickPopup(QObject *parent)
980 : QObject(*(new QQuickPopupPrivate), parent)
981{
982 Q_D(QQuickPopup);
983 d->init();
984}
985
986QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent)
987 : QObject(dd, parent)
988{
989 Q_D(QQuickPopup);
990 d->init();
991}
992
993QQuickPopup::~QQuickPopup()
994{
995 Q_D(QQuickPopup);
996 d->inDestructor = true;
997
998 QQuickItem *currentContentItem = d->popupItem->d_func()->contentItem.data();
999 if (currentContentItem) {
1000 disconnect(sender: currentContentItem, signal: &QQuickItem::childrenChanged,
1001 receiver: this, slot: &QQuickPopup::contentChildrenChanged);
1002 }
1003
1004 setParentItem(nullptr);
1005
1006 // If the popup is destroyed before the exit transition finishes,
1007 // the necessary cleanup (removing modal dimmers that block mouse events,
1008 // emitting closed signal, etc.) won't happen. That's why we do it manually here.
1009 if (d->transitionState == QQuickPopupPrivate::ExitTransition && d->transitionManager.isRunning())
1010 d->finalizeExitTransition();
1011
1012 delete d->popupItem;
1013 d->popupItem = nullptr;
1014 delete d->positioner;
1015 d->positioner = nullptr;
1016}
1017
1018/*!
1019 \qmlmethod void QtQuick.Controls::Popup::open()
1020
1021 Opens the popup.
1022
1023 \sa visible
1024*/
1025void QQuickPopup::open()
1026{
1027 setVisible(true);
1028}
1029
1030/*!
1031 \qmlmethod void QtQuick.Controls::Popup::close()
1032
1033 Closes the popup.
1034
1035 \sa visible
1036*/
1037void QQuickPopup::close()
1038{
1039 setVisible(false);
1040}
1041
1042/*!
1043 \qmlproperty real QtQuick.Controls::Popup::x
1044
1045 This property holds the x-coordinate of the popup.
1046
1047 \sa y, z
1048*/
1049qreal QQuickPopup::x() const
1050{
1051 Q_D(const QQuickPopup);
1052 return d->effectiveX;
1053}
1054
1055void QQuickPopup::setX(qreal x)
1056{
1057 Q_D(QQuickPopup);
1058 setPosition(QPointF(x, d->y));
1059}
1060
1061/*!
1062 \qmlproperty real QtQuick.Controls::Popup::y
1063
1064 This property holds the y-coordinate of the popup.
1065
1066 \sa x, z
1067*/
1068qreal QQuickPopup::y() const
1069{
1070 Q_D(const QQuickPopup);
1071 return d->effectiveY;
1072}
1073
1074void QQuickPopup::setY(qreal y)
1075{
1076 Q_D(QQuickPopup);
1077 setPosition(QPointF(d->x, y));
1078}
1079
1080QPointF QQuickPopup::position() const
1081{
1082 Q_D(const QQuickPopup);
1083 return QPointF(d->effectiveX, d->effectiveY);
1084}
1085
1086void QQuickPopup::setPosition(const QPointF &pos)
1087{
1088 Q_D(QQuickPopup);
1089 const bool xChange = !qFuzzyCompare(p1: d->x, p2: pos.x());
1090 const bool yChange = !qFuzzyCompare(p1: d->y, p2: pos.y());
1091 if (!xChange && !yChange)
1092 return;
1093
1094 d->x = pos.x();
1095 d->y = pos.y();
1096 if (d->popupItem->isVisible()) {
1097 d->reposition();
1098 } else {
1099 if (xChange)
1100 emit xChanged();
1101 if (yChange)
1102 emit yChanged();
1103 }
1104}
1105
1106/*!
1107 \qmlproperty real QtQuick.Controls::Popup::z
1108
1109 This property holds the z-value of the popup. Z-value determines
1110 the stacking order of popups.
1111
1112 If two visible popups have the same z-value, the last one that
1113 was opened will be on top.
1114
1115 If a popup has no explicitly set z-value when opened, and is a child
1116 of an already open popup, then it will be stacked on top of its parent.
1117 This ensures that children are never hidden under their parents.
1118
1119 The default z-value is \c 0.
1120
1121 \sa x, y
1122*/
1123qreal QQuickPopup::z() const
1124{
1125 Q_D(const QQuickPopup);
1126 return d->popupItem->z();
1127}
1128
1129void QQuickPopup::setZ(qreal z)
1130{
1131 Q_D(QQuickPopup);
1132 d->hasZ = true;
1133 if (qFuzzyCompare(p1: z, p2: d->popupItem->z()))
1134 return;
1135 d->popupItem->setZ(z);
1136 emit zChanged();
1137}
1138
1139void QQuickPopup::resetZ()
1140{
1141 Q_D(QQuickPopup);
1142 setZ(0);
1143 d->hasZ = false;
1144}
1145
1146/*!
1147 \qmlproperty real QtQuick.Controls::Popup::width
1148
1149 This property holds the width of the popup.
1150*/
1151qreal QQuickPopup::width() const
1152{
1153 Q_D(const QQuickPopup);
1154 return d->popupItem->width();
1155}
1156
1157void QQuickPopup::setWidth(qreal width)
1158{
1159 Q_D(QQuickPopup);
1160 d->hasWidth = true;
1161 d->popupItem->setWidth(width);
1162}
1163
1164void QQuickPopup::resetWidth()
1165{
1166 Q_D(QQuickPopup);
1167 if (!d->hasWidth)
1168 return;
1169
1170 d->hasWidth = false;
1171 d->popupItem->resetWidth();
1172 if (d->popupItem->isVisible())
1173 d->reposition();
1174}
1175
1176/*!
1177 \qmlproperty real QtQuick.Controls::Popup::height
1178
1179 This property holds the height of the popup.
1180*/
1181qreal QQuickPopup::height() const
1182{
1183 Q_D(const QQuickPopup);
1184 return d->popupItem->height();
1185}
1186
1187void QQuickPopup::setHeight(qreal height)
1188{
1189 Q_D(QQuickPopup);
1190 d->hasHeight = true;
1191 d->popupItem->setHeight(height);
1192}
1193
1194void QQuickPopup::resetHeight()
1195{
1196 Q_D(QQuickPopup);
1197 if (!d->hasHeight)
1198 return;
1199
1200 d->hasHeight = false;
1201 d->popupItem->resetHeight();
1202 if (d->popupItem->isVisible())
1203 d->reposition();
1204}
1205
1206/*!
1207 \qmlproperty real QtQuick.Controls::Popup::implicitWidth
1208
1209 This property holds the implicit width of the popup.
1210*/
1211qreal QQuickPopup::implicitWidth() const
1212{
1213 Q_D(const QQuickPopup);
1214 return d->popupItem->implicitWidth();
1215}
1216
1217void QQuickPopup::setImplicitWidth(qreal width)
1218{
1219 Q_D(QQuickPopup);
1220 d->popupItem->setImplicitWidth(width);
1221}
1222
1223/*!
1224 \qmlproperty real QtQuick.Controls::Popup::implicitHeight
1225
1226 This property holds the implicit height of the popup.
1227*/
1228qreal QQuickPopup::implicitHeight() const
1229{
1230 Q_D(const QQuickPopup);
1231 return d->popupItem->implicitHeight();
1232}
1233
1234void QQuickPopup::setImplicitHeight(qreal height)
1235{
1236 Q_D(QQuickPopup);
1237 d->popupItem->setImplicitHeight(height);
1238}
1239
1240/*!
1241 \qmlproperty real QtQuick.Controls::Popup::contentWidth
1242
1243 This property holds the content width. It is used for calculating the
1244 total implicit width of the Popup.
1245
1246 For more information, see \l {Popup Sizing}.
1247
1248 \sa contentHeight
1249*/
1250qreal QQuickPopup::contentWidth() const
1251{
1252 Q_D(const QQuickPopup);
1253 return d->popupItem->contentWidth();
1254}
1255
1256void QQuickPopup::setContentWidth(qreal width)
1257{
1258 Q_D(QQuickPopup);
1259 d->popupItem->setContentWidth(width);
1260}
1261
1262/*!
1263 \qmlproperty real QtQuick.Controls::Popup::contentHeight
1264
1265 This property holds the content height. It is used for calculating the
1266 total implicit height of the Popup.
1267
1268 For more information, see \l {Popup Sizing}.
1269
1270 \sa contentWidth
1271*/
1272qreal QQuickPopup::contentHeight() const
1273{
1274 Q_D(const QQuickPopup);
1275 return d->popupItem->contentHeight();
1276}
1277
1278void QQuickPopup::setContentHeight(qreal height)
1279{
1280 Q_D(QQuickPopup);
1281 d->popupItem->setContentHeight(height);
1282}
1283
1284/*!
1285 \qmlproperty real QtQuick.Controls::Popup::availableWidth
1286 \readonly
1287
1288 This property holds the width available to the \l contentItem after
1289 deducting horizontal padding from the \l {Item::}{width} of the popup.
1290
1291 \sa padding, leftPadding, rightPadding
1292*/
1293qreal QQuickPopup::availableWidth() const
1294{
1295 Q_D(const QQuickPopup);
1296 return d->popupItem->availableWidth();
1297}
1298
1299/*!
1300 \qmlproperty real QtQuick.Controls::Popup::availableHeight
1301 \readonly
1302
1303 This property holds the height available to the \l contentItem after
1304 deducting vertical padding from the \l {Item::}{height} of the popup.
1305
1306 \sa padding, topPadding, bottomPadding
1307*/
1308qreal QQuickPopup::availableHeight() const
1309{
1310 Q_D(const QQuickPopup);
1311 return d->popupItem->availableHeight();
1312}
1313
1314/*!
1315 \since QtQuick.Controls 2.1 (Qt 5.8)
1316 \qmlproperty real QtQuick.Controls::Popup::spacing
1317
1318 This property holds the spacing.
1319
1320 Spacing is useful for popups that have multiple or repetitive building
1321 blocks. For example, some styles use spacing to determine the distance
1322 between the header, content, and footer of \l Dialog. Spacing is not
1323 enforced by Popup, so each style may interpret it differently, and some
1324 may ignore it altogether.
1325*/
1326qreal QQuickPopup::spacing() const
1327{
1328 Q_D(const QQuickPopup);
1329 return d->popupItem->spacing();
1330}
1331
1332void QQuickPopup::setSpacing(qreal spacing)
1333{
1334 Q_D(QQuickPopup);
1335 d->popupItem->setSpacing(spacing);
1336}
1337
1338void QQuickPopup::resetSpacing()
1339{
1340 setSpacing(0);
1341}
1342
1343/*!
1344 \qmlproperty real QtQuick.Controls::Popup::margins
1345
1346 This property holds the distance between the edges of the popup and the
1347 edges of its window.
1348
1349 A popup with negative margins is not pushed within the bounds
1350 of the enclosing window. The default value is \c -1.
1351
1352 \sa topMargin, leftMargin, rightMargin, bottomMargin, {Popup Layout}
1353*/
1354qreal QQuickPopup::margins() const
1355{
1356 Q_D(const QQuickPopup);
1357 return d->margins;
1358}
1359
1360void QQuickPopup::setMargins(qreal margins)
1361{
1362 Q_D(QQuickPopup);
1363 if (qFuzzyCompare(p1: d->margins, p2: margins))
1364 return;
1365 QMarginsF oldMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
1366 d->margins = margins;
1367 emit marginsChanged();
1368 QMarginsF newMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
1369 if (!qFuzzyCompare(p1: newMargins.top(), p2: oldMargins.top()))
1370 emit topMarginChanged();
1371 if (!qFuzzyCompare(p1: newMargins.left(), p2: oldMargins.left()))
1372 emit leftMarginChanged();
1373 if (!qFuzzyCompare(p1: newMargins.right(), p2: oldMargins.right()))
1374 emit rightMarginChanged();
1375 if (!qFuzzyCompare(p1: newMargins.bottom(), p2: oldMargins.bottom()))
1376 emit bottomMarginChanged();
1377 marginsChange(newMargins, oldMargins);
1378}
1379
1380void QQuickPopup::resetMargins()
1381{
1382 setMargins(-1);
1383}
1384
1385/*!
1386 \qmlproperty real QtQuick.Controls::Popup::topMargin
1387
1388 This property holds the distance between the top edge of the popup and
1389 the top edge of its window.
1390
1391 A popup with a negative top margin is not pushed within the top edge
1392 of the enclosing window. The default value is \c -1.
1393
1394 \sa margins, bottomMargin, {Popup Layout}
1395*/
1396qreal QQuickPopup::topMargin() const
1397{
1398 Q_D(const QQuickPopup);
1399 if (d->hasTopMargin)
1400 return d->topMargin;
1401 return d->margins;
1402}
1403
1404void QQuickPopup::setTopMargin(qreal margin)
1405{
1406 Q_D(QQuickPopup);
1407 d->setTopMargin(value: margin);
1408}
1409
1410void QQuickPopup::resetTopMargin()
1411{
1412 Q_D(QQuickPopup);
1413 d->setTopMargin(value: -1, reset: true);
1414}
1415
1416/*!
1417 \qmlproperty real QtQuick.Controls::Popup::leftMargin
1418
1419 This property holds the distance between the left edge of the popup and
1420 the left edge of its window.
1421
1422 A popup with a negative left margin is not pushed within the left edge
1423 of the enclosing window. The default value is \c -1.
1424
1425 \sa margins, rightMargin, {Popup Layout}
1426*/
1427qreal QQuickPopup::leftMargin() const
1428{
1429 Q_D(const QQuickPopup);
1430 if (d->hasLeftMargin)
1431 return d->leftMargin;
1432 return d->margins;
1433}
1434
1435void QQuickPopup::setLeftMargin(qreal margin)
1436{
1437 Q_D(QQuickPopup);
1438 d->setLeftMargin(value: margin);
1439}
1440
1441void QQuickPopup::resetLeftMargin()
1442{
1443 Q_D(QQuickPopup);
1444 d->setLeftMargin(value: -1, reset: true);
1445}
1446
1447/*!
1448 \qmlproperty real QtQuick.Controls::Popup::rightMargin
1449
1450 This property holds the distance between the right edge of the popup and
1451 the right edge of its window.
1452
1453 A popup with a negative right margin is not pushed within the right edge
1454 of the enclosing window. The default value is \c -1.
1455
1456 \sa margins, leftMargin, {Popup Layout}
1457*/
1458qreal QQuickPopup::rightMargin() const
1459{
1460 Q_D(const QQuickPopup);
1461 if (d->hasRightMargin)
1462 return d->rightMargin;
1463 return d->margins;
1464}
1465
1466void QQuickPopup::setRightMargin(qreal margin)
1467{
1468 Q_D(QQuickPopup);
1469 d->setRightMargin(value: margin);
1470}
1471
1472void QQuickPopup::resetRightMargin()
1473{
1474 Q_D(QQuickPopup);
1475 d->setRightMargin(value: -1, reset: true);
1476}
1477
1478/*!
1479 \qmlproperty real QtQuick.Controls::Popup::bottomMargin
1480
1481 This property holds the distance between the bottom edge of the popup and
1482 the bottom edge of its window.
1483
1484 A popup with a negative bottom margin is not pushed within the bottom edge
1485 of the enclosing window. The default value is \c -1.
1486
1487 \sa margins, topMargin, {Popup Layout}
1488*/
1489qreal QQuickPopup::bottomMargin() const
1490{
1491 Q_D(const QQuickPopup);
1492 if (d->hasBottomMargin)
1493 return d->bottomMargin;
1494 return d->margins;
1495}
1496
1497void QQuickPopup::setBottomMargin(qreal margin)
1498{
1499 Q_D(QQuickPopup);
1500 d->setBottomMargin(value: margin);
1501}
1502
1503void QQuickPopup::resetBottomMargin()
1504{
1505 Q_D(QQuickPopup);
1506 d->setBottomMargin(value: -1, reset: true);
1507}
1508
1509/*!
1510 \qmlproperty real QtQuick.Controls::Popup::padding
1511
1512 This property holds the default padding.
1513
1514 \include qquickpopup-padding.qdocinc
1515
1516 \sa availableWidth, availableHeight, topPadding, leftPadding, rightPadding, bottomPadding
1517*/
1518qreal QQuickPopup::padding() const
1519{
1520 Q_D(const QQuickPopup);
1521 return d->popupItem->padding();
1522}
1523
1524void QQuickPopup::setPadding(qreal padding)
1525{
1526 Q_D(QQuickPopup);
1527 d->popupItem->setPadding(padding);
1528}
1529
1530void QQuickPopup::resetPadding()
1531{
1532 Q_D(QQuickPopup);
1533 d->popupItem->resetPadding();
1534}
1535
1536/*!
1537 \qmlproperty real QtQuick.Controls::Popup::topPadding
1538
1539 This property holds the top padding. Unless explicitly set, the value
1540 is equal to \c verticalPadding.
1541
1542 \include qquickpopup-padding.qdocinc
1543
1544 \sa padding, bottomPadding, verticalPadding, availableHeight
1545*/
1546qreal QQuickPopup::topPadding() const
1547{
1548 Q_D(const QQuickPopup);
1549 return d->popupItem->topPadding();
1550}
1551
1552void QQuickPopup::setTopPadding(qreal padding)
1553{
1554 Q_D(QQuickPopup);
1555 d->popupItem->setTopPadding(padding);
1556}
1557
1558void QQuickPopup::resetTopPadding()
1559{
1560 Q_D(QQuickPopup);
1561 d->popupItem->resetTopPadding();
1562}
1563
1564/*!
1565 \qmlproperty real QtQuick.Controls::Popup::leftPadding
1566
1567 This property holds the left padding. Unless explicitly set, the value
1568 is equal to \c horizontalPadding.
1569
1570 \include qquickpopup-padding.qdocinc
1571
1572 \sa padding, rightPadding, horizontalPadding, availableWidth
1573*/
1574qreal QQuickPopup::leftPadding() const
1575{
1576 Q_D(const QQuickPopup);
1577 return d->popupItem->leftPadding();
1578}
1579
1580void QQuickPopup::setLeftPadding(qreal padding)
1581{
1582 Q_D(QQuickPopup);
1583 d->popupItem->setLeftPadding(padding);
1584}
1585
1586void QQuickPopup::resetLeftPadding()
1587{
1588 Q_D(QQuickPopup);
1589 d->popupItem->resetLeftPadding();
1590}
1591
1592/*!
1593 \qmlproperty real QtQuick.Controls::Popup::rightPadding
1594
1595 This property holds the right padding. Unless explicitly set, the value
1596 is equal to \c horizontalPadding.
1597
1598 \include qquickpopup-padding.qdocinc
1599
1600 \sa padding, leftPadding, horizontalPadding, availableWidth
1601*/
1602qreal QQuickPopup::rightPadding() const
1603{
1604 Q_D(const QQuickPopup);
1605 return d->popupItem->rightPadding();
1606}
1607
1608void QQuickPopup::setRightPadding(qreal padding)
1609{
1610 Q_D(QQuickPopup);
1611 d->popupItem->setRightPadding(padding);
1612}
1613
1614void QQuickPopup::resetRightPadding()
1615{
1616 Q_D(QQuickPopup);
1617 d->popupItem->resetRightPadding();
1618}
1619
1620/*!
1621 \qmlproperty real QtQuick.Controls::Popup::bottomPadding
1622
1623 This property holds the bottom padding. Unless explicitly set, the value
1624 is equal to \c verticalPadding.
1625
1626 \include qquickpopup-padding.qdocinc
1627
1628 \sa padding, topPadding, verticalPadding, availableHeight
1629*/
1630qreal QQuickPopup::bottomPadding() const
1631{
1632 Q_D(const QQuickPopup);
1633 return d->popupItem->bottomPadding();
1634}
1635
1636void QQuickPopup::setBottomPadding(qreal padding)
1637{
1638 Q_D(QQuickPopup);
1639 d->popupItem->setBottomPadding(padding);
1640}
1641
1642void QQuickPopup::resetBottomPadding()
1643{
1644 Q_D(QQuickPopup);
1645 d->popupItem->resetBottomPadding();
1646}
1647
1648/*!
1649 \qmlproperty Locale QtQuick.Controls::Popup::locale
1650
1651 This property holds the locale of the popup.
1652
1653 \sa mirrored, {LayoutMirroring}{LayoutMirroring}
1654*/
1655QLocale QQuickPopup::locale() const
1656{
1657 Q_D(const QQuickPopup);
1658 return d->popupItem->locale();
1659}
1660
1661void QQuickPopup::setLocale(const QLocale &locale)
1662{
1663 Q_D(QQuickPopup);
1664 d->popupItem->setLocale(locale);
1665}
1666
1667void QQuickPopup::resetLocale()
1668{
1669 Q_D(QQuickPopup);
1670 d->popupItem->resetLocale();
1671}
1672
1673/*!
1674 \since QtQuick.Controls 2.3 (Qt 5.10)
1675 \qmlproperty bool QtQuick.Controls::Popup::mirrored
1676 \readonly
1677
1678 This property holds whether the popup is mirrored.
1679
1680 This property is provided for convenience. A popup is considered mirrored
1681 when its visual layout direction is right-to-left; that is, when using a
1682 right-to-left locale.
1683
1684 \sa locale, {Right-to-left User Interfaces}
1685*/
1686bool QQuickPopup::isMirrored() const
1687{
1688 Q_D(const QQuickPopup);
1689 return d->popupItem->isMirrored();
1690}
1691
1692/*!
1693 \qmlproperty font QtQuick.Controls::Popup::font
1694
1695 This property holds the font currently set for the popup.
1696
1697 Popup propagates explicit font properties to its children. If you change a specific
1698 property on a popup's font, that property propagates to all of the popup's children,
1699 overriding any system defaults for that property.
1700
1701 \code
1702 Popup {
1703 font.family: "Courier"
1704
1705 Column {
1706 Label {
1707 text: qsTr("This will use Courier...")
1708 }
1709
1710 Switch {
1711 text: qsTr("... and so will this")
1712 }
1713 }
1714 }
1715 \endcode
1716
1717 \sa Control::font, ApplicationWindow::font
1718*/
1719QFont QQuickPopup::font() const
1720{
1721 Q_D(const QQuickPopup);
1722 return d->popupItem->font();
1723}
1724
1725void QQuickPopup::setFont(const QFont &font)
1726{
1727 Q_D(QQuickPopup);
1728 d->popupItem->setFont(font);
1729}
1730
1731void QQuickPopup::resetFont()
1732{
1733 Q_D(QQuickPopup);
1734 d->popupItem->resetFont();
1735}
1736
1737QQuickWindow *QQuickPopup::window() const
1738{
1739 Q_D(const QQuickPopup);
1740 return d->window;
1741}
1742
1743QQuickItem *QQuickPopup::popupItem() const
1744{
1745 Q_D(const QQuickPopup);
1746 return d->popupItem;
1747}
1748
1749/*!
1750 \qmlproperty Item QtQuick.Controls::Popup::parent
1751
1752 This property holds the parent item.
1753*/
1754QQuickItem *QQuickPopup::parentItem() const
1755{
1756 Q_D(const QQuickPopup);
1757 return d->parentItem;
1758}
1759
1760void QQuickPopup::setParentItem(QQuickItem *parent)
1761{
1762 Q_D(QQuickPopup);
1763 if (d->parentItem == parent)
1764 return;
1765
1766 if (d->parentItem) {
1767 QObjectPrivate::disconnect(sender: d->parentItem, signal: &QQuickItem::windowChanged, receiverPrivate: d, slot: &QQuickPopupPrivate::setWindow);
1768 QQuickItemPrivate::get(item: d->parentItem)->removeItemChangeListener(d, types: QQuickItemPrivate::Destroyed);
1769 }
1770 d->parentItem = parent;
1771 QQuickPopupPositioner *positioner = d->getPositioner();
1772 if (positioner->parentItem())
1773 positioner->setParentItem(parent);
1774 if (parent) {
1775 QObjectPrivate::connect(sender: parent, signal: &QQuickItem::windowChanged, receiverPrivate: d, slot: &QQuickPopupPrivate::setWindow);
1776 QQuickItemPrivate::get(item: d->parentItem)->addItemChangeListener(listener: d, types: QQuickItemPrivate::Destroyed);
1777 } else if (!d->inDestructor) {
1778 // NOTE: if setParentItem is called from the dtor, this bypasses virtual dispatch and calls QQuickPopup::close() directly
1779 close();
1780 }
1781 d->setWindow(parent ? parent->window() : nullptr);
1782 emit parentChanged();
1783}
1784
1785void QQuickPopup::resetParentItem()
1786{
1787 if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object: parent()))
1788 setParentItem(window->contentItem());
1789 else
1790 setParentItem(qobject_cast<QQuickItem *>(o: parent()));
1791}
1792
1793/*!
1794 \qmlproperty Item QtQuick.Controls::Popup::background
1795
1796 This property holds the background item.
1797
1798 \note If the background item has no explicit size specified, it automatically
1799 follows the popup's size. In most cases, there is no need to specify
1800 width or height for a background item.
1801
1802 \note Most popups use the implicit size of the background item to calculate
1803 the implicit size of the popup itself. If you replace the background item
1804 with a custom one, you should also consider providing a sensible implicit
1805 size for it (unless it is an item like \l Image which has its own implicit
1806 size).
1807
1808 \sa {Customizing Popup}
1809*/
1810QQuickItem *QQuickPopup::background() const
1811{
1812 Q_D(const QQuickPopup);
1813 return d->popupItem->background();
1814}
1815
1816void QQuickPopup::setBackground(QQuickItem *background)
1817{
1818 Q_D(QQuickPopup);
1819 // The __notCustomizable property won't be on "this" when the popup item's setBackground function
1820 // is called, so it won't warn. That's why we do a check here.
1821 QQuickControlPrivate::warnIfCustomizationNotSupported(control: this, item: background, QStringLiteral("background"));
1822 d->popupItem->setBackground(background);
1823}
1824
1825/*!
1826 \qmlproperty Item QtQuick.Controls::Popup::contentItem
1827
1828 This property holds the content item of the popup.
1829
1830 The content item is the visual implementation of the popup. When the
1831 popup is made visible, the content item is automatically reparented to
1832 the \l {Overlay::overlay}{overlay item}.
1833
1834 \note The content item is automatically resized to fit within the
1835 \l padding of the popup.
1836
1837 \note Most popups use the implicit size of the content item to calculate
1838 the implicit size of the popup itself. If you replace the content item
1839 with a custom one, you should also consider providing a sensible implicit
1840 size for it (unless it is an item like \l Text which has its own implicit
1841 size).
1842
1843 \sa {Customizing Popup}
1844*/
1845QQuickItem *QQuickPopup::contentItem() const
1846{
1847 Q_D(const QQuickPopup);
1848 return d->popupItem->contentItem();
1849}
1850
1851void QQuickPopup::setContentItem(QQuickItem *item)
1852{
1853 Q_D(QQuickPopup);
1854 // See comment in setBackground for why we do this.
1855 QQuickControlPrivate::warnIfCustomizationNotSupported(control: this, item, QStringLiteral("contentItem"));
1856 QQuickItem *oldContentItem = d->complete ? d->popupItem->d_func()->contentItem.data()
1857 : nullptr;
1858 if (oldContentItem)
1859 disconnect(sender: oldContentItem, signal: &QQuickItem::childrenChanged, receiver: this, slot: &QQuickPopup::contentChildrenChanged);
1860 d->popupItem->setContentItem(item);
1861 if (d->complete) {
1862 QQuickItem *newContentItem = d->popupItem->d_func()->contentItem.data();
1863 connect(sender: newContentItem, signal: &QQuickItem::childrenChanged, context: this, slot: &QQuickPopup::contentChildrenChanged);
1864 if (oldContentItem != newContentItem)
1865 emit contentChildrenChanged();
1866 }
1867}
1868
1869/*!
1870 \qmlproperty list<QtObject> QtQuick.Controls::Popup::contentData
1871 \qmldefault
1872
1873 This property holds the list of content data.
1874
1875 The list contains all objects that have been declared in QML as children
1876 of the popup.
1877
1878 \note Unlike \c contentChildren, \c contentData does include non-visual QML
1879 objects.
1880
1881 \sa Item::data, contentChildren
1882*/
1883QQmlListProperty<QObject> QQuickPopupPrivate::contentData()
1884{
1885 QQuickControlPrivate *p = QQuickControlPrivate::get(control: popupItem);
1886 if (!p->contentItem)
1887 p->executeContentItem();
1888 return QQmlListProperty<QObject>(popupItem->contentItem(), nullptr,
1889 QQuickItemPrivate::data_append,
1890 QQuickItemPrivate::data_count,
1891 QQuickItemPrivate::data_at,
1892 QQuickItemPrivate::data_clear);
1893}
1894
1895/*!
1896 \qmlproperty list<Item> QtQuick.Controls::Popup::contentChildren
1897
1898 This property holds the list of content children.
1899
1900 The list contains all items that have been declared in QML as children
1901 of the popup.
1902
1903 \note Unlike \c contentData, \c contentChildren does not include non-visual
1904 QML objects.
1905
1906 \sa Item::children, contentData
1907*/
1908QQmlListProperty<QQuickItem> QQuickPopupPrivate::contentChildren()
1909{
1910 return QQmlListProperty<QQuickItem>(popupItem->contentItem(), nullptr,
1911 QQuickItemPrivate::children_append,
1912 QQuickItemPrivate::children_count,
1913 QQuickItemPrivate::children_at,
1914 QQuickItemPrivate::children_clear);
1915}
1916
1917/*!
1918 \qmlproperty bool QtQuick.Controls::Popup::clip
1919
1920 This property holds whether clipping is enabled. The default value is \c false.
1921*/
1922bool QQuickPopup::clip() const
1923{
1924 Q_D(const QQuickPopup);
1925 return d->popupItem->clip();
1926}
1927
1928void QQuickPopup::setClip(bool clip)
1929{
1930 Q_D(QQuickPopup);
1931 if (clip == d->popupItem->clip())
1932 return;
1933 d->popupItem->setClip(clip);
1934 emit clipChanged();
1935}
1936
1937/*!
1938 \qmlproperty bool QtQuick.Controls::Popup::focus
1939
1940 This property holds whether the popup wants focus.
1941
1942 When the popup actually receives focus, \l activeFocus will be \c true.
1943 For more information, see \l {Keyboard Focus in Qt Quick}.
1944
1945 The default value is \c false.
1946
1947 \sa activeFocus
1948*/
1949bool QQuickPopup::hasFocus() const
1950{
1951 Q_D(const QQuickPopup);
1952 return d->focus;
1953}
1954
1955void QQuickPopup::setFocus(bool focus)
1956{
1957 Q_D(QQuickPopup);
1958 if (d->focus == focus)
1959 return;
1960 d->focus = focus;
1961 emit focusChanged();
1962}
1963
1964/*!
1965 \qmlproperty bool QtQuick.Controls::Popup::activeFocus
1966 \readonly
1967
1968 This property holds whether the popup has active focus.
1969
1970 \sa focus, {Keyboard Focus in Qt Quick}
1971*/
1972bool QQuickPopup::hasActiveFocus() const
1973{
1974 Q_D(const QQuickPopup);
1975 return d->popupItem->hasActiveFocus();
1976}
1977
1978/*!
1979 \qmlproperty bool QtQuick.Controls::Popup::modal
1980
1981 This property holds whether the popup is modal.
1982
1983 Modal popups often have a distinctive background dimming effect defined
1984 in \l {Overlay::modal}{Overlay.modal}, and do not allow press
1985 or release events through to items beneath them. For example, if the user
1986 accidentally clicks outside of a popup, any item beneath that popup at
1987 the location of the click will not receive the event.
1988
1989 On desktop platforms, it is common for modal popups to be closed only when
1990 the escape key is pressed. To achieve this behavior, set
1991 \l closePolicy to \c Popup.CloseOnEscape. By default, \c closePolicy
1992 is set to \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}, which
1993 means that clicking outside of a modal popup will close it.
1994
1995 The default value is \c false.
1996
1997 \sa dim
1998*/
1999bool QQuickPopup::isModal() const
2000{
2001 Q_D(const QQuickPopup);
2002 return d->modal;
2003}
2004
2005void QQuickPopup::setModal(bool modal)
2006{
2007 Q_D(QQuickPopup);
2008 if (d->modal == modal)
2009 return;
2010 d->modal = modal;
2011 if (d->complete && d->visible)
2012 d->toggleOverlay();
2013 emit modalChanged();
2014
2015 QQuickItemPrivate::get(item: d->popupItem)->isTabFence = modal;
2016
2017 if (!d->hasDim) {
2018 setDim(modal);
2019 d->hasDim = false;
2020 }
2021}
2022
2023/*!
2024 \qmlproperty bool QtQuick.Controls::Popup::dim
2025
2026 This property holds whether the popup dims the background.
2027
2028 Unless explicitly set, this property follows the value of \l modal. To
2029 return to the default value, set this property to \c undefined.
2030
2031 \sa modal, {Overlay::modeless}{Overlay.modeless}
2032*/
2033bool QQuickPopup::dim() const
2034{
2035 Q_D(const QQuickPopup);
2036 return d->dim;
2037}
2038
2039void QQuickPopup::setDim(bool dim)
2040{
2041 Q_D(QQuickPopup);
2042 d->hasDim = true;
2043
2044 if (d->dim == dim)
2045 return;
2046
2047 d->dim = dim;
2048 if (d->complete && d->visible)
2049 d->toggleOverlay();
2050 emit dimChanged();
2051}
2052
2053void QQuickPopup::resetDim()
2054{
2055 Q_D(QQuickPopup);
2056 if (!d->hasDim)
2057 return;
2058
2059 setDim(d->modal);
2060 d->hasDim = false;
2061}
2062
2063/*!
2064 \qmlproperty bool QtQuick.Controls::Popup::visible
2065
2066 This property holds whether the popup is visible. The default value is \c false.
2067
2068 \sa open(), close(), opened
2069*/
2070bool QQuickPopup::isVisible() const
2071{
2072 Q_D(const QQuickPopup);
2073 return d->visible && d->popupItem->isVisible();
2074}
2075
2076void QQuickPopup::setVisible(bool visible)
2077{
2078 Q_D(QQuickPopup);
2079 if (d->visible == visible && d->transitionState != QQuickPopupPrivate::ExitTransition)
2080 return;
2081
2082 if (d->complete) {
2083 if (visible)
2084 d->transitionManager.transitionEnter();
2085 else
2086 d->transitionManager.transitionExit();
2087 } else {
2088 d->visible = visible;
2089 }
2090}
2091
2092/*!
2093 \since QtQuick.Controls 2.3 (Qt 5.10)
2094 \qmlproperty bool QtQuick.Controls::Popup::enabled
2095
2096 This property holds whether the popup is enabled. The default value is \c true.
2097
2098 \sa visible, Item::enabled
2099*/
2100bool QQuickPopup::isEnabled() const
2101{
2102 Q_D(const QQuickPopup);
2103 return d->popupItem->isEnabled();
2104}
2105
2106void QQuickPopup::setEnabled(bool enabled)
2107{
2108 Q_D(QQuickPopup);
2109 d->popupItem->setEnabled(enabled);
2110}
2111
2112/*!
2113 \since QtQuick.Controls 2.3 (Qt 5.10)
2114 \qmlproperty bool QtQuick.Controls::Popup::opened
2115
2116 This property holds whether the popup is fully open. The popup is considered opened
2117 when it's visible and neither the \l enter nor \l exit transitions are running.
2118
2119 \sa open(), close(), visible
2120*/
2121bool QQuickPopup::isOpened() const
2122{
2123 Q_D(const QQuickPopup);
2124 return d->transitionState == QQuickPopupPrivate::NoTransition && isVisible();
2125}
2126
2127/*!
2128 \qmlproperty real QtQuick.Controls::Popup::opacity
2129
2130 This property holds the opacity of the popup. Opacity is specified as a number between
2131 \c 0.0 (fully transparent) and \c 1.0 (fully opaque). The default value is \c 1.0.
2132
2133 \sa visible
2134*/
2135qreal QQuickPopup::opacity() const
2136{
2137 Q_D(const QQuickPopup);
2138 return d->popupItem->opacity();
2139}
2140
2141void QQuickPopup::setOpacity(qreal opacity)
2142{
2143 Q_D(QQuickPopup);
2144 d->popupItem->setOpacity(opacity);
2145}
2146
2147/*!
2148 \qmlproperty real QtQuick.Controls::Popup::scale
2149
2150 This property holds the scale factor of the popup. The default value is \c 1.0.
2151
2152 A scale of less than \c 1.0 causes the popup to be rendered at a smaller size,
2153 and a scale greater than \c 1.0 renders the popup at a larger size. Negative
2154 scales are not supported.
2155*/
2156qreal QQuickPopup::scale() const
2157{
2158 Q_D(const QQuickPopup);
2159 return d->popupItem->scale();
2160}
2161
2162void QQuickPopup::setScale(qreal scale)
2163{
2164 Q_D(QQuickPopup);
2165 if (qFuzzyCompare(p1: scale, p2: d->popupItem->scale()))
2166 return;
2167 d->popupItem->setScale(scale);
2168 emit scaleChanged();
2169}
2170
2171/*!
2172 \qmlproperty enumeration QtQuick.Controls::Popup::closePolicy
2173
2174 This property determines the circumstances under which the popup closes.
2175 The flags can be combined to allow several ways of closing the popup.
2176
2177 The available values are:
2178 \value Popup.NoAutoClose The popup will only close when manually instructed to do so.
2179 \value Popup.CloseOnPressOutside The popup will close when the mouse is pressed outside of it.
2180 \value Popup.CloseOnPressOutsideParent The popup will close when the mouse is pressed outside of its parent.
2181 \value Popup.CloseOnReleaseOutside The popup will close when the mouse is released outside of it.
2182 \value Popup.CloseOnReleaseOutsideParent The popup will close when the mouse is released outside of its parent.
2183 \value Popup.CloseOnEscape The popup will close when the escape key is pressed while the popup
2184 has active focus.
2185
2186 The \c {CloseOnPress*} and \c {CloseOnRelease*} policies only apply for events
2187 outside of popups. That is, if there are two popups open and the first has
2188 \c Popup.CloseOnPressOutside as its policy, clicking on the second popup will
2189 not result in the first closing.
2190
2191 The default value is \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}.
2192
2193 \note There is a known limitation that the \c Popup.CloseOnReleaseOutside
2194 and \c Popup.CloseOnReleaseOutsideParent policies only work with
2195 \l modal popups.
2196*/
2197QQuickPopup::ClosePolicy QQuickPopup::closePolicy() const
2198{
2199 Q_D(const QQuickPopup);
2200 return d->closePolicy;
2201}
2202
2203void QQuickPopup::setClosePolicy(ClosePolicy policy)
2204{
2205 Q_D(QQuickPopup);
2206 d->hasClosePolicy = true;
2207 if (d->closePolicy == policy)
2208 return;
2209 d->closePolicy = policy;
2210 emit closePolicyChanged();
2211}
2212
2213void QQuickPopup::resetClosePolicy()
2214{
2215 Q_D(QQuickPopup);
2216 setClosePolicy(QQuickPopupPrivate::DefaultClosePolicy);
2217 d->hasClosePolicy = false;
2218}
2219
2220/*!
2221 \qmlproperty enumeration QtQuick.Controls::Popup::transformOrigin
2222
2223 This property holds the origin point for transformations in enter and exit transitions.
2224
2225 Nine transform origins are available, as shown in the image below.
2226 The default transform origin is \c Popup.Center.
2227
2228 \image qtquickcontrols-popup-transformorigin.png
2229
2230 \sa enter, exit, Item::transformOrigin
2231*/
2232QQuickPopup::TransformOrigin QQuickPopup::transformOrigin() const
2233{
2234 Q_D(const QQuickPopup);
2235 return static_cast<TransformOrigin>(d->popupItem->transformOrigin());
2236}
2237
2238void QQuickPopup::setTransformOrigin(TransformOrigin origin)
2239{
2240 Q_D(QQuickPopup);
2241 d->popupItem->setTransformOrigin(static_cast<QQuickItem::TransformOrigin>(origin));
2242}
2243
2244/*!
2245 \qmlproperty Transition QtQuick.Controls::Popup::enter
2246
2247 This property holds the transition that is applied to the popup item
2248 when the popup is opened and enters the screen.
2249
2250 The following example animates the opacity of the popup when it enters
2251 the screen:
2252 \code
2253 Popup {
2254 enter: Transition {
2255 NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 }
2256 }
2257 }
2258 \endcode
2259
2260 \sa exit
2261*/
2262QQuickTransition *QQuickPopup::enter() const
2263{
2264 Q_D(const QQuickPopup);
2265 return d->enter;
2266}
2267
2268void QQuickPopup::setEnter(QQuickTransition *transition)
2269{
2270 Q_D(QQuickPopup);
2271 if (d->enter == transition)
2272 return;
2273 d->enter = transition;
2274 emit enterChanged();
2275}
2276
2277/*!
2278 \qmlproperty Transition QtQuick.Controls::Popup::exit
2279
2280 This property holds the transition that is applied to the popup item
2281 when the popup is closed and exits the screen.
2282
2283 The following example animates the opacity of the popup when it exits
2284 the screen:
2285 \code
2286 Popup {
2287 exit: Transition {
2288 NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 }
2289 }
2290 }
2291 \endcode
2292
2293 \sa enter
2294*/
2295QQuickTransition *QQuickPopup::exit() const
2296{
2297 Q_D(const QQuickPopup);
2298 return d->exit;
2299}
2300
2301void QQuickPopup::setExit(QQuickTransition *transition)
2302{
2303 Q_D(QQuickPopup);
2304 if (d->exit == transition)
2305 return;
2306 d->exit = transition;
2307 emit exitChanged();
2308}
2309
2310/*!
2311 \since QtQuick.Controls 2.5 (Qt 5.12)
2312 \qmlproperty real QtQuick.Controls::Popup::horizontalPadding
2313
2314 This property holds the horizontal padding. Unless explicitly set, the value
2315 is equal to \c padding.
2316
2317 \include qquickpopup-padding.qdocinc
2318
2319 \sa padding, leftPadding, rightPadding, verticalPadding
2320*/
2321qreal QQuickPopup::horizontalPadding() const
2322{
2323 Q_D(const QQuickPopup);
2324 return d->popupItem->horizontalPadding();
2325}
2326
2327void QQuickPopup::setHorizontalPadding(qreal padding)
2328{
2329 Q_D(QQuickPopup);
2330 d->popupItem->setHorizontalPadding(padding);
2331}
2332
2333void QQuickPopup::resetHorizontalPadding()
2334{
2335 Q_D(QQuickPopup);
2336 d->popupItem->resetHorizontalPadding();
2337}
2338
2339/*!
2340 \since QtQuick.Controls 2.5 (Qt 5.12)
2341 \qmlproperty real QtQuick.Controls::Popup::verticalPadding
2342
2343 This property holds the vertical padding. Unless explicitly set, the value
2344 is equal to \c padding.
2345
2346 \include qquickpopup-padding.qdocinc
2347
2348 \sa padding, topPadding, bottomPadding, horizontalPadding
2349*/
2350qreal QQuickPopup::verticalPadding() const
2351{
2352 Q_D(const QQuickPopup);
2353 return d->popupItem->verticalPadding();
2354}
2355
2356void QQuickPopup::setVerticalPadding(qreal padding)
2357{
2358 Q_D(QQuickPopup);
2359 d->popupItem->setVerticalPadding(padding);
2360}
2361
2362void QQuickPopup::resetVerticalPadding()
2363{
2364 Q_D(QQuickPopup);
2365 d->popupItem->resetVerticalPadding();
2366}
2367
2368/*!
2369 \since QtQuick.Controls 2.5 (Qt 5.12)
2370 \qmlproperty real QtQuick.Controls::Popup::implicitContentWidth
2371 \readonly
2372
2373 This property holds the implicit content width.
2374
2375 The value is calculated based on the content children.
2376
2377 \sa implicitContentHeight, implicitBackgroundWidth
2378*/
2379qreal QQuickPopup::implicitContentWidth() const
2380{
2381 Q_D(const QQuickPopup);
2382 return d->popupItem->implicitContentWidth();
2383}
2384
2385/*!
2386 \since QtQuick.Controls 2.5 (Qt 5.12)
2387 \qmlproperty real QtQuick.Controls::Popup::implicitContentHeight
2388 \readonly
2389
2390 This property holds the implicit content height.
2391
2392 The value is calculated based on the content children.
2393
2394 \sa implicitContentWidth, implicitBackgroundHeight
2395*/
2396qreal QQuickPopup::implicitContentHeight() const
2397{
2398 Q_D(const QQuickPopup);
2399 return d->popupItem->implicitContentHeight();
2400}
2401
2402/*!
2403 \since QtQuick.Controls 2.5 (Qt 5.12)
2404 \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundWidth
2405 \readonly
2406
2407 This property holds the implicit background width.
2408
2409 The value is equal to \c {background ? background.implicitWidth : 0}.
2410
2411 \sa implicitBackgroundHeight, implicitContentWidth
2412*/
2413qreal QQuickPopup::implicitBackgroundWidth() const
2414{
2415 Q_D(const QQuickPopup);
2416 return d->popupItem->implicitBackgroundWidth();
2417}
2418
2419/*!
2420 \since QtQuick.Controls 2.5 (Qt 5.12)
2421 \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundHeight
2422 \readonly
2423
2424 This property holds the implicit background height.
2425
2426 The value is equal to \c {background ? background.implicitHeight : 0}.
2427
2428 \sa implicitBackgroundWidth, implicitContentHeight
2429*/
2430qreal QQuickPopup::implicitBackgroundHeight() const
2431{
2432 Q_D(const QQuickPopup);
2433 return d->popupItem->implicitBackgroundHeight();
2434}
2435
2436/*!
2437 \since QtQuick.Controls 2.5 (Qt 5.12)
2438 \qmlproperty real QtQuick.Controls::Popup::topInset
2439
2440 This property holds the top inset for the background.
2441
2442 \sa {Popup Layout}, bottomInset
2443*/
2444qreal QQuickPopup::topInset() const
2445{
2446 Q_D(const QQuickPopup);
2447 return d->popupItem->topInset();
2448}
2449
2450void QQuickPopup::setTopInset(qreal inset)
2451{
2452 Q_D(QQuickPopup);
2453 d->popupItem->setTopInset(inset);
2454}
2455
2456void QQuickPopup::resetTopInset()
2457{
2458 Q_D(QQuickPopup);
2459 d->popupItem->resetTopInset();
2460}
2461
2462/*!
2463 \since QtQuick.Controls 2.5 (Qt 5.12)
2464 \qmlproperty real QtQuick.Controls::Popup::leftInset
2465
2466 This property holds the left inset for the background.
2467
2468 \sa {Popup Layout}, rightInset
2469*/
2470qreal QQuickPopup::leftInset() const
2471{
2472 Q_D(const QQuickPopup);
2473 return d->popupItem->leftInset();
2474}
2475
2476void QQuickPopup::setLeftInset(qreal inset)
2477{
2478 Q_D(QQuickPopup);
2479 d->popupItem->setLeftInset(inset);
2480}
2481
2482void QQuickPopup::resetLeftInset()
2483{
2484 Q_D(QQuickPopup);
2485 d->popupItem->resetLeftInset();
2486}
2487
2488/*!
2489 \since QtQuick.Controls 2.5 (Qt 5.12)
2490 \qmlproperty real QtQuick.Controls::Popup::rightInset
2491
2492 This property holds the right inset for the background.
2493
2494 \sa {Popup Layout}, leftInset
2495*/
2496qreal QQuickPopup::rightInset() const
2497{
2498 Q_D(const QQuickPopup);
2499 return d->popupItem->rightInset();
2500}
2501
2502void QQuickPopup::setRightInset(qreal inset)
2503{
2504 Q_D(QQuickPopup);
2505 d->popupItem->setRightInset(inset);
2506}
2507
2508void QQuickPopup::resetRightInset()
2509{
2510 Q_D(QQuickPopup);
2511 d->popupItem->resetRightInset();
2512}
2513
2514/*!
2515 \since QtQuick.Controls 2.5 (Qt 5.12)
2516 \qmlproperty real QtQuick.Controls::Popup::bottomInset
2517
2518 This property holds the bottom inset for the background.
2519
2520 \sa {Popup Layout}, topInset
2521*/
2522qreal QQuickPopup::bottomInset() const
2523{
2524 Q_D(const QQuickPopup);
2525 return d->popupItem->bottomInset();
2526}
2527
2528void QQuickPopup::setBottomInset(qreal inset)
2529{
2530 Q_D(QQuickPopup);
2531 d->popupItem->setBottomInset(inset);
2532}
2533
2534void QQuickPopup::resetBottomInset()
2535{
2536 Q_D(QQuickPopup);
2537 d->popupItem->resetBottomInset();
2538}
2539
2540/*!
2541 \since QtQuick.Controls 2.3 (Qt 5.10)
2542 \qmlproperty palette QtQuick.Controls::Popup::palette
2543
2544 This property holds the palette currently set for the popup.
2545
2546 Popup propagates explicit palette properties to its children. If you change a specific
2547 property on a popup's palette, that property propagates to all of the popup's children,
2548 overriding any system defaults for that property.
2549
2550 \code
2551 Popup {
2552 palette.text: "red"
2553
2554 Column {
2555 Label {
2556 text: qsTr("This will use red color...")
2557 }
2558
2559 Switch {
2560 text: qsTr("... and so will this")
2561 }
2562 }
2563 }
2564 \endcode
2565
2566 \sa Item::palette, Window::palette, ColorGroup, Palette
2567*/
2568
2569bool QQuickPopup::filtersChildMouseEvents() const
2570{
2571 Q_D(const QQuickPopup);
2572 return d->popupItem->filtersChildMouseEvents();
2573}
2574
2575void QQuickPopup::setFiltersChildMouseEvents(bool filter)
2576{
2577 Q_D(QQuickPopup);
2578 d->popupItem->setFiltersChildMouseEvents(filter);
2579}
2580
2581/*!
2582 \qmlmethod QtQuick.Controls::Popup::forceActiveFocus(enumeration reason = Qt.OtherFocusReason)
2583
2584 Forces active focus on the popup with the given \a reason.
2585
2586 This method sets focus on the popup and ensures that all ancestor
2587 \l FocusScope objects in the object hierarchy are also given \l focus.
2588
2589 \sa activeFocus, Qt::FocusReason
2590*/
2591void QQuickPopup::forceActiveFocus(Qt::FocusReason reason)
2592{
2593 Q_D(QQuickPopup);
2594 d->popupItem->forceActiveFocus(reason);
2595}
2596
2597void QQuickPopup::classBegin()
2598{
2599 Q_D(QQuickPopup);
2600 d->complete = false;
2601 QQmlContext *context = qmlContext(this);
2602 if (context)
2603 QQmlEngine::setContextForObject(d->popupItem, context);
2604 d->popupItem->classBegin();
2605}
2606
2607void QQuickPopup::componentComplete()
2608{
2609 Q_D(QQuickPopup);
2610 qCDebug(lcPopup) << "componentComplete" << this;
2611 if (!parentItem())
2612 resetParentItem();
2613
2614 if (d->visible && d->window)
2615 d->transitionManager.transitionEnter();
2616
2617 d->complete = true;
2618 d->popupItem->componentComplete();
2619
2620 if (auto currentContentItem = d->popupItem->d_func()->contentItem.data()) {
2621 connect(sender: currentContentItem, signal: &QQuickItem::childrenChanged,
2622 context: this, slot: &QQuickPopup::contentChildrenChanged);
2623 }
2624}
2625
2626bool QQuickPopup::isComponentComplete() const
2627{
2628 Q_D(const QQuickPopup);
2629 return d->complete;
2630}
2631
2632bool QQuickPopup::childMouseEventFilter(QQuickItem *child, QEvent *event)
2633{
2634 Q_UNUSED(child);
2635 Q_UNUSED(event);
2636 return false;
2637}
2638
2639void QQuickPopup::focusInEvent(QFocusEvent *event)
2640{
2641 event->accept();
2642}
2643
2644void QQuickPopup::focusOutEvent(QFocusEvent *event)
2645{
2646 event->accept();
2647}
2648
2649void QQuickPopup::keyPressEvent(QKeyEvent *event)
2650{
2651 Q_D(QQuickPopup);
2652 if (!hasActiveFocus())
2653 return;
2654
2655#if QT_CONFIG(shortcut)
2656 if (d->closePolicy.testFlag(flag: QQuickPopup::CloseOnEscape)
2657 && (event->matches(key: QKeySequence::Cancel)
2658#if defined(Q_OS_ANDROID)
2659 || event->key() == Qt::Key_Back
2660#endif
2661 )) {
2662 event->accept();
2663 if (d->interactive)
2664 d->closeOrReject();
2665 return;
2666 }
2667#endif
2668
2669 if (hasActiveFocus() && (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)) {
2670 event->accept();
2671 QQuickItemPrivate::focusNextPrev(item: d->popupItem, forward: event->key() == Qt::Key_Tab);
2672 }
2673}
2674
2675void QQuickPopup::keyReleaseEvent(QKeyEvent *event)
2676{
2677 event->accept();
2678}
2679
2680void QQuickPopup::mousePressEvent(QMouseEvent *event)
2681{
2682 Q_D(QQuickPopup);
2683 event->setAccepted(d->handleMouseEvent(item: d->popupItem, event));
2684}
2685
2686void QQuickPopup::mouseMoveEvent(QMouseEvent *event)
2687{
2688 Q_D(QQuickPopup);
2689 event->setAccepted(d->handleMouseEvent(item: d->popupItem, event));
2690}
2691
2692void QQuickPopup::mouseReleaseEvent(QMouseEvent *event)
2693{
2694 Q_D(QQuickPopup);
2695 event->setAccepted(d->handleMouseEvent(item: d->popupItem, event));
2696}
2697
2698void QQuickPopup::mouseDoubleClickEvent(QMouseEvent *event)
2699{
2700 event->accept();
2701}
2702
2703void QQuickPopup::mouseUngrabEvent()
2704{
2705 Q_D(QQuickPopup);
2706 d->handleUngrab();
2707}
2708
2709bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event)
2710{
2711 Q_D(QQuickPopup);
2712 switch (event->type()) {
2713 case QEvent::KeyPress:
2714 case QEvent::KeyRelease:
2715 case QEvent::MouseMove:
2716 case QEvent::Wheel:
2717 if (d->modal)
2718 event->accept();
2719 return d->modal;
2720
2721#if QT_CONFIG(quicktemplates2_multitouch)
2722 case QEvent::TouchBegin:
2723 case QEvent::TouchUpdate:
2724 case QEvent::TouchEnd:
2725 return d->handleTouchEvent(item, event: static_cast<QTouchEvent *>(event));
2726#endif
2727 case QEvent::HoverEnter:
2728 case QEvent::HoverMove:
2729 case QEvent::HoverLeave:
2730 return d->handleHoverEvent(item, event: static_cast<QHoverEvent *>(event));
2731
2732 case QEvent::MouseButtonPress:
2733 case QEvent::MouseButtonRelease:
2734 return d->handleMouseEvent(item, event: static_cast<QMouseEvent *>(event));
2735
2736 default:
2737 return false;
2738 }
2739}
2740
2741#if QT_CONFIG(quicktemplates2_multitouch)
2742void QQuickPopup::touchEvent(QTouchEvent *event)
2743{
2744 Q_D(QQuickPopup);
2745 d->handleTouchEvent(item: d->popupItem, event);
2746}
2747
2748void QQuickPopup::touchUngrabEvent()
2749{
2750 Q_D(QQuickPopup);
2751 d->handleUngrab();
2752}
2753#endif
2754
2755#if QT_CONFIG(wheelevent)
2756void QQuickPopup::wheelEvent(QWheelEvent *event)
2757{
2758 event->accept();
2759}
2760#endif
2761
2762void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
2763{
2764 Q_UNUSED(newItem);
2765 Q_UNUSED(oldItem);
2766}
2767
2768void QQuickPopup::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
2769{
2770 qCDebug(lcPopup) << "contentSizeChange called on" << this << "with newSize" << newSize << "oldSize" << oldSize;
2771 if (!qFuzzyCompare(p1: newSize.width(), p2: oldSize.width()))
2772 emit contentWidthChanged();
2773 if (!qFuzzyCompare(p1: newSize.height(), p2: oldSize.height()))
2774 emit contentHeightChanged();
2775}
2776
2777void QQuickPopup::fontChange(const QFont &newFont, const QFont &oldFont)
2778{
2779 Q_UNUSED(newFont);
2780 Q_UNUSED(oldFont);
2781 emit fontChanged();
2782}
2783
2784void QQuickPopup::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
2785{
2786 Q_D(QQuickPopup);
2787 qCDebug(lcPopup) << "geometryChange called on" << this << "with newGeometry" << newGeometry << "oldGeometry" << oldGeometry;
2788 d->reposition();
2789 if (!qFuzzyCompare(p1: newGeometry.width(), p2: oldGeometry.width())) {
2790 emit widthChanged();
2791 emit availableWidthChanged();
2792 }
2793 if (!qFuzzyCompare(p1: newGeometry.height(), p2: oldGeometry.height())) {
2794 emit heightChanged();
2795 emit availableHeightChanged();
2796 }
2797}
2798
2799void QQuickPopup::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &)
2800{
2801 switch (change) {
2802 case QQuickItem::ItemActiveFocusHasChanged:
2803 emit activeFocusChanged();
2804 break;
2805 case QQuickItem::ItemOpacityHasChanged:
2806 emit opacityChanged();
2807 break;
2808 default:
2809 break;
2810 }
2811}
2812
2813void QQuickPopup::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
2814{
2815 Q_UNUSED(newLocale);
2816 Q_UNUSED(oldLocale);
2817 emit localeChanged();
2818}
2819
2820void QQuickPopup::marginsChange(const QMarginsF &newMargins, const QMarginsF &oldMargins)
2821{
2822 Q_D(QQuickPopup);
2823 Q_UNUSED(newMargins);
2824 Q_UNUSED(oldMargins);
2825 d->reposition();
2826}
2827
2828void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
2829{
2830 const bool tp = !qFuzzyCompare(p1: newPadding.top(), p2: oldPadding.top());
2831 const bool lp = !qFuzzyCompare(p1: newPadding.left(), p2: oldPadding.left());
2832 const bool rp = !qFuzzyCompare(p1: newPadding.right(), p2: oldPadding.right());
2833 const bool bp = !qFuzzyCompare(p1: newPadding.bottom(), p2: oldPadding.bottom());
2834
2835 if (tp)
2836 emit topPaddingChanged();
2837 if (lp)
2838 emit leftPaddingChanged();
2839 if (rp)
2840 emit rightPaddingChanged();
2841 if (bp)
2842 emit bottomPaddingChanged();
2843
2844 if (lp || rp) {
2845 emit horizontalPaddingChanged();
2846 emit availableWidthChanged();
2847 }
2848 if (tp || bp) {
2849 emit verticalPaddingChanged();
2850 emit availableHeightChanged();
2851 }
2852}
2853
2854void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing)
2855{
2856 Q_UNUSED(newSpacing);
2857 Q_UNUSED(oldSpacing);
2858 emit spacingChanged();
2859}
2860
2861void QQuickPopup::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
2862{
2863 if (!qFuzzyCompare(p1: newInset.top(), p2: oldInset.top()))
2864 emit topInsetChanged();
2865 if (!qFuzzyCompare(p1: newInset.left(), p2: oldInset.left()))
2866 emit leftInsetChanged();
2867 if (!qFuzzyCompare(p1: newInset.right(), p2: oldInset.right()))
2868 emit rightInsetChanged();
2869 if (!qFuzzyCompare(p1: newInset.bottom(), p2: oldInset.bottom()))
2870 emit bottomInsetChanged();
2871}
2872
2873QFont QQuickPopup::defaultFont() const
2874{
2875 return QQuickTheme::font(scope: QQuickTheme::System);
2876}
2877
2878#if QT_CONFIG(accessibility)
2879QAccessible::Role QQuickPopup::effectiveAccessibleRole() const
2880{
2881 auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj: this, create: false);
2882
2883 auto role = QAccessible::NoRole;
2884 if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(object: attached))
2885 role = accessibleAttached->role();
2886 if (role == QAccessible::NoRole)
2887 role = accessibleRole();
2888
2889 return role;
2890}
2891
2892QAccessible::Role QQuickPopup::accessibleRole() const
2893{
2894 return QAccessible::Dialog;
2895}
2896
2897void QQuickPopup::accessibilityActiveChanged(bool active)
2898{
2899 Q_UNUSED(active);
2900}
2901#endif
2902
2903QString QQuickPopup::accessibleName() const
2904{
2905 Q_D(const QQuickPopup);
2906 return d->popupItem->accessibleName();
2907}
2908
2909void QQuickPopup::maybeSetAccessibleName(const QString &name)
2910{
2911 Q_D(QQuickPopup);
2912 d->popupItem->maybeSetAccessibleName(name);
2913}
2914
2915QVariant QQuickPopup::accessibleProperty(const char *propertyName)
2916{
2917 Q_D(const QQuickPopup);
2918 return d->popupItem->accessibleProperty(propertyName);
2919}
2920
2921bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant &value)
2922{
2923 Q_D(QQuickPopup);
2924 return d->popupItem->setAccessibleProperty(propertyName, value);
2925}
2926
2927QT_END_NAMESPACE
2928
2929#include "moc_qquickpopup_p.cpp"
2930

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