Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickpopup.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
14#if QT_CONFIG(quicktemplates2_container)
15#include "qquickdialog_p.h"
16#endif
17
18#include <QtCore/qloggingcategory.h>
19#include <QtQml/qqmlinfo.h>
20#include <QtQuick/qquickitem.h>
21#include <QtQuick/private/qquickaccessibleattached_p.h>
22#include <QtQuick/private/qquickattachedpropertypropagator_p.h>
23#include <QtQuick/private/qquicktransition_p.h>
24#include <QtQuick/private/qquickitem_p.h>
25#include <qpa/qplatformintegration.h>
26#include <private/qguiapplication_p.h>
27
29
30Q_STATIC_LOGGING_CATEGORY(lcDimmer, "qt.quick.controls.popup.dimmer")
31Q_STATIC_LOGGING_CATEGORY(lcQuickPopup, "qt.quick.controls.popup")
32
33/*!
34 \qmltype Popup
35 \inherits QtObject
36//! \nativetype QQuickPopup
37 \inqmlmodule QtQuick.Controls
38 \since 5.7
39 \ingroup qtquickcontrols-popups
40 \ingroup qtquickcontrols-focusscopes
41 \brief Base type of popup-like user interface controls.
42
43 Popup is the base type of popup-like user interface controls. It can be
44 used with \l Window or \l ApplicationWindow.
45
46 \qml
47 import QtQuick.Window
48 import QtQuick.Controls
49
50 ApplicationWindow {
51 id: window
52 width: 400
53 height: 400
54 visible: true
55
56 Button {
57 text: "Open"
58 onClicked: popup.open()
59 }
60
61 Popup {
62 id: popup
63 x: 100
64 y: 100
65 width: 200
66 height: 300
67 modal: true
68 focus: true
69 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
70 }
71 }
72 \endqml
73
74 Popup does not provide a layout of its own, but requires you to position
75 its contents, for instance by creating a \l RowLayout or a \l ColumnLayout.
76
77 Items declared as children of a Popup are automatically parented to the
78 Popups's \l contentItem. Items created dynamically need to be explicitly
79 parented to the contentItem.
80
81 \section1 Popup Layout
82
83 The following diagram illustrates the layout of a popup within a window:
84
85 \image qtquickcontrols-popup.png
86 {Popup window overlaying content}
87
88 The \l implicitWidth and \l implicitHeight of a popup are typically based
89 on the implicit sizes of the background and the content item plus any insets
90 and paddings. These properties determine how large the popup will be when no
91 explicit \l width or \l height is specified.
92
93 The geometry of the \l contentItem is determined by the padding. The following
94 example reserves 10px padding between the boundaries of the popup and its content:
95
96 \code
97 Popup {
98 padding: 10
99
100 contentItem: Text {
101 text: "Content"
102 }
103 }
104 \endcode
105
106 The \l background item fills the entire width and height of the popup,
107 unless insets or an explicit size have been given for it.
108
109 Negative insets can be used to make the background larger than the popup.
110 The following example uses negative insets to place a shadow outside the
111 popup's boundaries:
112
113 \code
114 Popup {
115 topInset: -2
116 leftInset: -2
117 rightInset: -6
118 bottomInset: -6
119
120 background: BorderImage {
121 source: ":/images/shadowed-background.png"
122 }
123 }
124 \endcode
125
126 \section1 Popup type
127
128 Since Qt 6.8, some popups, such as \l Menu, offer three different implementations,
129 depending on the platform. You can choose which one you prefer by setting \l popupType.
130
131 Whether a popup will be able to use the preferred type depends on the platform.
132 \c Popup.Item is supported on all platforms, but \c Popup.Window and \c Popup.Native
133 are normally only supported on desktop platforms. Additionally, if a popup is a
134 \l Menu inside a \l {Native menu bars}{native menubar}, the menu will be native as
135 well. And if the menu is a sub-menu inside another menu, the parent (or root) menu
136 will decide the type.
137
138 \section2 Showing a popup as an item
139
140 By setting \l popupType to \c Popup.Item, the popup will \e not be shown as a separate
141 window, but as an item inside the same scene as the parent. This item is parented
142 to that scene's \l{Overlay::overlay}{overlay}, and styled to look like an actual window.
143
144 This option is especially useful on platforms that doesn't support multiple windows.
145 This was also the only option before Qt 6.8.
146
147 In order to ensure that a popup is displayed above other items in the
148 scene, it is recommended to use ApplicationWindow. ApplicationWindow also
149 provides background dimming effects.
150
151 \section2 Showing a popup as a separate window
152
153 By setting \l popupType to \c Popup.Window, the popup will be shown inside a top-level
154 \l {QQuickWindow}{window} configured with the \l Qt::Popup flag. Using a window to show a
155 popup has the advantage that the popup will float on top of the parent window, and
156 can be placed outside of its geometry. The popup will otherwise look the same as when
157 using \c Popup.Item, that is, it will use the same QML delegates and styling as
158 when using \c Popup.Item.
159
160 \note If the platform doesn't support \c Popup.Window, \c Popup.Item will be used as fallback.
161
162 \section2 Showing a native popup
163
164 By setting \l popupType to \c Popup.Native, the popup will be shown using a platform
165 native popup window. This window, and all its contents, will be rendered by the
166 platform, and not by QML. This means that the QML delegates assigned to the popup
167 will \e not be used for rendering. If you for example
168 use this option on a \l Menu, it will be implemented using platform-specific
169 menu APIs. This will normally make the popup look and feel more native than for example
170 \c Popup.Window, but at the same time, suffer from platform limitations and differences
171 related to appearance and behavior. Such limitations are documented in more detail
172 in the subclasses that are affected, such as for a
173 \l {Limitations when using native menus}{Menu}).
174
175 \note If the platform doesn't support \c Popup.Native, \c Popup.Window will be used as fallback.
176
177 \section1 Popup Sizing
178
179 If only a single item is used within a Popup, it will resize to fit the
180 implicit size of its contained item. This makes it particularly suitable
181 for use together with layouts.
182
183 \code
184 Popup {
185 ColumnLayout {
186 anchors.fill: parent
187 CheckBox { text: qsTr("E-mail") }
188 CheckBox { text: qsTr("Calendar") }
189 CheckBox { text: qsTr("Contacts") }
190 }
191 }
192 \endcode
193
194 Sometimes there might be two items within the popup:
195
196 \code
197 Popup {
198 SwipeView {
199 // ...
200 }
201 PageIndicator {
202 anchors.horizontalCenter: parent.horizontalCenter
203 anchors.bottom: parent.bottom
204 }
205 }
206 \endcode
207
208 In this case, Popup cannot calculate a sensible implicit size. Since we're
209 anchoring the \l PageIndicator over the \l SwipeView, we can simply set the
210 content size to the view's implicit size:
211
212 \code
213 Popup {
214 contentWidth: view.implicitWidth
215 contentHeight: view.implicitHeight
216
217 SwipeView {
218 id: view
219 // ...
220 }
221 PageIndicator {
222 anchors.horizontalCenter: parent.horizontalCenter
223 anchors.bottom: parent.bottom
224 }
225 }
226 \endcode
227
228 \note When using \l {Showing a popup as an item}{popup items}, the popup's
229 \l{contentItem}{content item} gets parented to the \l{Overlay::}{overlay},
230 and does not live within the popup's parent. Because of that, a \l{Item::}
231 {scale} applied to the tree in which the popup lives does not apply to the
232 visual popup. To make the popup of e.g. a \l{ComboBox} follow the scale of
233 the combobox, apply the same scale to the \l{Overlay::}{overlay} as well:
234
235 \code
236 Window {
237 property double scaleFactor: 2.0
238
239 Scale {
240 id: scale
241 xScale: scaleFactor
242 yScale: scaleFactor
243 }
244 Item {
245 id: scaledContent
246 transform: scale
247
248 ComboBox {
249 id: combobox
250 // ...
251 }
252 }
253
254 Overlay.overlay.transform: scale
255 }
256 \endcode
257
258 \section1 Popup Positioning
259
260 Similar to items in Qt Quick, Popup's \l x and \l y coordinates are
261 relative to its parent. This means that opening a popup that is a
262 child of a \l Button, for example, will cause the popup to be positioned
263 relative to the button.
264
265 \include qquickoverlay-popup-parent.qdocinc
266
267 Another way to center a popup in the window regardless of its parent item
268 is to use \l {anchors.centerIn}:
269
270 \snippet qtquickcontrols-popup.qml centerIn
271
272 To ensure that the popup is positioned within the bounds of the enclosing
273 window, the \l margins property can be set to a non-negative value.
274
275 \section1 Using the overlay
276
277 In cases where \l {Showing a popup as an item}{popup windows} are not being used,
278 Popup sets its contentItem's \l{qtquick-visualcanvas-visualparent.html}{visual parent}
279 to be the window's \l {Overlay::overlay}{overlay}, in order to ensure that
280 the popup appears in front of everything else in the scene. Its main task is to
281 intercept events to prevent delivery to items under a \l modal popup, and to close
282 the popup according to its \l closePolicy.
283
284 In some cases, it might be useful to put an item in front of a popup,
285 such as a \l [QML QtVirtualKeyboard] {InputPanel} {virtual keyboard}.
286 This can currently only be done by setting the item's parent to the overlay,
287 and ensuring that the item is stacked before any popup item, which a positive
288 \l z value ensures.
289
290 It's generally not recommended to use the overlay in this way, since the overlay wasn't
291 designed for this purpose, and the behavior won't be consistent when changing the \l popupType.
292
293 \omit
294 This shouldn't be a snippet, since we don't want VKB to be a dependency to controls.
295 \endomit
296 \qml
297 Popup {
298 id: popup
299 visible: true
300 anchors.centerIn: parent
301 margins: 10
302 closePolicy: Popup.CloseOnEscape
303 ColumnLayout {
304 TextField {
305 placeholderText: qsTr("Username")
306 }
307 TextField {
308 placeholderText: qsTr("Password")
309 echoMode: TextInput.Password
310 }
311 }
312 }
313 InputPanel {
314 parent: Overlay.overlay
315 width: parent.width
316 y: popup.y + popup.topMargin + (window.activeFocusItem?.y ?? 0) + (window.activeFocusItem?.height ?? 0)
317 z: 1
318 }
319 \endqml
320
321 \section1 Popup Transitions
322
323 After the exit transition is finished, these properties will be reset to
324 their values before the enter transition is started.
325
326 \list
327 \li \l opacity
328 \li \l scale
329 \endlist
330
331 This allows the built-in styles to animate on these properties without losing any explicitly
332 defined value.
333
334 \section1 Back/Escape Event Handling
335
336 By default, a Popup will close if:
337 \list
338 \li It has \l activeFocus,
339 \li Its \l closePolicy is \c {Popup.CloseOnEscape}, and
340 \li The user presses the key sequence for QKeySequence::Cancel (typically
341 the Escape key)
342 \endlist
343
344 To prevent this from happening, either:
345
346 \list
347 \li Don't give the popup \l focus.
348 \li Set the popup's \l closePolicy to a value that does not include
349 \c {Popup.CloseOnEscape}.
350 \li Handle \l {Keys}' \l {Keys::}{escapePressed} signal in a child item of
351 the popup so that it gets the event before the Popup.
352 \endlist
353
354 \sa {Popup Controls}, {Customizing Popup}, ApplicationWindow
355
356 \section1 Property Propagation
357
358 Popup inherits fonts, palettes and attached properties through its parent
359 window, not its
360 \l {Concepts - Visual Parent in Qt Quick#Visual Parent}{object or visual parent}:
361
362 \snippet qtquickcontrols-popup-property-propagation.qml file
363
364 \image qtquickcontrols-basic-popup-property-propagation.png
365 {Diagram showing popup property inheritance}
366
367 In addition, popups do not propagate their properties to child popups. This
368 behavior is modelled on Qt Widgets, where a \c Qt::Popup widget is a
369 top-level window. Top-level windows do not propagate their properties to
370 child windows.
371
372 Certain derived types like ComboBox are typically implemented in such a way
373 that the popup is considered an integral part of the control, and as such,
374 may inherit things like attached properties. For example, in the
375 \l {Material Style}{Material style} ComboBox, the theme and other attached
376 properties are explicitly inherited by the Popup from the ComboBox itself:
377
378 \code
379 popup: T.Popup {
380 // ...
381
382 Material.theme: control.Material.theme
383 Material.accent: control.Material.accent
384 Material.primary: control.Material.primary
385 }
386 \endcode
387
388 So, to ensure that a child popup has the same property values as its parent
389 popup, explicitly set those properties:
390
391 \code
392 Popup {
393 id: parentPopup
394 // ...
395
396 Popup {
397 palette: parentPopup.palette
398 }
399 }
400 \endcode
401
402 \section1 Polish Behavior of Closed Popups
403
404 When a popup is closed, it has no associated window, and neither do its
405 child items. This means that any child items will not be
406 \l {QQuickItem::polish}{polished} until the popup is shown. For this
407 reason, you cannot, for example, rely on a \l ListView within a closed
408 \c Popup to update its \c count property:
409
410 \code
411 import QtQuick
412 import QtQuick.Controls
413
414 ApplicationWindow {
415 width: 640
416 height: 480
417 visible: true
418
419 SomeModel {
420 id: someModel
421 }
422
423 Button {
424 text: view.count
425 onClicked: popup.open()
426 }
427
428 Popup {
429 id: popup
430 width: 400
431 height: 400
432 contentItem: ListView {
433 id: view
434 model: someModel
435 delegate: Label {
436 text: display
437
438 required property string display
439 }
440 }
441 }
442 }
443 \endcode
444
445 In the example above, the Button's text will not update when rows are added
446 to or removed from \c someModel after \l {Component::completed}{component
447 completion} while the popup is closed.
448
449 Instead, a \c count property can be added to \c SomeModel that is updated
450 whenever the \l {QAbstractItemModel::}{rowsInserted}, \l
451 {QAbstractItemModel::}{rowsRemoved}, and \l
452 {QAbstractItemModel::}{modelReset} signals are emitted. The \c Button can
453 then bind this property to its \c text.
454*/
455
456/*!
457 \qmlsignal void QtQuick.Controls::Popup::opened()
458
459 This signal is emitted when the popup is opened.
460
461 \sa aboutToShow()
462*/
463
464/*!
465 \qmlsignal void QtQuick.Controls::Popup::closed()
466
467 This signal is emitted when the popup is closed.
468
469 \sa aboutToHide()
470*/
471
472/*!
473 \qmlsignal void QtQuick.Controls::Popup::aboutToShow()
474
475 This signal is emitted when the popup is about to show.
476
477 \sa opened()
478*/
479
480/*!
481 \qmlsignal void QtQuick.Controls::Popup::aboutToHide()
482
483 This signal is emitted when the popup is about to hide.
484
485 \sa closed()
486*/
487
488QQuickItem *QQuickPopup::findParentItem() const
489{
490 QObject *obj = parent();
491 while (obj) {
492 QQuickItem *item = qobject_cast<QQuickItem *>(obj);
493 if (item)
494 return item;
495 obj = obj->parent();
496 }
497 return nullptr;
498}
499
500const QQuickPopup::ClosePolicy QQuickPopupPrivate::DefaultClosePolicy = QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside;
501
502QQuickPopupPrivate::QQuickPopupPrivate()
503 : transitionManager(this)
504{
505}
506
507void QQuickPopupPrivate::init()
508{
509 Q_Q(QQuickPopup);
510 popupItem = new QQuickPopupItem(q);
511 popupItem->setVisible(false);
512 QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
513 QObject::connect(popupItem, &QQuickControl::backgroundChanged, q, &QQuickPopup::backgroundChanged);
514 QObject::connect(popupItem, &QQuickControl::contentItemChanged, q, &QQuickPopup::contentItemChanged);
515 QObject::connect(popupItem, &QQuickControl::implicitContentWidthChanged, q, &QQuickPopup::implicitContentWidthChanged);
516 QObject::connect(popupItem, &QQuickControl::implicitContentHeightChanged, q, &QQuickPopup::implicitContentHeightChanged);
517 QObject::connect(popupItem, &QQuickControl::implicitBackgroundWidthChanged, q, &QQuickPopup::implicitBackgroundWidthChanged);
518 QObject::connect(popupItem, &QQuickControl::implicitBackgroundHeightChanged, q, &QQuickPopup::implicitBackgroundHeightChanged);
519}
520
521void QQuickPopupPrivate::closeOrReject()
522{
523 Q_Q(QQuickPopup);
524#if QT_CONFIG(quicktemplates2_container)
525 if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(q))
526 dialog->reject();
527 else
528#endif
529 q->close();
530 touchId = -1;
531}
532
533bool QQuickPopupPrivate::tryClose(const QPointF &pos, QQuickPopup::ClosePolicy flags)
534{
535 if (!interactive)
536 return false;
537
538 static const QQuickPopup::ClosePolicy outsideFlags = QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnReleaseOutside;
539 static const QQuickPopup::ClosePolicy outsideParentFlags = QQuickPopup::CloseOnPressOutsideParent | QQuickPopup::CloseOnReleaseOutsideParent;
540
541 const bool onOutside = closePolicy & (flags & outsideFlags);
542 const bool onOutsideParent = closePolicy & (flags & outsideParentFlags);
543
544 if ((onOutside && outsidePressed) || (onOutsideParent && outsideParentPressed)) {
545 if (!contains(pos) && (!dimmer || dimmer->contains(dimmer->mapFromScene(pos)))) {
546 if (!onOutsideParent || !parentItem || !parentItem->contains(parentItem->mapFromScene(pos))) {
547 closeOrReject();
548 return true;
549 }
550 }
551 }
552 return false;
553}
554
555bool QQuickPopupPrivate::contains(const QPointF &scenePos) const
556{
557 return popupItem->contains(popupItem->mapFromScene(scenePos));
558}
559
560static QQuickItem *findRootOfOverlaySubtree(QQuickItem *source, const QQuickOverlay *overlay)
561{
562 QQuickItem *sourceAncestor = source;
563 while (sourceAncestor) {
564 QQuickItem *parentItem = sourceAncestor->parentItem();
565 if (parentItem == overlay)
566 return sourceAncestor;
567 sourceAncestor = parentItem;
568 }
569 // Not an ancestor of the overlay.
570 return nullptr;
571}
572
573bool QQuickPopupPrivate::belongsToOverlayChildAbove(QQuickItem *item) const
574{
575 auto *overlay = QQuickOverlay::overlay(window, parentItem);
576 Q_ASSERT(overlay);
577 const auto paintOrderChildItems = QQuickOverlayPrivate::get(overlay)->paintOrderChildItems();
578 return paintOrderChildItems.indexOf(findRootOfOverlaySubtree(item, overlay))
579 > paintOrderChildItems.indexOf(popupItem);
580}
581
582#if QT_CONFIG(quicktemplates2_multitouch)
583bool QQuickPopupPrivate::acceptTouch(const QTouchEvent::TouchPoint &point)
584{
585 if (point.id() == touchId)
586 return true;
587
588 if (touchId == -1 && point.state() != QEventPoint::Released) {
589 touchId = point.id();
590 return true;
591 }
592
593 return false;
594}
595#endif
596
597bool QQuickPopupPrivate::blockInput(QQuickItem *item, const QPointF &point) const
598{
599 // don't propagate events within the popup beyond the overlay
600 if (popupItem->contains(popupItem->mapFromScene(point))
601 && item == QQuickOverlay::overlay(window, parentItem)) {
602 return true;
603 }
604
605 // don't block presses and releases
606 // a) outside a non-modal popup,
607 // b) to popup children/content, or
608 // c) outside a modal popups's background dimming
609
610 return modal && ((popupItem != item) && !popupItem->isAncestorOf(item)) && (!dimmer || dimmer->contains(dimmer->mapFromScene(point)));
611}
612
613bool QQuickPopupPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp)
614{
615 Q_UNUSED(timestamp);
616 pressPoint = point;
617 outsidePressed = !contains(point);
618
619 if (outsidePressed && parentItem) {
620 // Note that the parentItem (e.g a menuBarItem, in case of a MenuBar) will
621 // live inside another window when using popup windows. We therefore need to
622 // map to and from global.
623 const QPointF globalPoint = item->mapToGlobal(item->mapFromScene(point));
624 const QPointF localPoint = parentItem->mapFromGlobal(globalPoint);
625 outsideParentPressed = !parentItem->contains(localPoint);
626 }
627
628 tryClose(point, QQuickPopup::CloseOnPressOutside | QQuickPopup::CloseOnPressOutsideParent);
629 return blockInput(item, point);
630}
631
632bool QQuickPopupPrivate::handleMove(QQuickItem *item, const QPointF &point, ulong timestamp)
633{
634 Q_UNUSED(timestamp);
635 return blockInput(item, point);
636}
637
638bool QQuickPopupPrivate::handleRelease(QQuickItem *item, const QEventPoint &point)
639{
640 const QPointF scenePosition = point.scenePosition();
641 if (item != popupItem && !contains(pressPoint))
642 tryClose(scenePosition, QQuickPopup::CloseOnReleaseOutside | QQuickPopup::CloseOnReleaseOutsideParent);
643 pressPoint = QPointF();
644 outsidePressed = false;
645 outsideParentPressed = false;
646 touchId = -1;
647 return blockInput(item, scenePosition);
648}
649
650void QQuickPopupPrivate::handleUngrab()
651{
652 Q_Q(QQuickPopup);
653 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem);
654 if (overlay) {
655 QQuickOverlayPrivate *p = QQuickOverlayPrivate::get(overlay);
656 if (p->mouseGrabberPopup == q)
657 p->mouseGrabberPopup = nullptr;
658 }
659 pressPoint = QPointF();
660 touchId = -1;
661}
662
663bool QQuickPopupPrivate::handleMouseEvent(QQuickItem *item, QMouseEvent *event)
664{
665 switch (event->type()) {
666 case QEvent::MouseButtonPress:
667 return handlePress(item, event->scenePosition(), event->timestamp());
668 case QEvent::MouseMove:
669 return handleMove(item, event->scenePosition(), event->timestamp());
670 case QEvent::MouseButtonRelease:
671 return handleRelease(item, event->point(0));
672 default:
673 Q_UNREACHABLE_RETURN(false);
674 }
675}
676
677bool QQuickPopupPrivate::handleHoverEvent(QQuickItem *item, QHoverEvent *event)
678{
679 switch (event->type()) {
680 case QEvent::HoverEnter:
681 case QEvent::HoverMove:
682 case QEvent::HoverLeave:
683 return blockInput(item, event->scenePosition());
684 default:
685 Q_UNREACHABLE_RETURN(false);
686 }
687}
688
689QMarginsF QQuickPopupPrivate::windowInsets() const
690{
691 // Don't honor negative insets on wayland. If we do,
692 // it would impact the popup window's geometry.
693 // We assume that the compositor will draw window decorations.
694#if QT_CONFIG(wayland)
695 if (QGuiApplication::platformName().startsWith(QLatin1String("wayland")))
696 return {0, 0, 0, 0};
697#endif
698 Q_Q(const QQuickPopup);
699 // If the popup has negative insets, it means that its background is pushed
700 // outside the bounds of the popup. This is fine when the popup is an item in the
701 // scene (Popup.Item), but will result in the background being clipped when using
702 // a window (Popup.Window). To avoid this, the window will been made bigger than
703 // the popup (according to the insets), to also include the part that ends up
704 // outside (which is usually a drop-shadow).
705 // Note that this also means that we need to take those extra margins into account
706 // whenever we resize or position the menu, so that the top-left of the popup ends
707 // up at the requested position, and not the top-left of the window.
708
709 const auto *popupItemPrivate = QQuickControlPrivate::get(popupItem);
710 if (!usePopupWindow() || (popupItemPrivate->background.isExecuting() && popupItemPrivate->background->clip())) {
711 // Items in the scene are allowed to draw out-of-bounds, so we don't
712 // need to do anything if we're not using popup windows. The same is
713 // also true for popup windows if the background is clipped.
714 return {0, 0, 0, 0};
715 }
716
717 return {
718 q->leftInset() < 0 ? -q->leftInset() : 0,
719 q->topInset() < 0 ? -q->topInset() : 0,
720 q->rightInset() < 0 ? -q->rightInset() : 0,
721 q->bottomInset() < 0 ? -q->bottomInset() : 0
722 };
723}
724
725QPointF QQuickPopupPrivate::windowInsetsTopLeft() const
726{
727 const QMarginsF windowMargins = windowInsets();
728 return {windowMargins.left(), windowMargins.top()};
729}
730
731void QQuickPopupPrivate::setEffectivePosFromWindowPos(const QPointF &windowPos)
732{
733 // Popup operates internally with three different positions; requested
734 // position, effective position, and window position. The first is the
735 // position requested by the application, and the second is where the popup
736 // is actually placed. The reason for placing it on a different position than
737 // the one requested, is to keep it inside the window (in case of Popup.Item),
738 // or the screen (in case of Popup.Window).
739 // Additionally, since a popup can set Qt::FramelessWindowHint and draw the
740 // window frame from the background delegate, the effective position in that
741 // case is adjusted to be the top-left corner of the background delegate, rather
742 // than the top-left corner of the window. This allowes the background delegate
743 // to render a drop-shadow between the edge of the window and the background frame.
744 // Finally, the window position is the actual position of the window, including
745 // any drop-shadow effects. This posision can be calculated by taking
746 // the effective position and subtract the dropShadowOffset().
747 Q_Q(QQuickPopup);
748 const QPointF oldEffectivePos = effectivePos;
749 effectivePos = windowPos + windowInsetsTopLeft();
750 if (!qFuzzyCompare(oldEffectivePos.x(), effectivePos.x()))
751 emit q->xChanged();
752 if (!qFuzzyCompare(oldEffectivePos.y(), effectivePos.y()))
753 emit q->yChanged();
754}
755
756#if QT_CONFIG(quicktemplates2_multitouch)
757bool QQuickPopupPrivate::handleTouchEvent(QQuickItem *item, QTouchEvent *event)
758{
759 switch (event->type()) {
760 case QEvent::TouchBegin:
761 case QEvent::TouchUpdate:
762 case QEvent::TouchEnd:
763 for (const QTouchEvent::TouchPoint &point : event->points()) {
764 if (event->type() != QEvent::TouchEnd && !acceptTouch(point))
765 return blockInput(item, point.position());
766
767 switch (point.state()) {
768 case QEventPoint::Pressed:
769 return handlePress(item, point.scenePosition(), event->timestamp());
770 case QEventPoint::Updated:
771 return handleMove(item, point.scenePosition(), event->timestamp());
772 case QEventPoint::Released:
773 return handleRelease(item, point);
774 default:
775 break;
776 }
777 }
778 break;
779
780 case QEvent::TouchCancel:
781 handleUngrab();
782 break;
783
784 default:
785 break;
786 }
787
788 return false;
789}
790#endif
791
792bool QQuickPopupPrivate::prepareEnterTransition()
793{
794 Q_Q(QQuickPopup);
795 if (!window) {
796 qmlWarning(q) << "cannot find any window to open popup in.";
797 return false;
798 }
799
800 if (transitionState == EnterTransition && transitionManager.isRunning())
801 return false;
802
803 if (transitionState != EnterTransition) {
804 const QPointer<QQuickItem> lastActiveFocusItem = window->activeFocusItem();
805 visible = true;
806 adjustPopupItemParentAndWindow();
807 if (dim)
808 createOverlay();
809 showDimmer();
810 emit q->aboutToShow();
811 transitionState = EnterTransition;
812 getPositioner()->setParentItem(parentItem);
813 emit q->visibleChanged();
814
815 if (lastActiveFocusItem) {
816 this->lastActiveFocusItem = lastActiveFocusItem;
817 if (auto *overlay = QQuickOverlay::overlay(window, parentItem)) {
818 auto *overlayPrivate = QQuickOverlayPrivate::get(overlay);
819 if (overlayPrivate->lastActiveFocusItem.isNull() && !popupItem->isAncestorOf(lastActiveFocusItem)) {
820 overlayPrivate->lastActiveFocusItem = lastActiveFocusItem;
821 overlayPrivate->lastActiveFocusItemPopup = q;
822 }
823 }
824 }
825
826 if (focus)
827 popupItem->setFocus(true, Qt::PopupFocusReason);
828 }
829 return true;
830}
831
832bool QQuickPopupPrivate::prepareExitTransition()
833{
834 Q_Q(QQuickPopup);
835 if (transitionState == ExitTransition && transitionManager.isRunning())
836 return false;
837
838 Q_ASSERT(popupItem);
839
840 // We need to cache the original scale and opacity values so we can reset it after
841 // the exit transition is done so they have the original values again
842 prevScale = popupItem->scale();
843 prevOpacity = popupItem->opacity();
844
845 if (transitionState != ExitTransition) {
846 // The setFocus(false) call below removes any active focus before we're
847 // able to check it in finalizeExitTransition.
848 if (!hadActiveFocusBeforeExitTransition) {
849 const auto *da = QQuickItemPrivate::get(popupItem)->deliveryAgentPrivate();
850 hadActiveFocusBeforeExitTransition = popupItem->hasActiveFocus() || (da && da->focusTargetItem() == popupItem);
851 }
852 if (focus)
853 popupItem->setFocus(false, Qt::PopupFocusReason);
854 transitionState = ExitTransition;
855 hideDimmer();
856 emit q->aboutToHide();
857 emit q->openedChanged();
858 }
859 return true;
860}
861
862void QQuickPopupPrivate::finalizeEnterTransition()
863{
864 Q_Q(QQuickPopup);
865 transitionState = NoTransition;
866 reposition();
867 emit q->openedChanged();
868 opened();
869}
870
871void QQuickPopupPrivate::finalizeExitTransition()
872{
873 Q_Q(QQuickPopup);
874 getPositioner()->setParentItem(nullptr);
875 if (popupItem) {
876 popupItem->setParentItem(nullptr);
877 popupItem->setVisible(false);
878 }
879 destroyDimmer();
880
881 if (auto *overlay = QQuickOverlay::overlay(window, parentItem)) {
882 auto *overlayPrivate = QQuickOverlayPrivate::get(overlay);
883 const auto stackingOrderPopups = overlayPrivate->stackingOrderPopups();
884 // Reset the last active focus item in the overlay when this popup exit
885 bool resetLastActiveFocusItem = (overlayPrivate->lastActiveFocusItemPopup == q);
886 if (resetLastActiveFocusItem) {
887 /**
888 * Check for popups in the stack that:
889 * 1. Are not in an exit transition.
890 * 2. Contain a saved last active focus item (from the window).
891 * If found, update the overlay's focus reference to this item and
892 * prevent a reset. This ensures focus returns to the correct
893 * pre-popup element once the window clears.
894 */
895 for (auto popup : stackingOrderPopups) {
896 if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition) {
897 if (auto savedFocusItem = QQuickPopupPrivate::get(popup)->lastActiveFocusItem) {
898 if (!qobject_cast<QQuickRootItem *>(savedFocusItem) && savedFocusItem != popupItem
899 && !popupItem->isAncestorOf(savedFocusItem)) {
900 overlayPrivate->lastActiveFocusItem = savedFocusItem;
901 }
902 overlayPrivate->lastActiveFocusItemPopup = popup;
903 resetLastActiveFocusItem = false;
904 break;
905 }
906 }
907 }
908 }
909
910 // restore focus to the next popup in chain, or to the window content if there are no other popups open
911 if (hadActiveFocusBeforeExitTransition) {
912 QQuickPopup *nextFocusPopup = nullptr;
913 for (auto popup : stackingOrderPopups) {
914 // only pick a popup that is focused but has not already been activated
915 if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition
916 && popup->hasFocus() && !popup->hasActiveFocus()) {
917 nextFocusPopup = popup;
918 break;
919 }
920 }
921 if (nextFocusPopup) {
922 nextFocusPopup->forceActiveFocus(Qt::PopupFocusReason);
923 } else {
924 auto *appWindow = qobject_cast<QQuickApplicationWindow*>(window);
925 auto *contentItem = appWindow ? appWindow->contentItem() : window->contentItem();
926 if (!contentItem->scopedFocusItem()
927 && !overlayPrivate->lastActiveFocusItem.isNull()) {
928 // The last active focus item may have lost focus not just for
929 // itself but for its entire focus chain, so force active focus.
930 overlayPrivate->lastActiveFocusItem->forceActiveFocus(Qt::OtherFocusReason);
931 } else {
932 contentItem->setFocus(true, Qt::PopupFocusReason);
933 }
934 }
935 }
936
937 // Clear the overlay's saved focus if this popup was the one that set it
938 if (resetLastActiveFocusItem || stackingOrderPopups.isEmpty()) {
939 overlayPrivate->lastActiveFocusItem = nullptr;
940 overlayPrivate->lastActiveFocusItemPopup = nullptr;
941 }
942 }
943
944 visible = false;
945 adjustPopupItemParentAndWindow();
946 transitionState = NoTransition;
947 hadActiveFocusBeforeExitTransition = false;
948 lastActiveFocusItem = nullptr;
949 emit q->visibleChanged();
950 emit q->closed();
951#if QT_CONFIG(accessibility)
952 const auto type = q->effectiveAccessibleRole() == QAccessible::PopupMenu
953 ? QAccessible::PopupMenuEnd
954 : QAccessible::DialogEnd;
955 QAccessibleEvent ev(q->popupItem(), type);
956 QAccessible::updateAccessibility(&ev);
957#endif
958 if (popupItem) {
959 popupItem->setScale(prevScale);
960 popupItem->setOpacity(prevOpacity);
961 }
962}
963
964void QQuickPopupPrivate::opened()
965{
966 Q_Q(QQuickPopup);
967 emit q->opened();
968#if QT_CONFIG(accessibility)
969 const auto type = q->effectiveAccessibleRole() == QAccessible::PopupMenu
970 ? QAccessible::PopupMenuStart
971 : QAccessible::DialogStart;
972 QAccessibleEvent ev(q->popupItem(), type);
973 QAccessible::updateAccessibility(&ev);
974#endif
975}
976
977Qt::WindowFlags QQuickPopupPrivate::popupWindowFlags() const
978{
979 return windowFlags;
980}
981
982void QQuickPopupPrivate::setPopupWindowFlags(Qt::WindowFlags flags)
983{
984 windowFlags = flags;
985}
986
987QMarginsF QQuickPopupPrivate::getMargins() const
988{
989 Q_Q(const QQuickPopup);
990 return QMarginsF(q->leftMargin(), q->topMargin(), q->rightMargin(), q->bottomMargin());
991}
992
993void QQuickPopupPrivate::setTopMargin(qreal value, bool reset)
994{
995 Q_Q(QQuickPopup);
996 qreal oldMargin = q->topMargin();
997 topMargin = value;
998 hasTopMargin = !reset;
999 if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
1000 emit q->topMarginChanged();
1001 q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
1002 QMarginsF(leftMargin, oldMargin, rightMargin, bottomMargin));
1003 }
1004}
1005
1006void QQuickPopupPrivate::setLeftMargin(qreal value, bool reset)
1007{
1008 Q_Q(QQuickPopup);
1009 qreal oldMargin = q->leftMargin();
1010 leftMargin = value;
1011 hasLeftMargin = !reset;
1012 if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
1013 emit q->leftMarginChanged();
1014 q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
1015 QMarginsF(oldMargin, topMargin, rightMargin, bottomMargin));
1016 }
1017}
1018
1019void QQuickPopupPrivate::setRightMargin(qreal value, bool reset)
1020{
1021 Q_Q(QQuickPopup);
1022 qreal oldMargin = q->rightMargin();
1023 rightMargin = value;
1024 hasRightMargin = !reset;
1025 if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
1026 emit q->rightMarginChanged();
1027 q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
1028 QMarginsF(leftMargin, topMargin, oldMargin, bottomMargin));
1029 }
1030}
1031
1032void QQuickPopupPrivate::setBottomMargin(qreal value, bool reset)
1033{
1034 Q_Q(QQuickPopup);
1035 qreal oldMargin = q->bottomMargin();
1036 bottomMargin = value;
1037 hasBottomMargin = !reset;
1038 if ((!reset && !qFuzzyCompare(oldMargin, value)) || (reset && !qFuzzyCompare(oldMargin, margins))) {
1039 emit q->bottomMarginChanged();
1040 q->marginsChange(QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin),
1041 QMarginsF(leftMargin, topMargin, rightMargin, oldMargin));
1042 }
1043}
1044
1045/*!
1046 \since QtQuick.Controls 2.5 (Qt 5.12)
1047 \qmlproperty Item QtQuick.Controls::Popup::anchors.centerIn
1048
1049 Anchors provide a way to position an item by specifying its
1050 relationship with other items.
1051
1052 A common use case is to center a popup within its parent. One way to do
1053 this is with the \l[QtQuick]{Item::}{x} and \l[QtQuick]{Item::}{y} properties. Anchors offer
1054 a more convenient approach:
1055
1056 \qml
1057 Pane {
1058 // ...
1059
1060 Popup {
1061 anchors.centerIn: parent
1062 }
1063 }
1064 \endqml
1065
1066 It is also possible to center the popup in the window by using \l Overlay:
1067
1068 \snippet qtquickcontrols-popup.qml centerIn
1069
1070 This makes it easy to center a popup in the window from any component.
1071
1072 \note Popups can only be centered within their immediate parent or
1073 the window overlay; trying to center in other items will produce a warning.
1074
1075 \sa {Popup Positioning}, {Item::}{anchors}, {Using Qt Quick Controls types
1076 in property declarations}
1077*/
1078QQuickPopupAnchors *QQuickPopupPrivate::getAnchors()
1079{
1080 Q_Q(QQuickPopup);
1081 if (!anchors)
1082 anchors = new QQuickPopupAnchors(q);
1083 return anchors;
1084}
1085
1086QQuickPopupPositioner *QQuickPopupPrivate::getPositioner()
1087{
1088 Q_Q(QQuickPopup);
1089 if (!positioner)
1090 positioner = new QQuickPopupPositioner(q);
1091 return positioner;
1092}
1093
1094
1096{
1097 Q_OBJECT
1098public:
1100 : m_func(func)
1101 {
1102 w->installEventFilter(this);
1103 }
1104protected:
1107 if (event->type() == QEvent::Expose)
1108 m_func();
1109 return false;
1110 }
1111private:
1112 std::function<void()> m_func;
1113};
1114
1116{
1118 observer->disconnect();
1119 observer->deleteLater();
1120 }
1121};
1123
1124/*!
1125 \internal
1126 A popup's position is meant to be relative to its nearest parent item.
1127 If this item exists in another window, the position needs to be mapped between the windows.
1128 We use mapToGlobal(QPointF) to figure out where to position the popup window.
1129 However, if mapToGlobal(QPointF) is called before the parent window is exposed,
1130 it will on Windows and X11 assume that the parent windows position is (0,0).
1131 This means that the popup window's position will usually be wrong, when it's
1132 opened at the same time as the parent window.
1133 To work around this issue, we wait for the parent window to be exposed, before opening the popup window.
1134 */
1135void openPopup(QQuickPopupPrivate *d)
1136{
1137#if defined(Q_OS_MACOS)
1138 d->transitionManager.transitionEnter();
1139#else
1140 const auto callPrepareEnterTransition = [d]() {
1141 d->transitionManager.transitionEnter();
1142 std::ignore = s_windowExposedObserver.release();
1143 };
1144 if (d->usePopupWindow() && d->window->isVisible() && !d->window->isExposed())
1145 s_windowExposedObserver.reset(new QWindowExposedObserver(d->window, callPrepareEnterTransition));
1146 else
1147 callPrepareEnterTransition();
1148#endif
1149}
1150
1151void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
1152{
1153 Q_Q(QQuickPopup);
1154 if (window == newWindow)
1155 return;
1156
1157 if (window) {
1158 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem);
1159 if (overlay)
1160 QQuickOverlayPrivate::get(overlay)->removePopup(q);
1161
1162 // Interacting with Popups in async Loaders (QTBUG-139306) would cause crashes
1163 // because the popup's window was null. We can avoid this by unparenting the popupItem,
1164 // which removes it from stackingOrderPopups and hence excludes it from receiving events.
1165 if (!newWindow && popupItem)
1166 popupItem->setParentItem(nullptr);
1167 }
1168
1169 window = newWindow;
1170
1171 if (newWindow) {
1172 QQuickOverlay *overlay = QQuickOverlay::overlay(newWindow, parentItem);
1173 if (overlay)
1174 QQuickOverlayPrivate::get(overlay)->addPopup(q);
1175
1176 QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem);
1177 p->resolveFont();
1178 if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(newWindow))
1179 p->updateLocale(appWindow->locale(), false); // explicit=false
1180 }
1181
1182 emit q->windowChanged(newWindow);
1183
1184 if (complete && visible && window)
1185 openPopup(this);
1186}
1187
1188void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
1189{
1190 Q_Q(QQuickPopup);
1191 if (item == parentItem)
1192 q->setParentItem(nullptr);
1193}
1194
1195void QQuickPopupPrivate::reposition()
1196{
1197 getPositioner()->reposition();
1198}
1199
1200QPalette QQuickPopupPrivate::defaultPalette() const
1201{
1202 return QQuickTheme::palette(QQuickTheme::System);
1203}
1204
1205QQuickPopup::PopupType QQuickPopupPrivate::resolvedPopupType() const
1206{
1207 // Whether or not the resolved popup type ends up the same as the preferred popup type
1208 // depends on platform capabilities, the popup subclass, and sometimes also the location
1209 // of the popup in the parent hierarchy (menus). This function can therefore be overridden
1210 // to return the actual popup type that should be used, based on the knowledge the popup
1211 // has just before it's about to be shown.
1212
1213 // PopupType::Native is not directly supported by QQuickPopup (only by subclasses).
1214 // So for that case, we fall back to use PopupType::Window, if supported.
1215 if (popupType == QQuickPopup::PopupType::Window
1216 || popupType == QQuickPopup::PopupType::Native) {
1217 if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::Capability::MultipleWindows))
1218 return QQuickPopup::PopupType::Window;
1219 }
1220
1221 return QQuickPopup::PopupType::Item;
1222}
1223
1224bool QQuickPopupPrivate::usePopupWindow() const
1225{
1226 return resolvedPopupType() == QQuickPopup::PopupType::Window;
1227}
1228
1229void QQuickPopupPrivate::adjustPopupItemParentAndWindow()
1230{
1231 Q_Q(QQuickPopup);
1232 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem);
1233
1234 if (visible && popupWindowDirty) {
1235 popupItem->setParentItem(overlay);
1236 if (popupWindow) {
1237 popupWindow->deleteLater();
1238 popupWindow = nullptr;
1239 }
1240 popupWindowDirty = false;
1241 }
1242
1243 if (usePopupWindow()) {
1244 if (visible) {
1245 if (!popupWindow) {
1246 QWindow *ancestor = window;
1247 while (ancestor->parent())
1248 ancestor = ancestor->parent();
1249 popupWindow = new QQuickPopupWindow(q, ancestor);
1250 // Changing the visual parent can cause the popup item's implicit width/height to change.
1251 // We store the initial size here first, to ensure that we're resizing the window to the correct size.
1252 const qreal initialWidth = popupItem->width() + windowInsets().left() + windowInsets().right();
1253 const qreal initialHeight = popupItem->height() + windowInsets().top() + windowInsets().bottom();
1254 popupItem->setParentItem(popupWindow->contentItem());
1255 popupWindow->resize(qCeil(initialWidth), qCeil(initialHeight));
1256 if (popupWndModality != Qt::NonModal)
1257 popupWindow->setModality(popupWndModality);
1258 else
1259 popupWindow->setModality(modal ? Qt::ApplicationModal : Qt::NonModal);
1260 popupItem->resetTitle();
1261 popupWindow->setTitle(title);
1262 }
1263 popupItem->setParentItem(popupWindow->contentItem());
1264 popupItem->forceActiveFocus(Qt::PopupFocusReason);
1265 }
1266 if (popupWindow && popupWindow->transientParent()) {
1267 if (qobject_cast<QQuickWindow *>(popupWindow->transientParent())) {
1268 auto *transientParentPriv = QQuickWindowPrivate::get(qobject_cast<QQuickWindow *>(popupWindow->transientParent()));
1269 if (!transientParentPriv->inDestructor)
1270 popupWindow->setVisible(visible);
1271 } else {
1272 popupWindow->setVisible(visible);
1273 }
1274 }
1275 } else {
1276 if (visible) {
1277 popupItem->setParentItem(overlay);
1278 const auto popupStack = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
1279 // if there is a stack of popups, and the current top popup item belongs to an
1280 // ancestor of this popup, then make sure that this popup's item is at the top
1281 // of the stack.
1282 const QQuickPopup *topPopup = popupStack.isEmpty() ? nullptr : popupStack.first();
1283 const QObject *ancestor = q;
1284 while (ancestor && topPopup) {
1285 if (ancestor == topPopup)
1286 break;
1287 ancestor = ancestor->parent();
1288 }
1289 if (topPopup && topPopup != q && ancestor) {
1290 QQuickItem *topPopupItem = popupStack.first()->popupItem();
1291 popupItem->stackAfter(topPopupItem);
1292 // If the popup doesn't have an explicit z value set, set it to be at least as
1293 // high as the current top popup item so that later opened popups are on top.
1294 if (!hasZ)
1295 popupItem->setZ(qMax(topPopupItem->z(), popupItem->z()));
1296 }
1297 q->setModal((popupWndModality != Qt::NonModal) || modal);
1298 }
1299
1300 popupItem->setTitle(title);
1301 }
1302 popupItem->setVisible(visible);
1303}
1304
1305QQuickItem *QQuickPopupPrivate::createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent) const
1306{
1307 QQuickItem *item = nullptr;
1308 if (component) {
1309 QQmlContext *context = component->creationContext();
1310 if (!context)
1311 context = qmlContext(popup);
1312 item = qobject_cast<QQuickItem*>(component->beginCreate(context));
1313 }
1314
1315 // when there is no overlay component available (with plain QQuickWindow),
1316 // use a plain QQuickItem as a fallback to block hover events
1317 if (!item && popup->isModal())
1318 item = new QQuickItem;
1319
1320 if (item) {
1321 item->setParentItem(parent);
1322 if (resolvedPopupType() != QQuickPopup::PopupType::Window)
1323 item->stackBefore(popup->popupItem());
1324 item->setZ(popup->z());
1325 // needed for the virtual keyboard to set a containment mask on the dimmer item
1326 qCDebug(lcDimmer) << "dimmer" << item << "registered with" << parent;
1327 parent->setProperty("_q_dimmerItem", QVariant::fromValue<QQuickItem*>(item));
1328 if (popup->isModal()) {
1329 item->setAcceptedMouseButtons(Qt::AllButtons);
1330#if QT_CONFIG(cursor)
1331 item->setCursor(Qt::ArrowCursor);
1332#endif
1333#if QT_CONFIG(quicktemplates2_hover)
1334 // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
1335 item->setAcceptHoverEvents(true);
1336 // item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
1337 // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
1338#endif
1339 }
1340 if (component)
1341 component->completeCreate();
1342 }
1343 qCDebug(lcDimmer) << "finished creating dimmer from component" << component
1344 << "for popup" << popup << "with parent" << parent << "- item is:" << item;
1345 return item;
1346}
1347
1348void QQuickPopupPrivate::createOverlay()
1349{
1350 Q_Q(QQuickPopup);
1351 QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem);
1352 if (!overlay)
1353 return;
1354
1355 QQmlComponent *component = nullptr;
1356 QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(qmlAttachedPropertiesObject<QQuickOverlay>(q, false));
1357 if (overlayAttached)
1358 component = modal ? overlayAttached->modal() : overlayAttached->modeless();
1359
1360 if (!component)
1361 component = modal ? overlay->modal() : overlay->modeless();
1362
1363 if (!dimmer) {
1364 dimmer = createDimmer(component, q, overlay);
1365 if (!dimmer)
1366 return;
1367 // We cannot update explicitDimmerOpacity when dimmer's opacity changes,
1368 // as it is expected to do so when we fade the dimmer in and out in
1369 // show/hideDimmer, and any binding of the dimmer's opacity will be
1370 // implicitly broken anyway.
1371 explicitDimmerOpacity = dimmer->opacity();
1372 // initially fully transparent, showDimmer fades the dimmer in.
1373 dimmer->setOpacity(0);
1374 if (q->isVisible())
1375 showDimmer();
1376 }
1377 resizeDimmer();
1378}
1379
1380void QQuickPopupPrivate::destroyDimmer()
1381{
1382 if (dimmer) {
1383 qCDebug(lcDimmer) << "destroying dimmer" << dimmer;
1384 if (QObject *dimmerParentItem = dimmer->parentItem()) {
1385 if (dimmerParentItem->property("_q_dimmerItem").value<QQuickItem*>() == dimmer)
1386 dimmerParentItem->setProperty("_q_dimmerItem", QVariant());
1387 }
1388 dimmer->setParentItem(nullptr);
1389 dimmer->deleteLater();
1390 dimmer = nullptr;
1391 }
1392}
1393
1394void QQuickPopupPrivate::toggleOverlay()
1395{
1396 destroyDimmer();
1397 if (dim)
1398 createOverlay();
1399}
1400
1401void QQuickPopupPrivate::updateContentPalettes(const QPalette& parentPalette)
1402{
1403 // Inherit parent palette to all child objects
1404 if (providesPalette())
1405 inheritPalette(parentPalette);
1406 // Inherit parent palette to items within popup (such as headers and footers)
1407 QQuickItemPrivate::get(popupItem)->updateChildrenPalettes(parentPalette);
1408}
1409
1410void QQuickPopupPrivate::updateChildrenPalettes(const QPalette& parentPalette)
1411{
1412 updateContentPalettes(parentPalette);
1413}
1414
1415void QQuickPopupPrivate::showDimmer()
1416{
1417 // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
1418 if (dim && dimmer)
1419 QQmlProperty::write(dimmer, QStringLiteral("opacity"), explicitDimmerOpacity);
1420}
1421
1422void QQuickPopupPrivate::hideDimmer()
1423{
1424 // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors
1425 if (dim && dimmer)
1426 QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0);
1427}
1428
1429void QQuickPopupPrivate::resizeDimmer()
1430{
1431 if (!dimmer)
1432 return;
1433
1434 const QQuickOverlay *overlay = QQuickOverlay::overlay(window, parentItem);
1435
1436 qreal w = overlay ? overlay->width() : 0;
1437 qreal h = overlay ? overlay->height() : 0;
1438 dimmer->setSize(QSizeF(w, h));
1439}
1440
1441QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
1442 : popup(popup)
1443{
1444}
1445
1446void QQuickPopupTransitionManager::transitionEnter()
1447{
1448 if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
1449 cancel();
1450
1451 if (!popup->prepareEnterTransition())
1452 return;
1453
1454 if (popup->window)
1455 transition(popup->enterActions, popup->enter, popup->q_func());
1456 else
1457 finished();
1458}
1459
1460void QQuickPopupTransitionManager::transitionExit()
1461{
1462 if (!popup->prepareExitTransition())
1463 return;
1464
1465 if (popup->window)
1466 transition(popup->exitActions, popup->exit, popup->q_func());
1467 else
1468 finished();
1469}
1470
1471void QQuickPopupTransitionManager::finished()
1472{
1473 if (popup->transitionState == QQuickPopupPrivate::EnterTransition)
1474 popup->finalizeEnterTransition();
1475 else if (popup->transitionState == QQuickPopupPrivate::ExitTransition)
1476 popup->finalizeExitTransition();
1477}
1478
1479QQuickPopup::QQuickPopup(QObject *parent)
1480 : QObject(*(new QQuickPopupPrivate), parent)
1481{
1482 Q_D(QQuickPopup);
1483 d->init();
1484 // By default, allow popup to move beyond window edges
1485 d->relaxEdgeConstraint = true;
1486}
1487
1488QQuickPopup::QQuickPopup(QQuickPopupPrivate &dd, QObject *parent)
1489 : QObject(dd, parent)
1490{
1491 Q_D(QQuickPopup);
1492 d->init();
1493}
1494
1495QQuickPopup::~QQuickPopup()
1496{
1497 Q_D(QQuickPopup);
1498 d->inDestructor = true;
1499
1500 QQuickItem *currentContentItem = d->popupItem->d_func()->contentItem.data();
1501 if (currentContentItem) {
1502 disconnect(currentContentItem, &QQuickItem::childrenChanged,
1503 this, &QQuickPopup::contentChildrenChanged);
1504 }
1505
1506 setParentItem(nullptr);
1507
1508 // If the popup is destroyed before the exit transition finishes,
1509 // the necessary cleanup (removing modal dimmers that block mouse events,
1510 // emitting closed signal, etc.) won't happen. That's why we do it manually here.
1511 if (d->transitionState == QQuickPopupPrivate::ExitTransition && d->transitionManager.isRunning())
1512 d->finalizeExitTransition();
1513
1514 delete d->popupItem;
1515 d->popupItem = nullptr;
1516 delete d->positioner;
1517 d->positioner = nullptr;
1518 if (d->popupWindow)
1519 delete d->popupWindow;
1520 d->popupWindow = nullptr;
1521}
1522
1523/*!
1524 \qmlmethod void QtQuick.Controls::Popup::open()
1525
1526 Opens the popup.
1527
1528 \sa visible
1529*/
1530void QQuickPopup::open()
1531{
1532 setVisible(true);
1533}
1534
1535/*!
1536 \qmlmethod void QtQuick.Controls::Popup::close()
1537
1538 Closes the popup.
1539
1540 \sa visible
1541*/
1542void QQuickPopup::close()
1543{
1544 setVisible(false);
1545}
1546
1547/*!
1548 \qmlproperty real QtQuick.Controls::Popup::x
1549
1550 This property holds the x-coordinate of the popup.
1551
1552 \sa y, z
1553*/
1554qreal QQuickPopup::x() const
1555{
1556 return d_func()->effectivePos.x();
1557}
1558
1559void QQuickPopup::setX(qreal x)
1560{
1561 Q_D(QQuickPopup);
1562 setPosition(QPointF(x, d->y));
1563}
1564
1565/*!
1566 \qmlproperty real QtQuick.Controls::Popup::y
1567
1568 This property holds the y-coordinate of the popup.
1569
1570 \sa x, z
1571*/
1572qreal QQuickPopup::y() const
1573{
1574 return d_func()->effectivePos.y();
1575}
1576
1577void QQuickPopup::setY(qreal y)
1578{
1579 Q_D(QQuickPopup);
1580 setPosition(QPointF(d->x, y));
1581}
1582
1583QPointF QQuickPopup::position() const
1584{
1585 return d_func()->effectivePos;
1586}
1587
1588void QQuickPopup::setPosition(const QPointF &pos)
1589{
1590 Q_D(QQuickPopup);
1591 const bool xChange = !qFuzzyCompare(d->x, pos.x());
1592 const bool yChange = !qFuzzyCompare(d->y, pos.y());
1593 if (!xChange && !yChange)
1594 return;
1595
1596 d->x = pos.x();
1597 d->y = pos.y();
1598 if (d->popupItem->isVisible()) {
1599 d->reposition();
1600 } else {
1601 if (xChange)
1602 emit xChanged();
1603 if (yChange)
1604 emit yChanged();
1605 }
1606}
1607
1608/*!
1609 \qmlproperty real QtQuick.Controls::Popup::z
1610
1611 This property holds the z-value of the popup. Z-value determines
1612 the stacking order of popups.
1613
1614 If two visible popups have the same z-value, the last one that
1615 was opened will be on top.
1616
1617 If a popup has no explicitly set z-value when opened, and is a child
1618 of an already open popup, then it will be stacked on top of its parent.
1619 This ensures that children are never hidden under their parents.
1620
1621 If the popup has its own window, the z-value will determine the window
1622 stacking order instead.
1623
1624 The default z-value is \c 0.
1625
1626 \sa x, y
1627*/
1628qreal QQuickPopup::z() const
1629{
1630 Q_D(const QQuickPopup);
1631 return d->popupItem->z();
1632}
1633
1634void QQuickPopup::setZ(qreal z)
1635{
1636 Q_D(QQuickPopup);
1637 d->hasZ = true;
1638 bool previousZ = d->popupWindow ? d->popupWindow->z() : d->popupItem->z();
1639 if (qFuzzyCompare(z, previousZ))
1640 return;
1641 if (d->popupWindow)
1642 d->popupWindow->setZ(z);
1643 else
1644 d->popupItem->setZ(z);
1645 emit zChanged();
1646}
1647
1648void QQuickPopup::resetZ()
1649{
1650 Q_D(QQuickPopup);
1651 setZ(0);
1652 d->hasZ = false;
1653}
1654
1655/*!
1656 \qmlproperty real QtQuick.Controls::Popup::width
1657
1658 This property holds the width of the popup.
1659*/
1660qreal QQuickPopup::width() const
1661{
1662 Q_D(const QQuickPopup);
1663 return d->popupItem->width();
1664}
1665
1666void QQuickPopup::setWidth(qreal width)
1667{
1668 Q_D(QQuickPopup);
1669 d->hasWidth = true;
1670
1671 // QQuickPopupWindow::setWidth() triggers a window resize event.
1672 // This will cause QQuickPopupWindow::resizeEvent() to resize
1673 // the popupItem. QQuickPopupItem::geometryChanged() calls QQuickPopup::geometryChange(),
1674 // which emits widthChanged().
1675
1676 if (d->popupWindow)
1677 d->popupWindow->setWidth(width + d->windowInsets().left() + d->windowInsets().right());
1678 else
1679 d->popupItem->setWidth(width);
1680}
1681
1682void QQuickPopup::resetWidth()
1683{
1684 Q_D(QQuickPopup);
1685 if (!d->hasWidth)
1686 return;
1687
1688 d->hasWidth = false;
1689 d->popupItem->resetWidth();
1690 if (d->popupItem->isVisible())
1691 d->reposition();
1692}
1693
1694/*!
1695 \qmlproperty real QtQuick.Controls::Popup::height
1696
1697 This property holds the height of the popup.
1698*/
1699qreal QQuickPopup::height() const
1700{
1701 Q_D(const QQuickPopup);
1702 return d->popupItem->height();
1703}
1704
1705void QQuickPopup::setHeight(qreal height)
1706{
1707 Q_D(QQuickPopup);
1708 d->hasHeight = true;
1709
1710 // QQuickPopupWindow::setHeight() triggers a window resize event.
1711 // This will cause QQuickPopupWindow::resizeEvent() to resize
1712 // the popupItem. QQuickPopupItem::geometryChanged() calls QQuickPopup::geometryChange(),
1713 // which emits heightChanged().
1714
1715 if (d->popupWindow)
1716 d->popupWindow->setHeight(height + d->windowInsets().top() + d->windowInsets().bottom());
1717 else
1718 d->popupItem->setHeight(height);
1719}
1720
1721void QQuickPopup::resetHeight()
1722{
1723 Q_D(QQuickPopup);
1724 if (!d->hasHeight)
1725 return;
1726
1727 d->hasHeight = false;
1728 d->popupItem->resetHeight();
1729 if (d->popupItem->isVisible())
1730 d->reposition();
1731}
1732
1733/*!
1734 \qmlproperty real QtQuick.Controls::Popup::implicitWidth
1735
1736 This property holds the implicit width of the popup.
1737*/
1738qreal QQuickPopup::implicitWidth() const
1739{
1740 Q_D(const QQuickPopup);
1741 return d->popupItem->implicitWidth();
1742}
1743
1744void QQuickPopup::setImplicitWidth(qreal width)
1745{
1746 Q_D(QQuickPopup);
1747 d->popupItem->setImplicitWidth(width);
1748}
1749
1750/*!
1751 \qmlproperty real QtQuick.Controls::Popup::implicitHeight
1752
1753 This property holds the implicit height of the popup.
1754*/
1755qreal QQuickPopup::implicitHeight() const
1756{
1757 Q_D(const QQuickPopup);
1758 return d->popupItem->implicitHeight();
1759}
1760
1761void QQuickPopup::setImplicitHeight(qreal height)
1762{
1763 Q_D(QQuickPopup);
1764 d->popupItem->setImplicitHeight(height);
1765}
1766
1767/*!
1768 \qmlproperty real QtQuick.Controls::Popup::contentWidth
1769
1770 This property holds the content width. It is used for calculating the
1771 total implicit width of the Popup.
1772
1773 For more information, see \l {Popup Sizing}.
1774
1775 \sa contentHeight
1776*/
1777qreal QQuickPopup::contentWidth() const
1778{
1779 Q_D(const QQuickPopup);
1780 return d->popupItem->contentWidth();
1781}
1782
1783void QQuickPopup::setContentWidth(qreal width)
1784{
1785 Q_D(QQuickPopup);
1786 d->popupItem->setContentWidth(width);
1787}
1788
1789/*!
1790 \qmlproperty real QtQuick.Controls::Popup::contentHeight
1791
1792 This property holds the content height. It is used for calculating the
1793 total implicit height of the Popup.
1794
1795 For more information, see \l {Popup Sizing}.
1796
1797 \sa contentWidth
1798*/
1799qreal QQuickPopup::contentHeight() const
1800{
1801 Q_D(const QQuickPopup);
1802 return d->popupItem->contentHeight();
1803}
1804
1805void QQuickPopup::setContentHeight(qreal height)
1806{
1807 Q_D(QQuickPopup);
1808 d->popupItem->setContentHeight(height);
1809}
1810
1811/*!
1812 \qmlproperty real QtQuick.Controls::Popup::availableWidth
1813 \readonly
1814
1815 This property holds the width available to the \l contentItem after
1816 deducting horizontal padding from the \l {Item::}{width} of the popup.
1817
1818 \sa padding, leftPadding, rightPadding
1819*/
1820qreal QQuickPopup::availableWidth() const
1821{
1822 Q_D(const QQuickPopup);
1823 return d->popupItem->availableWidth();
1824}
1825
1826/*!
1827 \qmlproperty real QtQuick.Controls::Popup::availableHeight
1828 \readonly
1829
1830 This property holds the height available to the \l contentItem after
1831 deducting vertical padding from the \l {Item::}{height} of the popup.
1832
1833 \sa padding, topPadding, bottomPadding
1834*/
1835qreal QQuickPopup::availableHeight() const
1836{
1837 Q_D(const QQuickPopup);
1838 return d->popupItem->availableHeight();
1839}
1840
1841/*!
1842 \since QtQuick.Controls 2.1 (Qt 5.8)
1843 \qmlproperty real QtQuick.Controls::Popup::spacing
1844
1845 This property holds the spacing.
1846
1847 Spacing is useful for popups that have multiple or repetitive building
1848 blocks. For example, some styles use spacing to determine the distance
1849 between the header, content, and footer of \l Dialog. Spacing is not
1850 enforced by Popup, so each style may interpret it differently, and some
1851 may ignore it altogether.
1852*/
1853qreal QQuickPopup::spacing() const
1854{
1855 Q_D(const QQuickPopup);
1856 return d->popupItem->spacing();
1857}
1858
1859void QQuickPopup::setSpacing(qreal spacing)
1860{
1861 Q_D(QQuickPopup);
1862 d->popupItem->setSpacing(spacing);
1863}
1864
1865void QQuickPopup::resetSpacing()
1866{
1867 setSpacing(0);
1868}
1869
1870/*!
1871 \qmlproperty real QtQuick.Controls::Popup::margins
1872
1873 This property holds the distance between the edges of the popup and the
1874 edges of its window.
1875
1876 A popup with negative margins is not pushed within the bounds
1877 of the enclosing window. The default value is \c -1.
1878
1879 \sa topMargin, leftMargin, rightMargin, bottomMargin, {Popup Layout}
1880*/
1881qreal QQuickPopup::margins() const
1882{
1883 Q_D(const QQuickPopup);
1884 return d->margins;
1885}
1886
1887void QQuickPopup::setMargins(qreal margins)
1888{
1889 Q_D(QQuickPopup);
1890 if (qFuzzyCompare(d->margins, margins))
1891 return;
1892 QMarginsF oldMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
1893 d->margins = margins;
1894 emit marginsChanged();
1895 QMarginsF newMargins(leftMargin(), topMargin(), rightMargin(), bottomMargin());
1896 if (!qFuzzyCompare(newMargins.top(), oldMargins.top()))
1897 emit topMarginChanged();
1898 if (!qFuzzyCompare(newMargins.left(), oldMargins.left()))
1899 emit leftMarginChanged();
1900 if (!qFuzzyCompare(newMargins.right(), oldMargins.right()))
1901 emit rightMarginChanged();
1902 if (!qFuzzyCompare(newMargins.bottom(), oldMargins.bottom()))
1903 emit bottomMarginChanged();
1904 marginsChange(newMargins, oldMargins);
1905}
1906
1907void QQuickPopup::resetMargins()
1908{
1909 setMargins(-1);
1910}
1911
1912/*!
1913 \qmlproperty real QtQuick.Controls::Popup::topMargin
1914
1915 This property holds the distance between the top edge of the popup and
1916 the top edge of its window.
1917
1918 A popup with a negative top margin is not pushed within the top edge
1919 of the enclosing window. The default value is \c -1.
1920
1921 \sa margins, bottomMargin, {Popup Layout}
1922*/
1923qreal QQuickPopup::topMargin() const
1924{
1925 Q_D(const QQuickPopup);
1926 if (d->hasTopMargin)
1927 return d->topMargin;
1928 return d->margins;
1929}
1930
1931void QQuickPopup::setTopMargin(qreal margin)
1932{
1933 Q_D(QQuickPopup);
1934 d->setTopMargin(margin);
1935}
1936
1937void QQuickPopup::resetTopMargin()
1938{
1939 Q_D(QQuickPopup);
1940 d->setTopMargin(-1, true);
1941}
1942
1943/*!
1944 \qmlproperty real QtQuick.Controls::Popup::leftMargin
1945
1946 This property holds the distance between the left edge of the popup and
1947 the left edge of its window.
1948
1949 A popup with a negative left margin is not pushed within the left edge
1950 of the enclosing window. The default value is \c -1.
1951
1952 \sa margins, rightMargin, {Popup Layout}
1953*/
1954qreal QQuickPopup::leftMargin() const
1955{
1956 Q_D(const QQuickPopup);
1957 if (d->hasLeftMargin)
1958 return d->leftMargin;
1959 return d->margins;
1960}
1961
1962void QQuickPopup::setLeftMargin(qreal margin)
1963{
1964 Q_D(QQuickPopup);
1965 d->setLeftMargin(margin);
1966}
1967
1968void QQuickPopup::resetLeftMargin()
1969{
1970 Q_D(QQuickPopup);
1971 d->setLeftMargin(-1, true);
1972}
1973
1974/*!
1975 \qmlproperty real QtQuick.Controls::Popup::rightMargin
1976
1977 This property holds the distance between the right edge of the popup and
1978 the right edge of its window.
1979
1980 A popup with a negative right margin is not pushed within the right edge
1981 of the enclosing window. The default value is \c -1.
1982
1983 \sa margins, leftMargin, {Popup Layout}
1984*/
1985qreal QQuickPopup::rightMargin() const
1986{
1987 Q_D(const QQuickPopup);
1988 if (d->hasRightMargin)
1989 return d->rightMargin;
1990 return d->margins;
1991}
1992
1993void QQuickPopup::setRightMargin(qreal margin)
1994{
1995 Q_D(QQuickPopup);
1996 d->setRightMargin(margin);
1997}
1998
1999void QQuickPopup::resetRightMargin()
2000{
2001 Q_D(QQuickPopup);
2002 d->setRightMargin(-1, true);
2003}
2004
2005/*!
2006 \qmlproperty real QtQuick.Controls::Popup::bottomMargin
2007
2008 This property holds the distance between the bottom edge of the popup and
2009 the bottom edge of its window.
2010
2011 A popup with a negative bottom margin is not pushed within the bottom edge
2012 of the enclosing window. The default value is \c -1.
2013
2014 \sa margins, topMargin, {Popup Layout}
2015*/
2016qreal QQuickPopup::bottomMargin() const
2017{
2018 Q_D(const QQuickPopup);
2019 if (d->hasBottomMargin)
2020 return d->bottomMargin;
2021 return d->margins;
2022}
2023
2024void QQuickPopup::setBottomMargin(qreal margin)
2025{
2026 Q_D(QQuickPopup);
2027 d->setBottomMargin(margin);
2028}
2029
2030void QQuickPopup::resetBottomMargin()
2031{
2032 Q_D(QQuickPopup);
2033 d->setBottomMargin(-1, true);
2034}
2035
2036/*!
2037 \qmlproperty real QtQuick.Controls::Popup::padding
2038
2039 This property holds the default padding.
2040
2041 \include qquickpopup-padding.qdocinc
2042
2043 \sa availableWidth, availableHeight, topPadding, leftPadding, rightPadding, bottomPadding
2044*/
2045qreal QQuickPopup::padding() const
2046{
2047 Q_D(const QQuickPopup);
2048 return d->popupItem->padding();
2049}
2050
2051void QQuickPopup::setPadding(qreal padding)
2052{
2053 Q_D(QQuickPopup);
2054 d->popupItem->setPadding(padding);
2055}
2056
2057void QQuickPopup::resetPadding()
2058{
2059 Q_D(QQuickPopup);
2060 d->popupItem->resetPadding();
2061}
2062
2063/*!
2064 \qmlproperty real QtQuick.Controls::Popup::topPadding
2065
2066 This property holds the top padding. Unless explicitly set, the value
2067 is equal to \c verticalPadding.
2068
2069 \include qquickpopup-padding.qdocinc
2070
2071 \sa padding, bottomPadding, verticalPadding, availableHeight
2072*/
2073qreal QQuickPopup::topPadding() const
2074{
2075 Q_D(const QQuickPopup);
2076 return d->popupItem->topPadding();
2077}
2078
2079void QQuickPopup::setTopPadding(qreal padding)
2080{
2081 Q_D(QQuickPopup);
2082 d->popupItem->setTopPadding(padding);
2083}
2084
2085void QQuickPopup::resetTopPadding()
2086{
2087 Q_D(QQuickPopup);
2088 d->popupItem->resetTopPadding();
2089}
2090
2091/*!
2092 \qmlproperty real QtQuick.Controls::Popup::leftPadding
2093
2094 This property holds the left padding. Unless explicitly set, the value
2095 is equal to \c horizontalPadding.
2096
2097 \include qquickpopup-padding.qdocinc
2098
2099 \sa padding, rightPadding, horizontalPadding, availableWidth
2100*/
2101qreal QQuickPopup::leftPadding() const
2102{
2103 Q_D(const QQuickPopup);
2104 return d->popupItem->leftPadding();
2105}
2106
2107void QQuickPopup::setLeftPadding(qreal padding)
2108{
2109 Q_D(QQuickPopup);
2110 d->popupItem->setLeftPadding(padding);
2111}
2112
2113void QQuickPopup::resetLeftPadding()
2114{
2115 Q_D(QQuickPopup);
2116 d->popupItem->resetLeftPadding();
2117}
2118
2119/*!
2120 \qmlproperty real QtQuick.Controls::Popup::rightPadding
2121
2122 This property holds the right padding. Unless explicitly set, the value
2123 is equal to \c horizontalPadding.
2124
2125 \include qquickpopup-padding.qdocinc
2126
2127 \sa padding, leftPadding, horizontalPadding, availableWidth
2128*/
2129qreal QQuickPopup::rightPadding() const
2130{
2131 Q_D(const QQuickPopup);
2132 return d->popupItem->rightPadding();
2133}
2134
2135void QQuickPopup::setRightPadding(qreal padding)
2136{
2137 Q_D(QQuickPopup);
2138 d->popupItem->setRightPadding(padding);
2139}
2140
2141void QQuickPopup::resetRightPadding()
2142{
2143 Q_D(QQuickPopup);
2144 d->popupItem->resetRightPadding();
2145}
2146
2147/*!
2148 \qmlproperty real QtQuick.Controls::Popup::bottomPadding
2149
2150 This property holds the bottom padding. Unless explicitly set, the value
2151 is equal to \c verticalPadding.
2152
2153 \include qquickpopup-padding.qdocinc
2154
2155 \sa padding, topPadding, verticalPadding, availableHeight
2156*/
2157qreal QQuickPopup::bottomPadding() const
2158{
2159 Q_D(const QQuickPopup);
2160 return d->popupItem->bottomPadding();
2161}
2162
2163void QQuickPopup::setBottomPadding(qreal padding)
2164{
2165 Q_D(QQuickPopup);
2166 d->popupItem->setBottomPadding(padding);
2167}
2168
2169void QQuickPopup::resetBottomPadding()
2170{
2171 Q_D(QQuickPopup);
2172 d->popupItem->resetBottomPadding();
2173}
2174
2175/*!
2176 \qmlproperty Locale QtQuick.Controls::Popup::locale
2177
2178 This property holds the locale of the popup.
2179
2180 \sa mirrored, {LayoutMirroring}{LayoutMirroring}
2181*/
2182QLocale QQuickPopup::locale() const
2183{
2184 Q_D(const QQuickPopup);
2185 return d->popupItem->locale();
2186}
2187
2188void QQuickPopup::setLocale(const QLocale &locale)
2189{
2190 Q_D(QQuickPopup);
2191 d->popupItem->setLocale(locale);
2192}
2193
2194void QQuickPopup::resetLocale()
2195{
2196 Q_D(QQuickPopup);
2197 d->popupItem->resetLocale();
2198}
2199
2200/*!
2201 \since QtQuick.Controls 2.3 (Qt 5.10)
2202 \qmlproperty bool QtQuick.Controls::Popup::mirrored
2203 \readonly
2204
2205 This property holds whether the popup is mirrored.
2206
2207 This property is provided for convenience. A popup is considered mirrored
2208 when its visual layout direction is right-to-left; that is, when using a
2209 right-to-left locale.
2210
2211 \sa locale, {Right-to-left User Interfaces}
2212*/
2213bool QQuickPopup::isMirrored() const
2214{
2215 Q_D(const QQuickPopup);
2216 return d->popupItem->isMirrored();
2217}
2218
2219/*!
2220 \qmlproperty font QtQuick.Controls::Popup::font
2221
2222 This property holds the font currently set for the popup.
2223
2224 Popup propagates explicit font properties to its children. If you change a specific
2225 property on a popup's font, that property propagates to all of the popup's children,
2226 overriding any system defaults for that property.
2227
2228 \code
2229 Popup {
2230 font.family: "Courier"
2231
2232 Column {
2233 Label {
2234 text: qsTr("This will use Courier...")
2235 }
2236
2237 Switch {
2238 text: qsTr("... and so will this")
2239 }
2240 }
2241 }
2242 \endcode
2243
2244 \sa Control::font, ApplicationWindow::font
2245*/
2246QFont QQuickPopup::font() const
2247{
2248 Q_D(const QQuickPopup);
2249 return d->popupItem->font();
2250}
2251
2252void QQuickPopup::setFont(const QFont &font)
2253{
2254 Q_D(QQuickPopup);
2255 d->popupItem->setFont(font);
2256}
2257
2258void QQuickPopup::resetFont()
2259{
2260 Q_D(QQuickPopup);
2261 d->popupItem->resetFont();
2262}
2263
2264QQuickWindow *QQuickPopup::window() const
2265{
2266 Q_D(const QQuickPopup);
2267 return d->window;
2268}
2269
2270QQuickItem *QQuickPopup::popupItem() const
2271{
2272 Q_D(const QQuickPopup);
2273 return d->popupItem;
2274}
2275
2276/*!
2277 \qmlproperty Item QtQuick.Controls::Popup::parent
2278
2279 This property holds the parent item.
2280*/
2281QQuickItem *QQuickPopup::parentItem() const
2282{
2283 Q_D(const QQuickPopup);
2284 return d->parentItem;
2285}
2286
2287void QQuickPopup::setParentItem(QQuickItem *parent)
2288{
2289 Q_D(QQuickPopup);
2290 if (d->parentItem == parent)
2291 return;
2292
2293 if (d->parentItem) {
2294 QObjectPrivate::disconnect(d->parentItem, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
2295 QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
2296 }
2297 d->parentItem = parent;
2298 QQuickPopupPositioner *positioner = d->getPositioner();
2299 if (positioner->parentItem())
2300 positioner->setParentItem(parent);
2301 if (parent) {
2302 QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
2303 QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
2304 } else if (d->inDestructor) {
2305 d->destroyDimmer();
2306 } else {
2307 // Reset transition manager state when its parent window destroyed
2308 if (!d->window && d->transitionManager.isRunning()) {
2309 if (d->transitionState == QQuickPopupPrivate::EnterTransition)
2310 d->finalizeEnterTransition();
2311 else if (d->transitionState == QQuickPopupPrivate::ExitTransition)
2312 d->finalizeExitTransition();
2313 }
2314 // NOTE: if setParentItem is called from the dtor, this bypasses virtual dispatch and calls
2315 // QQuickPopup::close() directly
2316 close();
2317 }
2318 d->setWindow(parent ? parent->window() : nullptr);
2319 emit parentChanged();
2320}
2321
2322void QQuickPopup::resetParentItem()
2323{
2324 if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent()))
2325 setParentItem(window->contentItem());
2326 else
2327 setParentItem(findParentItem());
2328}
2329
2330/*!
2331 \qmlproperty Item QtQuick.Controls::Popup::background
2332
2333 This property holds the background item.
2334
2335 \note If the background item has no explicit size specified, it automatically
2336 follows the popup's size. In most cases, there is no need to specify
2337 width or height for a background item.
2338
2339 \note Most popups use the implicit size of the background item to calculate
2340 the implicit size of the popup itself. If you replace the background item
2341 with a custom one, you should also consider providing a sensible implicit
2342 size for it (unless it is an item like \l Image which has its own implicit
2343 size).
2344
2345 \sa {Customizing Popup}
2346*/
2347QQuickItem *QQuickPopup::background() const
2348{
2349 Q_D(const QQuickPopup);
2350 return d->popupItem->background();
2351}
2352
2353void QQuickPopup::setBackground(QQuickItem *background)
2354{
2355 Q_D(QQuickPopup);
2356 // The __notCustomizable property won't be on "this" when the popup item's setBackground function
2357 // is called, so it won't warn. That's why we do a check here.
2358 QQuickControlPrivate::warnIfCustomizationNotSupported(this, background, QStringLiteral("background"));
2359 d->popupItem->setBackground(background);
2360}
2361
2362/*!
2363 \qmlproperty Item QtQuick.Controls::Popup::contentItem
2364
2365 This property holds the content item of the popup.
2366
2367 The content item is the visual implementation of the popup. When the
2368 popup is made visible, the content item is automatically reparented to
2369 the \l {Overlay::overlay}{overlay item}.
2370
2371 \note The content item is automatically resized to fit within the
2372 \l padding of the popup.
2373
2374 \note Most popups use the implicit size of the content item to calculate
2375 the implicit size of the popup itself. If you replace the content item
2376 with a custom one, you should also consider providing a sensible implicit
2377 size for it (unless it is an item like \l Text which has its own implicit
2378 size).
2379
2380 \sa {Customizing Popup}
2381*/
2382QQuickItem *QQuickPopup::contentItem() const
2383{
2384 Q_D(const QQuickPopup);
2385 return d->popupItem->contentItem();
2386}
2387
2388void QQuickPopup::setContentItem(QQuickItem *item)
2389{
2390 Q_D(QQuickPopup);
2391 // See comment in setBackground for why we do this.
2392 QQuickControlPrivate::warnIfCustomizationNotSupported(this, item, QStringLiteral("contentItem"));
2393 QQuickItem *oldContentItem = d->complete ? d->popupItem->d_func()->contentItem.data()
2394 : nullptr;
2395 if (oldContentItem)
2396 disconnect(oldContentItem, &QQuickItem::childrenChanged, this, &QQuickPopup::contentChildrenChanged);
2397 d->popupItem->setContentItem(item);
2398 if (d->complete) {
2399 QQuickItem *newContentItem = d->popupItem->d_func()->contentItem.data();
2400 if (newContentItem)
2401 connect(newContentItem, &QQuickItem::childrenChanged, this, &QQuickPopup::contentChildrenChanged);
2402 if (oldContentItem != newContentItem)
2403 emit contentChildrenChanged();
2404 }
2405}
2406
2407/*!
2408 \qmlproperty list<QtObject> QtQuick.Controls::Popup::contentData
2409 \qmldefault
2410
2411 This property holds the list of content data.
2412
2413 The list contains all objects that have been declared in QML as children
2414 of the popup.
2415
2416 \note Unlike \c contentChildren, \c contentData does include non-visual QML
2417 objects.
2418
2419 \sa Item::data, contentChildren
2420*/
2421QQmlListProperty<QObject> QQuickPopupPrivate::contentData()
2422{
2423 QQuickControlPrivate *p = QQuickControlPrivate::get(popupItem);
2424 if (!p->contentItem)
2425 p->executeContentItem();
2426 return QQmlListProperty<QObject>(popupItem->contentItem(), nullptr,
2427 QQuickItemPrivate::data_append,
2428 QQuickItemPrivate::data_count,
2429 QQuickItemPrivate::data_at,
2430 QQuickItemPrivate::data_clear);
2431}
2432
2433/*!
2434 \qmlproperty list<Item> QtQuick.Controls::Popup::contentChildren
2435
2436 This property holds the list of content children.
2437
2438 The list contains all items that have been declared in QML as children
2439 of the popup.
2440
2441 \note Unlike \c contentData, \c contentChildren does not include non-visual
2442 QML objects.
2443
2444 \sa Item::children, contentData
2445*/
2446QQmlListProperty<QQuickItem> QQuickPopupPrivate::contentChildren()
2447{
2448 return QQmlListProperty<QQuickItem>(popupItem->contentItem(), nullptr,
2449 QQuickItemPrivate::children_append,
2450 QQuickItemPrivate::children_count,
2451 QQuickItemPrivate::children_at,
2452 QQuickItemPrivate::children_clear);
2453}
2454
2455/*!
2456 \qmlproperty bool QtQuick.Controls::Popup::clip
2457
2458 This property holds whether clipping is enabled. The default value is \c false.
2459 Clipping only works when the popup isn't in its own window.
2460*/
2461bool QQuickPopup::clip() const
2462{
2463 Q_D(const QQuickPopup);
2464 return d->popupItem->clip() && !d->usePopupWindow();
2465}
2466
2467void QQuickPopup::setClip(bool clip)
2468{
2469 Q_D(QQuickPopup);
2470 if (clip == d->popupItem->clip() || d->usePopupWindow())
2471 return;
2472 d->popupItem->setClip(clip);
2473 emit clipChanged();
2474}
2475
2476/*!
2477 \qmlproperty bool QtQuick.Controls::Popup::focus
2478
2479 This property holds whether the popup wants focus.
2480
2481 When the popup actually receives focus, \l activeFocus will be \c true.
2482 For more information, see \l {Keyboard Focus in Qt Quick}.
2483
2484 The default value is \c false.
2485
2486 \sa activeFocus
2487*/
2488bool QQuickPopup::hasFocus() const
2489{
2490 Q_D(const QQuickPopup);
2491 return d->focus;
2492}
2493
2494void QQuickPopup::setFocus(bool focus)
2495{
2496 Q_D(QQuickPopup);
2497 if (d->focus == focus)
2498 return;
2499 d->focus = focus;
2500 emit focusChanged();
2501}
2502
2503/*!
2504 \qmlproperty bool QtQuick.Controls::Popup::activeFocus
2505 \readonly
2506
2507 This property holds whether the popup has active focus.
2508
2509 \sa focus, {Keyboard Focus in Qt Quick}
2510*/
2511bool QQuickPopup::hasActiveFocus() const
2512{
2513 Q_D(const QQuickPopup);
2514 return d->popupItem->hasActiveFocus();
2515}
2516
2517/*!
2518 \qmlproperty bool QtQuick.Controls::Popup::modal
2519
2520 This property holds whether the popup is modal.
2521
2522 Modal popups often have a distinctive background dimming effect defined
2523 in \l {Overlay::modal}{Overlay.modal}, and do not allow press
2524 or release events through to items beneath them. For example, if the user
2525 accidentally clicks outside of a popup, any item beneath that popup at
2526 the location of the click will not receive the event.
2527
2528 On desktop platforms, it is common for modal popups to be closed only when
2529 the escape key is pressed. To achieve this behavior, set
2530 \l closePolicy to \c Popup.CloseOnEscape. By default, \c closePolicy
2531 is set to \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}, which
2532 means that clicking outside of a modal popup will close it.
2533
2534 The default value is \c false.
2535
2536 \sa dim
2537*/
2538bool QQuickPopup::isModal() const
2539{
2540 Q_D(const QQuickPopup);
2541 return d->modal;
2542}
2543
2544void QQuickPopup::setModal(bool modal)
2545{
2546 Q_D(QQuickPopup);
2547 if (d->modal == modal)
2548 return;
2549 d->modal = modal;
2550 d->popupWindowDirty = true;
2551 if (d->complete && d->visible)
2552 d->toggleOverlay();
2553 emit modalChanged();
2554
2555 if (!d->hasDim) {
2556 setDim(modal);
2557 d->hasDim = false;
2558 }
2559}
2560
2561/*!
2562 \qmlproperty bool QtQuick.Controls::Popup::dim
2563
2564 This property holds whether the popup dims the background.
2565
2566 Unless explicitly set, this property follows the value of \l modal. To
2567 return to the default value, set this property to \c undefined.
2568
2569 \sa modal, {Overlay::modeless}{Overlay.modeless}
2570*/
2571bool QQuickPopup::dim() const
2572{
2573 Q_D(const QQuickPopup);
2574 return d->dim;
2575}
2576
2577void QQuickPopup::setDim(bool dim)
2578{
2579 Q_D(QQuickPopup);
2580 d->hasDim = true;
2581
2582 if (d->dim == dim)
2583 return;
2584
2585 d->dim = dim;
2586 if (d->complete && d->visible)
2587 d->toggleOverlay();
2588 emit dimChanged();
2589}
2590
2591void QQuickPopup::resetDim()
2592{
2593 Q_D(QQuickPopup);
2594 if (!d->hasDim)
2595 return;
2596
2597 setDim(d->modal);
2598 d->hasDim = false;
2599}
2600
2601/*!
2602 \qmlproperty bool QtQuick.Controls::Popup::visible
2603
2604 This property holds whether the popup is visible. The default value is \c false.
2605
2606 \sa open(), close(), opened
2607*/
2608bool QQuickPopup::isVisible() const
2609{
2610 Q_D(const QQuickPopup);
2611 return d->visible && d->popupItem->isVisible();
2612}
2613
2614void QQuickPopup::setVisible(bool visible)
2615{
2616 Q_D(QQuickPopup);
2617 // During an exit transition, d->visible == true until the transition has completed.
2618 // Therefore, this guard must not return early if setting visible to true while
2619 // d->visible is true.
2620 if (d->visible && visible && d->transitionState != QQuickPopupPrivate::ExitTransition)
2621 return;
2622
2623 if (!d->visible && !visible)
2624 return;
2625
2626 if (!d->complete || (visible && !d->window)) {
2627 d->visible = visible;
2628 return;
2629 }
2630
2631 if (visible && !parentItem()) {
2632 qmlWarning(this) << "cannot show popup: parent is null";
2633 return;
2634 }
2635
2636 if (visible)
2637 openPopup(d);
2638 else
2639 d->transitionManager.transitionExit();
2640}
2641
2642/*!
2643 \since QtQuick.Controls 2.3 (Qt 5.10)
2644 \qmlproperty bool QtQuick.Controls::Popup::enabled
2645
2646 This property holds whether the popup is enabled. The default value is \c true.
2647
2648 \sa visible, Item::enabled
2649*/
2650bool QQuickPopup::isEnabled() const
2651{
2652 Q_D(const QQuickPopup);
2653 return d->popupItem->isEnabled();
2654}
2655
2656void QQuickPopup::setEnabled(bool enabled)
2657{
2658 Q_D(QQuickPopup);
2659 d->popupItem->setEnabled(enabled);
2660}
2661
2662/*!
2663 \since QtQuick.Controls 2.3 (Qt 5.10)
2664 \qmlproperty bool QtQuick.Controls::Popup::opened
2665
2666 This property holds whether the popup is fully open. The popup is considered opened
2667 when it's visible and neither the \l enter nor \l exit transitions are running.
2668
2669 \sa open(), close(), visible
2670*/
2671bool QQuickPopup::isOpened() const
2672{
2673 Q_D(const QQuickPopup);
2674 return d->transitionState == QQuickPopupPrivate::NoTransition && isVisible();
2675}
2676
2677/*!
2678 \qmlproperty real QtQuick.Controls::Popup::opacity
2679
2680 This property holds the opacity of the popup. Opacity is specified as a number between
2681 \c 0.0 (fully transparent) and \c 1.0 (fully opaque). The default value is \c 1.0.
2682
2683 \sa visible
2684*/
2685qreal QQuickPopup::opacity() const
2686{
2687 Q_D(const QQuickPopup);
2688 return d->popupItem->opacity();
2689}
2690
2691void QQuickPopup::setOpacity(qreal opacity)
2692{
2693 Q_D(QQuickPopup);
2694 d->popupItem->setOpacity(opacity);
2695}
2696
2697/*!
2698 \qmlproperty real QtQuick.Controls::Popup::scale
2699
2700 This property holds the scale factor of the popup. The default value is \c 1.0.
2701
2702 A scale of less than \c 1.0 causes the popup to be rendered at a smaller size,
2703 and a scale greater than \c 1.0 renders the popup at a larger size. Negative
2704 scales are not supported.
2705*/
2706qreal QQuickPopup::scale() const
2707{
2708 Q_D(const QQuickPopup);
2709 return d->popupItem->scale();
2710}
2711
2712void QQuickPopup::setScale(qreal scale)
2713{
2714 Q_D(QQuickPopup);
2715 if (qFuzzyCompare(scale, d->popupItem->scale()))
2716 return;
2717 d->popupItem->setScale(scale);
2718 emit scaleChanged();
2719}
2720
2721/*!
2722 \qmlproperty enumeration QtQuick.Controls::Popup::closePolicy
2723
2724 This property determines the circumstances under which the popup closes.
2725 The flags can be combined to allow several ways of closing the popup.
2726
2727 The available values are:
2728 \value Popup.NoAutoClose The popup will only close when manually instructed to do so.
2729 \value Popup.CloseOnPressOutside The popup will close when the mouse is pressed outside of it.
2730 \value Popup.CloseOnPressOutsideParent The popup will close when the mouse is pressed outside of its parent.
2731 \value Popup.CloseOnReleaseOutside The popup will close when the mouse is released outside of it.
2732 \value Popup.CloseOnReleaseOutsideParent The popup will close when the mouse is released outside of its parent.
2733 \value Popup.CloseOnEscape The popup will close when the escape key is pressed while the popup
2734 has active focus.
2735 \value Popup.CloseMultiple When using multiple nested popups, only the top-most popup closes on each outside
2736 click by default. When the closing popup has this flag set, the next popup in the stack is also
2737 checked: if the click position was outside it too, it closes as well. This cascade
2738 continues down the stack until all popups have closed, a popup whose bounds contain
2739 the click position is reached, or a popup without \c CloseMultiple is closed. Must
2740 be combined with at least one \c {CloseOnPress*} or \c {CloseOnRelease*} flag.
2741
2742 The default value is \c {Popup.CloseOnEscape | Popup.CloseOnPressOutside}.
2743
2744 \note There is a known limitation that the \c Popup.CloseOnReleaseOutside
2745 and \c Popup.CloseOnReleaseOutsideParent policies only work with
2746 \l modal popups.
2747*/
2748QQuickPopup::ClosePolicy QQuickPopup::closePolicy() const
2749{
2750 Q_D(const QQuickPopup);
2751 return d->closePolicy;
2752}
2753
2754void QQuickPopup::setClosePolicy(ClosePolicy policy)
2755{
2756 Q_D(QQuickPopup);
2757 d->hasClosePolicy = true;
2758 if (d->closePolicy == policy)
2759 return;
2760 d->closePolicy = policy;
2761 emit closePolicyChanged();
2762}
2763
2764void QQuickPopup::resetClosePolicy()
2765{
2766 Q_D(QQuickPopup);
2767 setClosePolicy(QQuickPopupPrivate::DefaultClosePolicy);
2768 d->hasClosePolicy = false;
2769}
2770
2771/*!
2772 \qmlproperty enumeration QtQuick.Controls::Popup::transformOrigin
2773
2774 This property holds the origin point for transformations in enter and exit transitions.
2775
2776 Nine transform origins are available, as shown in the image below.
2777 The default transform origin is \c Popup.Center.
2778
2779 \image qtquickcontrols-popup-transformorigin.png
2780 {Popup demonstrating transform origin points}
2781
2782 \sa enter, exit, Item::transformOrigin
2783*/
2784QQuickPopup::TransformOrigin QQuickPopup::transformOrigin() const
2785{
2786 Q_D(const QQuickPopup);
2787 return static_cast<TransformOrigin>(d->popupItem->transformOrigin());
2788}
2789
2790void QQuickPopup::setTransformOrigin(TransformOrigin origin)
2791{
2792 Q_D(QQuickPopup);
2793 d->popupItem->setTransformOrigin(static_cast<QQuickItem::TransformOrigin>(origin));
2794}
2795
2796/*!
2797 \qmlproperty Transition QtQuick.Controls::Popup::enter
2798
2799 This property holds the transition that is applied to the popup item
2800 when the popup is opened and enters the screen.
2801
2802 The following example animates the opacity of the popup when it enters
2803 the screen:
2804 \code
2805 Popup {
2806 enter: Transition {
2807 NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 }
2808 }
2809 }
2810 \endcode
2811
2812 \sa exit
2813*/
2814QQuickTransition *QQuickPopup::enter() const
2815{
2816 Q_D(const QQuickPopup);
2817 return d->enter;
2818}
2819
2820void QQuickPopup::setEnter(QQuickTransition *transition)
2821{
2822 Q_D(QQuickPopup);
2823 if (d->enter == transition)
2824 return;
2825 d->enter = transition;
2826 emit enterChanged();
2827}
2828
2829/*!
2830 \qmlproperty Transition QtQuick.Controls::Popup::exit
2831
2832 This property holds the transition that is applied to the popup item
2833 when the popup is closed and exits the screen.
2834
2835 The following example animates the opacity of the popup when it exits
2836 the screen:
2837 \code
2838 Popup {
2839 exit: Transition {
2840 NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 }
2841 }
2842 }
2843 \endcode
2844
2845 \sa enter
2846*/
2847QQuickTransition *QQuickPopup::exit() const
2848{
2849 Q_D(const QQuickPopup);
2850 return d->exit;
2851}
2852
2853void QQuickPopup::setExit(QQuickTransition *transition)
2854{
2855 Q_D(QQuickPopup);
2856 if (d->exit == transition)
2857 return;
2858 d->exit = transition;
2859 emit exitChanged();
2860}
2861
2862/*!
2863 \since QtQuick.Controls 2.5 (Qt 5.12)
2864 \qmlproperty real QtQuick.Controls::Popup::horizontalPadding
2865
2866 This property holds the horizontal padding. Unless explicitly set, the value
2867 is equal to \c padding.
2868
2869 \include qquickpopup-padding.qdocinc
2870
2871 \sa padding, leftPadding, rightPadding, verticalPadding
2872*/
2873qreal QQuickPopup::horizontalPadding() const
2874{
2875 Q_D(const QQuickPopup);
2876 return d->popupItem->horizontalPadding();
2877}
2878
2879void QQuickPopup::setHorizontalPadding(qreal padding)
2880{
2881 Q_D(QQuickPopup);
2882 d->popupItem->setHorizontalPadding(padding);
2883}
2884
2885void QQuickPopup::resetHorizontalPadding()
2886{
2887 Q_D(QQuickPopup);
2888 d->popupItem->resetHorizontalPadding();
2889}
2890
2891/*!
2892 \since QtQuick.Controls 2.5 (Qt 5.12)
2893 \qmlproperty real QtQuick.Controls::Popup::verticalPadding
2894
2895 This property holds the vertical padding. Unless explicitly set, the value
2896 is equal to \c padding.
2897
2898 \include qquickpopup-padding.qdocinc
2899
2900 \sa padding, topPadding, bottomPadding, horizontalPadding
2901*/
2902qreal QQuickPopup::verticalPadding() const
2903{
2904 Q_D(const QQuickPopup);
2905 return d->popupItem->verticalPadding();
2906}
2907
2908void QQuickPopup::setVerticalPadding(qreal padding)
2909{
2910 Q_D(QQuickPopup);
2911 d->popupItem->setVerticalPadding(padding);
2912}
2913
2914void QQuickPopup::resetVerticalPadding()
2915{
2916 Q_D(QQuickPopup);
2917 d->popupItem->resetVerticalPadding();
2918}
2919
2920/*!
2921 \since QtQuick.Controls 2.5 (Qt 5.12)
2922 \qmlproperty real QtQuick.Controls::Popup::implicitContentWidth
2923 \readonly
2924
2925 This property holds the implicit content width.
2926
2927 The value is calculated based on the content children.
2928
2929 \sa implicitContentHeight, implicitBackgroundWidth
2930*/
2931qreal QQuickPopup::implicitContentWidth() const
2932{
2933 Q_D(const QQuickPopup);
2934 return d->popupItem->implicitContentWidth();
2935}
2936
2937/*!
2938 \since QtQuick.Controls 2.5 (Qt 5.12)
2939 \qmlproperty real QtQuick.Controls::Popup::implicitContentHeight
2940 \readonly
2941
2942 This property holds the implicit content height.
2943
2944 The value is calculated based on the content children.
2945
2946 \sa implicitContentWidth, implicitBackgroundHeight
2947*/
2948qreal QQuickPopup::implicitContentHeight() const
2949{
2950 Q_D(const QQuickPopup);
2951 return d->popupItem->implicitContentHeight();
2952}
2953
2954/*!
2955 \since QtQuick.Controls 2.5 (Qt 5.12)
2956 \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundWidth
2957 \readonly
2958
2959 This property holds the implicit background width.
2960
2961 The value is equal to \c {background ? background.implicitWidth : 0}.
2962
2963 \sa implicitBackgroundHeight, implicitContentWidth
2964*/
2965qreal QQuickPopup::implicitBackgroundWidth() const
2966{
2967 Q_D(const QQuickPopup);
2968 return d->popupItem->implicitBackgroundWidth();
2969}
2970
2971/*!
2972 \since QtQuick.Controls 2.5 (Qt 5.12)
2973 \qmlproperty real QtQuick.Controls::Popup::implicitBackgroundHeight
2974 \readonly
2975
2976 This property holds the implicit background height.
2977
2978 The value is equal to \c {background ? background.implicitHeight : 0}.
2979
2980 \sa implicitBackgroundWidth, implicitContentHeight
2981*/
2982qreal QQuickPopup::implicitBackgroundHeight() const
2983{
2984 Q_D(const QQuickPopup);
2985 return d->popupItem->implicitBackgroundHeight();
2986}
2987
2988/*!
2989 \since QtQuick.Controls 2.5 (Qt 5.12)
2990 \qmlproperty real QtQuick.Controls::Popup::topInset
2991
2992 This property holds the top inset for the background.
2993
2994 \sa {Popup Layout}, bottomInset
2995*/
2996qreal QQuickPopup::topInset() const
2997{
2998 Q_D(const QQuickPopup);
2999 return d->popupItem->topInset();
3000}
3001
3002void QQuickPopup::setTopInset(qreal inset)
3003{
3004 Q_D(QQuickPopup);
3005 d->popupItem->setTopInset(inset);
3006}
3007
3008void QQuickPopup::resetTopInset()
3009{
3010 Q_D(QQuickPopup);
3011 d->popupItem->resetTopInset();
3012}
3013
3014/*!
3015 \since QtQuick.Controls 2.5 (Qt 5.12)
3016 \qmlproperty real QtQuick.Controls::Popup::leftInset
3017
3018 This property holds the left inset for the background.
3019
3020 \sa {Popup Layout}, rightInset
3021*/
3022qreal QQuickPopup::leftInset() const
3023{
3024 Q_D(const QQuickPopup);
3025 return d->popupItem->leftInset();
3026}
3027
3028void QQuickPopup::setLeftInset(qreal inset)
3029{
3030 Q_D(QQuickPopup);
3031 d->popupItem->setLeftInset(inset);
3032}
3033
3034void QQuickPopup::resetLeftInset()
3035{
3036 Q_D(QQuickPopup);
3037 d->popupItem->resetLeftInset();
3038}
3039
3040/*!
3041 \since QtQuick.Controls 2.5 (Qt 5.12)
3042 \qmlproperty real QtQuick.Controls::Popup::rightInset
3043
3044 This property holds the right inset for the background.
3045
3046 \sa {Popup Layout}, leftInset
3047*/
3048qreal QQuickPopup::rightInset() const
3049{
3050 Q_D(const QQuickPopup);
3051 return d->popupItem->rightInset();
3052}
3053
3054void QQuickPopup::setRightInset(qreal inset)
3055{
3056 Q_D(QQuickPopup);
3057 d->popupItem->setRightInset(inset);
3058}
3059
3060void QQuickPopup::resetRightInset()
3061{
3062 Q_D(QQuickPopup);
3063 d->popupItem->resetRightInset();
3064}
3065
3066/*!
3067 \since QtQuick.Controls 2.5 (Qt 5.12)
3068 \qmlproperty real QtQuick.Controls::Popup::bottomInset
3069
3070 This property holds the bottom inset for the background.
3071
3072 \sa {Popup Layout}, topInset
3073*/
3074qreal QQuickPopup::bottomInset() const
3075{
3076 Q_D(const QQuickPopup);
3077 return d->popupItem->bottomInset();
3078}
3079
3080void QQuickPopup::setBottomInset(qreal inset)
3081{
3082 Q_D(QQuickPopup);
3083 d->popupItem->setBottomInset(inset);
3084}
3085
3086void QQuickPopup::resetBottomInset()
3087{
3088 Q_D(QQuickPopup);
3089 d->popupItem->resetBottomInset();
3090}
3091
3092
3093/*!
3094 \qmlproperty enumeration QtQuick.Controls::Popup::popupType
3095 \since 6.8
3096
3097 This property determines the type of popup that is preferred.
3098
3099 Available options:
3100 \value Item The popup will be embedded into the
3101 \l{Showing a popup as an item}{same scene as the parent},
3102 without the use of a separate window.
3103 \value Window The popup will be presented in a \l {Popup type}
3104 {separate window}. If the platform doesn't support
3105 multiple windows, \c Popup.Item will be used instead.
3106 \value Native The popup will be native to the platform. If the
3107 platform doesn't support native popups, \c Popup.Window
3108 will be used instead.
3109
3110 Whether a popup will be able to use the preferred type depends on the platform.
3111 \c Popup.Item is supported on all platforms, but \c Popup.Window and \c Popup.Native
3112 are normally only supported on desktop platforms. Additionally, if a popup is a
3113 \l Menu inside a \l {Native menu bars}{native menubar}, the menu will be native as
3114 well. And if the menu is a sub-menu inside another menu, the parent (or root) menu
3115 will decide the type.
3116
3117 The default value is usually \c Popup.Item, with some exceptions, mentioned above.
3118 This might change in future versions of Qt, for certain styles and platforms that benefit
3119 from using other popup types.
3120 If you always want to use native menus for all styles on macOS, for example, you can do:
3121
3122 \code
3123 Menu {
3124 popupType: Qt.platform.os === "osx" ? Popup.Native : Popup.Window
3125 }
3126 \endcode
3127
3128 Also, if you choose to customize a popup (by for example changing any of the
3129 delegates), you should consider setting the popup type to be \c Popup.Window
3130 as well. This will ensure that your changes will be visible on all platforms
3131 and for all styles. Otherwise, when native menus are being used, the delegates
3132 will \e not be used for rendering.
3133
3134 \sa {Popup type}
3135*/
3136QQuickPopup::PopupType QQuickPopup::popupType() const
3137{
3138 Q_D(const QQuickPopup);
3139 return d->popupType;
3140}
3141
3142void QQuickPopup::setPopupType(PopupType popupType)
3143{
3144 Q_D(QQuickPopup);
3145 if (d->popupType == popupType)
3146 return;
3147
3148 d->popupType = popupType;
3149
3150 emit popupTypeChanged();
3151}
3152
3153/*!
3154 \since QtQuick.Controls 2.3 (Qt 5.10)
3155 \qmlproperty palette QtQuick.Controls::Popup::palette
3156
3157 This property holds the palette currently set for the popup.
3158
3159 Popup propagates explicit palette properties to its children. If you change a specific
3160 property on a popup's palette, that property propagates to all of the popup's children,
3161 overriding any system defaults for that property.
3162
3163 \code
3164 Popup {
3165 palette.text: "red"
3166
3167 Column {
3168 Label {
3169 text: qsTr("This will use red color...")
3170 }
3171
3172 Switch {
3173 text: qsTr("... and so will this")
3174 }
3175 }
3176 }
3177 \endcode
3178
3179 \b {See also}: \l Item::palette, \l Window::palette, \l ColorGroup,
3180 \l [QML] {Palette}
3181*/
3182
3183bool QQuickPopup::filtersChildMouseEvents() const
3184{
3185 Q_D(const QQuickPopup);
3186 return d->popupItem->filtersChildMouseEvents();
3187}
3188
3189void QQuickPopup::setFiltersChildMouseEvents(bool filter)
3190{
3191 Q_D(QQuickPopup);
3192 d->popupItem->setFiltersChildMouseEvents(filter);
3193}
3194
3195/*!
3196 \qmlmethod void QtQuick.Controls::Popup::forceActiveFocus(enumeration reason = Qt.OtherFocusReason)
3197
3198 Forces active focus on the popup with the given \a reason.
3199
3200 This method sets focus on the popup and ensures that all ancestor
3201 \l FocusScope objects in the object hierarchy are also given \l focus.
3202
3203 \sa activeFocus, Qt::FocusReason
3204*/
3205void QQuickPopup::forceActiveFocus(Qt::FocusReason reason)
3206{
3207 Q_D(QQuickPopup);
3208 d->popupItem->forceActiveFocus(reason);
3209}
3210
3211void QQuickPopup::classBegin()
3212{
3213 Q_D(QQuickPopup);
3214 d->complete = false;
3215 QQmlContext *context = qmlContext(this);
3216 if (context)
3217 QQmlEngine::setContextForObject(d->popupItem, context);
3218 d->popupItem->classBegin();
3219}
3220
3221void QQuickPopup::componentComplete()
3222{
3223 Q_D(QQuickPopup);
3224 qCDebug(lcQuickPopup) << "componentComplete" << this;
3225 if (!parentItem())
3226 resetParentItem();
3227
3228 d->complete = true;
3229 d->popupItem->setObjectName(QQmlMetaType::prettyTypeName(this));
3230 d->popupItem->componentComplete();
3231
3232 if (auto currentContentItem = d->popupItem->d_func()->contentItem.data()) {
3233 connect(currentContentItem, &QQuickItem::childrenChanged,
3234 this, &QQuickPopup::contentChildrenChanged);
3235 }
3236
3237 if (d->visible && d->window)
3238 openPopup(d);
3239}
3240
3241bool QQuickPopup::isComponentComplete() const
3242{
3243 Q_D(const QQuickPopup);
3244 return d->complete;
3245}
3246
3247bool QQuickPopup::childMouseEventFilter(QQuickItem *child, QEvent *event)
3248{
3249 Q_UNUSED(child);
3250 Q_UNUSED(event);
3251 return false;
3252}
3253
3254void QQuickPopup::focusInEvent(QFocusEvent *event)
3255{
3256 event->accept();
3257}
3258
3259void QQuickPopup::focusOutEvent(QFocusEvent *event)
3260{
3261 event->accept();
3262}
3263
3264void QQuickPopup::keyPressEvent(QKeyEvent *event)
3265{
3266 Q_D(QQuickPopup);
3267 if (!hasActiveFocus())
3268 return;
3269
3270#if QT_CONFIG(shortcut)
3271 if (d->closePolicy.testFlag(QQuickPopup::CloseOnEscape)
3272 && (event->matches(QKeySequence::Cancel)
3273#if defined(Q_OS_ANDROID)
3274 || event->key() == Qt::Key_Back
3275#endif
3276 )) {
3277 event->accept();
3278 if (d->interactive)
3279 d->closeOrReject();
3280 return;
3281 }
3282#endif
3283
3284 if (hasActiveFocus() && (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab)) {
3285 event->accept();
3286 QQuickItemPrivate::focusNextPrev(d->popupItem, event->key() == Qt::Key_Tab);
3287 }
3288}
3289
3290void QQuickPopup::keyReleaseEvent(QKeyEvent *event)
3291{
3292 event->accept();
3293}
3294
3295void QQuickPopup::mousePressEvent(QMouseEvent *event)
3296{
3297 Q_D(QQuickPopup);
3298 event->setAccepted(d->handleMouseEvent(d->popupItem, event));
3299}
3300
3301void QQuickPopup::mouseMoveEvent(QMouseEvent *event)
3302{
3303 Q_D(QQuickPopup);
3304 event->setAccepted(d->handleMouseEvent(d->popupItem, event));
3305}
3306
3307void QQuickPopup::mouseReleaseEvent(QMouseEvent *event)
3308{
3309 Q_D(QQuickPopup);
3310 event->setAccepted(d->handleMouseEvent(d->popupItem, event));
3311}
3312
3313void QQuickPopup::mouseDoubleClickEvent(QMouseEvent *event)
3314{
3315 event->accept();
3316}
3317
3318void QQuickPopup::mouseUngrabEvent()
3319{
3320 Q_D(QQuickPopup);
3321 d->handleUngrab();
3322}
3323
3324
3325/*!
3326 \internal
3327
3328 Called whenever the window receives a Wheel/Hover/Mouse/Touch/Tablet event,
3329 and has an active popup (with popupType: Popup.Item) in its scene.
3330
3331 The purpose is to close popups when the press/release event happened outside of it,
3332 and the closePolicy allows for it to happen.
3333
3334 If the function is called from childMouseEventFilter, then the return value of this
3335 function will determine whether the event will be filtered, or delivered to \a item.
3336*/
3337bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event)
3338{
3339 Q_D(QQuickPopup);
3340
3341 // The overlay will normally call this function for each active popup, assuming there is no active mouse grabber.
3342 // If \a item doesn't belong to any of these popups, but exists in an overlay subtree, we shouldn't filter the event,
3343 // since the item is supposed to be independent of any active popups.
3344 if (d->belongsToOverlayChildAbove(item))
3345 return false;
3346
3347 switch (event->type()) {
3348 case QEvent::KeyPress:
3349 case QEvent::KeyRelease:
3350 case QEvent::MouseMove:
3351 case QEvent::Wheel:
3352 if (d->modal)
3353 event->accept();
3354 return d->modal;
3355 case QEvent::DragEnter:
3356 case QEvent::DragMove:
3357 case QEvent::DragLeave:
3358 case QEvent::Drop:
3359 // ignore() so that the OS sees Qt::IgnoreAction and renders the "not allowed" cursor
3360 // within the drag image. accept() would only change the window cursor after the drag ends: too late.
3361 if (d->modal)
3362 event->ignore();
3363 return d->modal;
3364#if QT_CONFIG(tabletevent)
3365 case QEvent::TabletPress:
3366 case QEvent::TabletMove:
3367 case QEvent::TabletRelease:
3368 if (d->modal)
3369 event->accept();
3370 return d->modal;
3371#endif
3372#if QT_CONFIG(quicktemplates2_multitouch)
3373 case QEvent::TouchBegin:
3374 case QEvent::TouchUpdate:
3375 case QEvent::TouchEnd:
3376 return d->handleTouchEvent(item, static_cast<QTouchEvent *>(event));
3377#endif
3378 case QEvent::HoverEnter:
3379 case QEvent::HoverMove:
3380 case QEvent::HoverLeave:
3381 return d->handleHoverEvent(item, static_cast<QHoverEvent *>(event));
3382
3383 case QEvent::MouseButtonPress:
3384 case QEvent::MouseButtonRelease:
3385 return d->handleMouseEvent(item, static_cast<QMouseEvent *>(event));
3386
3387 default:
3388 return false;
3389 }
3390}
3391
3392#if QT_CONFIG(quicktemplates2_multitouch)
3393void QQuickPopup::touchEvent(QTouchEvent *event)
3394{
3395 Q_D(QQuickPopup);
3396 event->setAccepted(d->handleTouchEvent(d->popupItem, event));
3397}
3398
3399void QQuickPopup::touchUngrabEvent()
3400{
3401 Q_D(QQuickPopup);
3402 d->handleUngrab();
3403}
3404#endif
3405
3406#if QT_CONFIG(wheelevent)
3407void QQuickPopup::wheelEvent(QWheelEvent *event)
3408{
3409 event->accept();
3410}
3411#endif
3412
3413#if QT_CONFIG(quick_draganddrop)
3414void QQuickPopup::dragMoveEvent(QDragMoveEvent *event)
3415{
3416 event->accept();
3417}
3418
3419void QQuickPopup::dragLeaveEvent(QDragLeaveEvent *event)
3420{
3421 event->accept();
3422}
3423
3424void QQuickPopup::dropEvent(QDropEvent *event)
3425{
3426 event->accept();
3427}
3428
3429void QQuickPopup::dragEnterEvent(QDragEnterEvent *event)
3430{
3431 event->ignore(); // OS shows "forbidden" cursor as part of drag image
3432}
3433#endif
3434
3435void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
3436{
3437 Q_UNUSED(newItem);
3438 Q_UNUSED(oldItem);
3439}
3440
3441void QQuickPopup::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
3442{
3443 qCDebug(lcQuickPopup) << "contentSizeChange called on" << this << "with newSize" << newSize << "oldSize" << oldSize;
3444 if (!qFuzzyCompare(newSize.width(), oldSize.width()))
3445 emit contentWidthChanged();
3446 if (!qFuzzyCompare(newSize.height(), oldSize.height()))
3447 emit contentHeightChanged();
3448}
3449
3450void QQuickPopup::fontChange(const QFont &newFont, const QFont &oldFont)
3451{
3452 Q_UNUSED(newFont);
3453 Q_UNUSED(oldFont);
3454 emit fontChanged();
3455}
3456
3457void QQuickPopup::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3458{
3459 Q_D(QQuickPopup);
3460 qCDebug(lcQuickPopup) << "geometryChange called on" << this << "with newGeometry" << newGeometry << "oldGeometry" << oldGeometry;
3461 if (!d->usePopupWindow())
3462 d->reposition();
3463 if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) {
3464 emit widthChanged();
3465 emit availableWidthChanged();
3466 }
3467 if (!qFuzzyCompare(newGeometry.height(), oldGeometry.height())) {
3468 emit heightChanged();
3469 emit availableHeightChanged();
3470 }
3471}
3472
3473void QQuickPopup::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &)
3474{
3475 switch (change) {
3476 case QQuickItem::ItemActiveFocusHasChanged:
3477 emit activeFocusChanged();
3478 break;
3479 case QQuickItem::ItemOpacityHasChanged:
3480 emit opacityChanged();
3481 break;
3482 default:
3483 break;
3484 }
3485}
3486
3487void QQuickPopup::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
3488{
3489 Q_UNUSED(newLocale);
3490 Q_UNUSED(oldLocale);
3491 emit localeChanged();
3492}
3493
3494void QQuickPopup::marginsChange(const QMarginsF &newMargins, const QMarginsF &oldMargins)
3495{
3496 Q_D(QQuickPopup);
3497 Q_UNUSED(newMargins);
3498 Q_UNUSED(oldMargins);
3499 d->reposition();
3500}
3501
3502void QQuickPopup::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
3503{
3504 const bool tp = !qFuzzyCompare(newPadding.top(), oldPadding.top());
3505 const bool lp = !qFuzzyCompare(newPadding.left(), oldPadding.left());
3506 const bool rp = !qFuzzyCompare(newPadding.right(), oldPadding.right());
3507 const bool bp = !qFuzzyCompare(newPadding.bottom(), oldPadding.bottom());
3508
3509 if (tp)
3510 emit topPaddingChanged();
3511 if (lp)
3512 emit leftPaddingChanged();
3513 if (rp)
3514 emit rightPaddingChanged();
3515 if (bp)
3516 emit bottomPaddingChanged();
3517
3518 if (lp || rp) {
3519 emit horizontalPaddingChanged();
3520 emit availableWidthChanged();
3521 }
3522 if (tp || bp) {
3523 emit verticalPaddingChanged();
3524 emit availableHeightChanged();
3525 }
3526}
3527
3528void QQuickPopup::spacingChange(qreal newSpacing, qreal oldSpacing)
3529{
3530 Q_UNUSED(newSpacing);
3531 Q_UNUSED(oldSpacing);
3532 emit spacingChanged();
3533}
3534
3535void QQuickPopup::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
3536{
3537 if (!qFuzzyCompare(newInset.top(), oldInset.top()))
3538 emit topInsetChanged();
3539 if (!qFuzzyCompare(newInset.left(), oldInset.left()))
3540 emit leftInsetChanged();
3541 if (!qFuzzyCompare(newInset.right(), oldInset.right()))
3542 emit rightInsetChanged();
3543 if (!qFuzzyCompare(newInset.bottom(), oldInset.bottom()))
3544 emit bottomInsetChanged();
3545}
3546
3547QFont QQuickPopup::defaultFont() const
3548{
3549 return QQuickTheme::font(QQuickTheme::System);
3550}
3551
3552#if QT_CONFIG(accessibility)
3553QAccessible::Role QQuickPopup::effectiveAccessibleRole() const
3554{
3555 auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(this, false);
3556
3557 auto role = QAccessible::NoRole;
3558 if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(attached))
3559 role = accessibleAttached->role();
3560 if (role == QAccessible::NoRole)
3561 role = accessibleRole();
3562
3563 return role;
3564}
3565
3566QAccessible::Role QQuickPopup::accessibleRole() const
3567{
3568 return QAccessible::Dialog;
3569}
3570
3571void QQuickPopup::accessibilityActiveChanged(bool active)
3572{
3573 Q_UNUSED(active);
3574}
3575#endif
3576
3577QString QQuickPopup::accessibleName() const
3578{
3579 Q_D(const QQuickPopup);
3580 return d->popupItem->accessibleName();
3581}
3582
3583void QQuickPopup::maybeSetAccessibleName(const QString &name)
3584{
3585 Q_D(QQuickPopup);
3586 d->popupItem->maybeSetAccessibleName(name);
3587}
3588
3589QVariant QQuickPopup::accessibleProperty(const char *propertyName)
3590{
3591 Q_D(const QQuickPopup);
3592 return d->popupItem->accessibleProperty(propertyName);
3593}
3594
3595bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant &value)
3596{
3597 Q_D(QQuickPopup);
3598 return d->popupItem->setAccessibleProperty(propertyName, value);
3599}
3600
3601void QQuickPopup::setWindowModality(const Qt::WindowModality modality)
3602{
3603 Q_D(QQuickPopup);
3604 d->popupWndModality = modality;
3605}
3606
3607QQuickItem *QQuickPopup::safeAreaAttachmentItem()
3608{
3609 return popupItem();
3610}
3611
3612QQuickItem *QQuickPopup::attacheeItem() const
3613{
3614 return popupItem();
3615}
3616
3617QtPrivate::QQuickAttachedPropertyPropagator *QQuickPopup::attachedParent(
3618 const QMetaObject *ourAttachedType) const
3619{
3620 auto *popupWindow = popupItem()->window();
3621 qCDebug(lcAttachedPropertyPropagator).noquote() << "- attachee is a popup; checking its window"
3622 << popupWindow;
3623 auto *object = QtPrivate::QQuickAttachedPropertyPropagator::attachedObject(
3624 ourAttachedType, popupWindow);
3625 if (object)
3626 return object;
3627
3628 if (qobject_cast<QQuickPopupWindow *>(popupWindow)) {
3629 qCDebug(lcAttachedPropertyPropagator).noquote() << "- checking its window's transientParent"
3630 << popupWindow->transientParent();
3631 return QtPrivate::QQuickAttachedPropertyPropagator::attachedObject(ourAttachedType,
3632 popupWindow->transientParent());
3633 }
3634
3635 return {};
3636}
3637
3638QT_END_NAMESPACE
3639
3640#include "qquickpopup.moc"
3641#include "moc_qquickpopup_p.cpp"
Combined button and popup list for selecting options.
static std::unique_ptr< QWindowExposedObserver, ObserverDeleter > s_windowExposedObserver
static QQuickItem * findRootOfOverlaySubtree(QQuickItem *source, const QQuickOverlay *overlay)
void openPopup(QQuickPopupPrivate *d)
void operator()(QWindowExposedObserver *observer)