diff options
26 files changed, 416 insertions, 43 deletions
diff --git a/examples/quickcontrols2/gallery/pages/DialogPage.qml b/examples/quickcontrols2/gallery/pages/DialogPage.qml index daaa7329..8bade21f 100644 --- a/examples/quickcontrols2/gallery/pages/DialogPage.qml +++ b/examples/quickcontrols2/gallery/pages/DialogPage.qml @@ -50,7 +50,7 @@ import QtQuick 2.6 import QtQuick.Layouts 1.0 -import QtQuick.Controls 2.1 +import QtQuick.Controls 2.3 ScrollablePage { id: page @@ -101,7 +101,7 @@ ScrollablePage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 - parent: ApplicationWindow.overlay + parent: Overlay.overlay modal: true title: "Confirmation" @@ -134,7 +134,7 @@ ScrollablePage { y: (parent.height - height) / 2 width: Math.min(page.width, page.height) / 3 * 2 contentHeight: logo.height * 2 - parent: ApplicationWindow.overlay + parent: Overlay.overlay modal: true title: "Content" @@ -194,7 +194,7 @@ ScrollablePage { x: (parent.width - width) / 2 y: (parent.height - height) / 2 - parent: ApplicationWindow.overlay + parent: Overlay.overlay focus: true modal: true diff --git a/src/imports/controls/Dialog.qml b/src/imports/controls/Dialog.qml index f2ebae34..28266670 100644 --- a/src/imports/controls/Dialog.qml +++ b/src/imports/controls/Dialog.qml @@ -76,4 +76,12 @@ T.Dialog { footer: DialogButtonBox { visible: count > 0 } + + T.Overlay.modal: Rectangle { + color: Default.overlayModalColor + } + + T.Overlay.modeless: Rectangle { + color: Default.overlayDimColor + } } diff --git a/src/imports/controls/Drawer.qml b/src/imports/controls/Drawer.qml index 8368838a..e21de5b4 100644 --- a/src/imports/controls/Drawer.qml +++ b/src/imports/controls/Drawer.qml @@ -42,7 +42,7 @@ import QtQuick.Templates 2.3 as T T.Drawer { id: control - parent: T.ApplicationWindow.overlay + parent: T.Overlay.overlay implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) @@ -68,4 +68,12 @@ T.Drawer { y: control.edge === Qt.TopEdge ? parent.height - 1 : 0 } } + + T.Overlay.modal: Rectangle { + color: Default.overlayModalColor + } + + T.Overlay.modeless: Rectangle { + color: Default.overlayDimColor + } } diff --git a/src/imports/controls/Menu.qml b/src/imports/controls/Menu.qml index 32cbfa3f..03503e0a 100644 --- a/src/imports/controls/Menu.qml +++ b/src/imports/controls/Menu.qml @@ -69,4 +69,12 @@ T.Menu { color: Default.backgroundColor border.color: Default.frameDarkColor } + + T.Overlay.modal: Rectangle { + color: Default.overlayModalColor + } + + T.Overlay.modeless: Rectangle { + color: Default.overlayDimColor + } } diff --git a/src/imports/controls/Popup.qml b/src/imports/controls/Popup.qml index 7a94aaab..58799744 100644 --- a/src/imports/controls/Popup.qml +++ b/src/imports/controls/Popup.qml @@ -55,4 +55,12 @@ T.Popup { background: Rectangle { border.color: Default.frameDarkColor } + + T.Overlay.modal: Rectangle { + color: Default.overlayModalColor + } + + T.Overlay.modeless: Rectangle { + color: Default.overlayDimColor + } } diff --git a/src/imports/controls/fusion/Dialog.qml b/src/imports/controls/fusion/Dialog.qml index a0c9ef18..b79b9254 100644 --- a/src/imports/controls/fusion/Dialog.qml +++ b/src/imports/controls/fusion/Dialog.qml @@ -92,4 +92,12 @@ T.Dialog { footer: DialogButtonBox { visible: count > 0 } + + T.Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + T.Overlay.modeless: Rectangle { + color: Fusion.topShadow + } } diff --git a/src/imports/controls/fusion/Drawer.qml b/src/imports/controls/fusion/Drawer.qml index 4115ec06..236c359a 100644 --- a/src/imports/controls/fusion/Drawer.qml +++ b/src/imports/controls/fusion/Drawer.qml @@ -44,7 +44,7 @@ import QtQuick.Controls.Fusion.impl 2.3 T.Drawer { id: control - parent: T.ApplicationWindow.overlay + parent: T.Overlay.overlay implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) @@ -79,4 +79,12 @@ T.Drawer { y: control.edge === Qt.TopEdge ? parent.height : 0 } } + + T.Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + T.Overlay.modeless: Rectangle { + color: Fusion.topShadow + } } diff --git a/src/imports/controls/fusion/Menu.qml b/src/imports/controls/fusion/Menu.qml index 06886ad7..fe82e0e7 100644 --- a/src/imports/controls/fusion/Menu.qml +++ b/src/imports/controls/fusion/Menu.qml @@ -82,4 +82,12 @@ T.Menu { opacity: 0.2 } } + + T.Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + T.Overlay.modeless: Rectangle { + color: Fusion.topShadow + } } diff --git a/src/imports/controls/fusion/Popup.qml b/src/imports/controls/fusion/Popup.qml index 64c9fe49..30532e7e 100644 --- a/src/imports/controls/fusion/Popup.qml +++ b/src/imports/controls/fusion/Popup.qml @@ -59,4 +59,12 @@ T.Popup { border.color: control.palette.mid radius: 2 } + + T.Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + T.Overlay.modeless: Rectangle { + color: Fusion.topShadow + } } diff --git a/src/imports/controls/material/Dialog.qml b/src/imports/controls/material/Dialog.qml index 68f856c6..abad5662 100644 --- a/src/imports/controls/material/Dialog.qml +++ b/src/imports/controls/material/Dialog.qml @@ -103,4 +103,14 @@ T.Dialog { footer: DialogButtonBox { visible: count > 0 } + + T.Overlay.modal: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + T.Overlay.modeless: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } } diff --git a/src/imports/controls/material/Drawer.qml b/src/imports/controls/material/Drawer.qml index 78b6f2b8..7ea52b46 100644 --- a/src/imports/controls/material/Drawer.qml +++ b/src/imports/controls/material/Drawer.qml @@ -42,7 +42,7 @@ import QtQuick.Controls.Material.impl 2.3 T.Drawer { id: control - parent: T.ApplicationWindow.overlay + parent: T.Overlay.overlay implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) @@ -79,4 +79,14 @@ T.Drawer { fullHeight: true } } + + T.Overlay.modal: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + T.Overlay.modeless: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } } diff --git a/src/imports/controls/material/Menu.qml b/src/imports/controls/material/Menu.qml index 8410dfeb..9c8128a7 100644 --- a/src/imports/controls/material/Menu.qml +++ b/src/imports/controls/material/Menu.qml @@ -94,4 +94,14 @@ T.Menu { elevation: control.Material.elevation } } + + T.Overlay.modal: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + T.Overlay.modeless: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } } diff --git a/src/imports/controls/material/Popup.qml b/src/imports/controls/material/Popup.qml index 49b39a6c..e22b8b7c 100644 --- a/src/imports/controls/material/Popup.qml +++ b/src/imports/controls/material/Popup.qml @@ -75,4 +75,14 @@ T.Popup { elevation: control.Material.elevation } } + + T.Overlay.modal: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + T.Overlay.modeless: Rectangle { + color: control.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } } diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index f9ee88d8..7a1651e4 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -48,6 +48,7 @@ #if QT_CONFIG(quick_listview) && QT_CONFIG(quick_pathview) #include <QtQuickControls2/private/qquicktumblerview_p.h> #endif +#include <QtQuickTemplates2/private/qquickoverlay_p.h> #include "qquickdefaultbusyindicator_p.h" #include "qquickdefaultdial_p.h" @@ -157,6 +158,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) // QtQuick.Controls 2.3 (new types in Qt 5.10) qmlRegisterType(selector.select(QStringLiteral("Action.qml")), uri, 2, 3, "Action"); qmlRegisterType(selector.select(QStringLiteral("ActionGroup.qml")), uri, 2, 3, "ActionGroup"); + qmlRegisterUncreatableType<QQuickOverlay>(uri, 2, 3, "Overlay", QStringLiteral("Overlay is only available as an attached property.")); } static QObject *styleSingleton(QQmlEngine *engine, QJSEngine *scriptEngine) diff --git a/src/imports/controls/universal/Dialog.qml b/src/imports/controls/universal/Dialog.qml index 4f8a6180..dd463b83 100644 --- a/src/imports/controls/universal/Dialog.qml +++ b/src/imports/controls/universal/Dialog.qml @@ -84,4 +84,12 @@ T.Dialog { footer: DialogButtonBox { visible: count > 0 } + + T.Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + T.Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } } diff --git a/src/imports/controls/universal/Drawer.qml b/src/imports/controls/universal/Drawer.qml index 5ef0b325..40cfaadd 100644 --- a/src/imports/controls/universal/Drawer.qml +++ b/src/imports/controls/universal/Drawer.qml @@ -41,7 +41,7 @@ import QtQuick.Controls.Universal 2.3 T.Drawer { id: control - parent: T.ApplicationWindow.overlay + parent: T.Overlay.overlay implicitWidth: Math.max(background ? background.implicitWidth : 0, contentWidth + leftPadding + rightPadding) implicitHeight: Math.max(background ? background.implicitHeight : 0, contentHeight + topPadding + bottomPadding) @@ -68,4 +68,12 @@ T.Drawer { y: control.edge === Qt.TopEdge ? parent.height - 1 : 0 } } + + T.Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + T.Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } } diff --git a/src/imports/controls/universal/Menu.qml b/src/imports/controls/universal/Menu.qml index 8ffefb1b..8b69051f 100644 --- a/src/imports/controls/universal/Menu.qml +++ b/src/imports/controls/universal/Menu.qml @@ -70,4 +70,12 @@ T.Menu { border.color: control.Universal.chromeHighColor border.width: 1 // FlyoutBorderThemeThickness } + + T.Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + T.Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } } diff --git a/src/imports/controls/universal/Popup.qml b/src/imports/controls/universal/Popup.qml index f844d8e1..e44e953c 100644 --- a/src/imports/controls/universal/Popup.qml +++ b/src/imports/controls/universal/Popup.qml @@ -56,4 +56,12 @@ T.Popup { border.color: control.Universal.chromeHighColor border.width: 1 // FlyoutBorderThemeThickness } + + T.Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + T.Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } } diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index e7e08e32..2ce655c3 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -301,6 +301,8 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) qRegisterMetaType<QQuickIcon>(); qmlRegisterType<QQuickMenu, 3>(uri, 2, 3, "Menu"); qmlRegisterType<QQuickMenuItem, 3>(uri, 2, 3, "MenuItem"); + qmlRegisterUncreatableType<QQuickOverlay>(uri, 2, 3, "Overlay", QStringLiteral("Overlay is only available as an attached property.")); + qmlRegisterType<QQuickOverlayAttached>(); qmlRegisterType<QQuickPopup, 3>(uri, 2, 3, "Popup"); qmlRegisterType<QQuickRangeSlider, 3>(uri, 2, 3, "RangeSlider"); qmlRegisterType<QQuickScrollBar, 3>(uri, 2, 3, "ScrollBar"); diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 9311958e..cee38b23 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -88,11 +88,6 @@ QT_BEGIN_NAMESPACE } \endqml - ApplicationWindow supports popups via its \l overlay property, which - ensures that popups are displayed above other content and that the - background is dimmed when a \l {Popup::}{modal} or \l {Popup::dim} - {dimmed} popup is visible. - \note By default, an ApplicationWindow is not visible. \section2 Attached ApplicationWindow Properties @@ -107,29 +102,9 @@ QT_BEGIN_NAMESPACE to access the window and its building blocks from places where no direct access to the window is available, without creating a dependency to a certain window \c id. A QML component that uses the ApplicationWindow - attached properties works in any window regardless of its \c id. The - following example uses the attached \c overlay property to position the - popup to the center of the window, despite the position of the button - that opens the popup. - - \code - Button { - onClicked: popup.open() + attached properties works in any window regardless of its \c id. - Popup { - id: popup - - parent: ApplicationWindow.overlay - - x: (parent.width - width) / 2 - y: (parent.height - height) / 2 - width: 100 - height: 100 - } - } - \endcode - - \sa {Customizing ApplicationWindow}, Page, {Container Controls} + \sa {Customizing ApplicationWindow}, Overlay, Page, {Container Controls} */ class QQuickApplicationWindowPrivate : public QQuickItemChangeListener @@ -378,7 +353,7 @@ QQuickApplicationWindow::~QQuickApplicationWindow() follows the control's size. In most cases, there is no need to specify width or height for a background item. - \sa {Customizing ApplicationWindow}, contentItem, header, footer, overlay + \sa {Customizing ApplicationWindow}, contentItem, header, footer */ QQuickItem *QQuickApplicationWindow::background() const { @@ -554,9 +529,9 @@ QQmlListProperty<QObject> QQuickApplicationWindow::contentData() This property holds the window content item. The content item is stacked above the \l background item, and under the - \l header, \l footer, and \l overlay items. + \l header, and \l footer items. - \sa background, header, footer, overlay + \sa background, header, footer */ QQuickItem *QQuickApplicationWindow::contentItem() const { @@ -591,11 +566,14 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const } /*! + \deprecated \qmlpropertygroup QtQuick.Controls::ApplicationWindow::overlay \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay \qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modal \qmlproperty Component QtQuick.Controls::ApplicationWindow::overlay.modeless + Use the \l Overlay attached properties and signals instead. + This property holds the window overlay item. Popups are automatically reparented to the overlay. @@ -976,9 +954,12 @@ QQuickItem *QQuickApplicationWindowAttached::footer() const } /*! + \deprecated \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::overlay \readonly + Use the \l Overlay::overlay attached property instead. + This attached property holds the window overlay item. The property can be attached to any item. The value is \c null if the item is not in an ApplicationWindow. diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index 8ea97069..12158f06 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -47,6 +47,43 @@ QT_BEGIN_NAMESPACE +/*! + \qmltype Overlay + \inherits Item + \instantiates QQuickOverlay + \inqmlmodule QtQuick.Controls + \since 5.10 + \brief A window overlay for popups. + + Overlay provides a layer for popups, ensuring that popups are displayed above + other content and that the background is dimmed when a \l {Popup::}{modal} or + \l {Popup::dim}{dimmed} popup is visible. + + The overlay is an ordinary Item that covers the entire window. It can be used + as a visual parent to position a popup in scene coordinates. The following + example uses the attached \c overlay property to position a popup to the center + of the window, despite the position of the button that opens the popup. + + \code + Button { + onClicked: popup.open() + + Popup { + id: popup + + parent: Overlay.overlay + + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: 100 + height: 100 + } + } + \endcode + + \sa ApplicationWindow +*/ + QVector<QQuickPopup *> QQuickOverlayPrivate::stackingOrderPopups() const { const QList<QQuickItem *> children = paintOrderChildItems(); @@ -321,6 +358,11 @@ QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window) return overlay; } +QQuickOverlayAttached *QQuickOverlay::qmlAttachedProperties(QObject *object) +{ + return new QQuickOverlayAttached(object); +} + void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data) { Q_D(QQuickOverlay); @@ -490,4 +532,149 @@ bool QQuickOverlay::eventFilter(QObject *object, QEvent *event) return false; } +class QQuickOverlayAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickOverlayAttached) + +public: + QQuickOverlayAttachedPrivate() + : window(nullptr), + modal(nullptr), + modeless(nullptr) + { + } + + void setWindow(QQuickWindow *newWindow); + + QQuickWindow *window; + QQmlComponent *modal; + QQmlComponent *modeless; +}; + +void QQuickOverlayAttachedPrivate::setWindow(QQuickWindow *newWindow) +{ + Q_Q(QQuickOverlayAttached); + if (window == newWindow) + return; + + if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) { + QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed); + QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released); + } + + if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow)) { + QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed); + QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released); + } + + window = newWindow; + emit q->overlayChanged(); +} + +/*! + \qmlattachedsignal QtQuick.Controls::Overlay::pressed() + + This attached signal is emitted when the overlay is pressed by the user while + a popup is visible. + + The signal can be attached to any item, popup, or window. When attached to an + item or a popup, the signal is only emitted if the item or popup is in a window. +*/ + +/*! + \qmlattachedsignal QtQuick.Controls::Overlay::released() + + This attached signal is emitted when the overlay is released by the user while + a popup is visible. + + The signal can be attached to any item, popup, or window. When attached to an + item or a popup, the signal is only emitted if the item or popup is in a window. +*/ + +QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent) + : QObject(*(new QQuickOverlayAttachedPrivate), parent) +{ + Q_D(QQuickOverlayAttached); + if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) { + d->setWindow(item->window()); + QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow); + } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) { + d->setWindow(popup->window()); + QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow); + } else { + d->setWindow(qobject_cast<QQuickWindow *>(parent)); + } +} + +/*! + \qmlattachedproperty Overlay QtQuick.Controls::Overlay::overlay + \readonly + + This attached property holds the window overlay item. + + The property can be attached to any item, popup, or window. When attached to an + item or a popup, the value is \c null if the item or popup is not in a window. +*/ +QQuickOverlay *QQuickOverlayAttached::overlay() const +{ + Q_D(const QQuickOverlayAttached); + return QQuickOverlay::overlay(d->window); +} + +/*! + \qmlattachedproperty Component QtQuick.Controls::Overlay::modal + + This attached property holds a component to use as a visual item that implements + background dimming for modal popups. It is created for and stacked below visible + modal popups. + + The property can be attached to any popup. + + \sa Popup::modal +*/ +QQmlComponent *QQuickOverlayAttached::modal() const +{ + Q_D(const QQuickOverlayAttached); + return d->modal; +} + +void QQuickOverlayAttached::setModal(QQmlComponent *modal) +{ + Q_D(QQuickOverlayAttached); + if (d->modal == modal) + return; + + delete d->modal; + d->modal = modal; + emit modalChanged(); +} + +/*! + \qmlattachedproperty Component QtQuick.Controls::Overlay::modeless + + This attached property holds a component to use as a visual item that implements + background dimming for modeless popups. It is created for and stacked below visible + dimming popups. + + The property can be attached to any popup. + + \sa Popup::dim +*/ +QQmlComponent *QQuickOverlayAttached::modeless() const +{ + Q_D(const QQuickOverlayAttached); + return d->modeless; +} + +void QQuickOverlayAttached::setModeless(QQmlComponent *modeless) +{ + Q_D(QQuickOverlayAttached); + if (d->modeless == modeless) + return; + + delete d->modeless; + d->modeless = modeless; + emit modelessChanged(); +} + QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h index ba61c9c9..0d8bccf5 100644 --- a/src/quicktemplates2/qquickoverlay_p.h +++ b/src/quicktemplates2/qquickoverlay_p.h @@ -55,6 +55,8 @@ QT_BEGIN_NAMESPACE class QQmlComponent; class QQuickOverlayPrivate; +class QQuickOverlayAttached; +class QQuickOverlayAttachedPrivate; class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickOverlay : public QQuickItem { @@ -74,6 +76,8 @@ public: static QQuickOverlay *overlay(QQuickWindow *window); + static QQuickOverlayAttached *qmlAttachedProperties(QObject *object); + Q_SIGNALS: void modalChanged(); void modelessChanged(); @@ -101,8 +105,39 @@ private: Q_DECLARE_PRIVATE(QQuickOverlay) }; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickOverlayAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickOverlay *overlay READ overlay NOTIFY overlayChanged FINAL) + Q_PROPERTY(QQmlComponent *modal READ modal WRITE setModal NOTIFY modalChanged FINAL) + Q_PROPERTY(QQmlComponent *modeless READ modeless WRITE setModeless NOTIFY modelessChanged FINAL) + +public: + explicit QQuickOverlayAttached(QObject *parent = nullptr); + + QQuickOverlay *overlay() const; + + QQmlComponent *modal() const; + void setModal(QQmlComponent *modal); + + QQmlComponent *modeless() const; + void setModeless(QQmlComponent *modeless); + +Q_SIGNALS: + void overlayChanged(); + void modalChanged(); + void modelessChanged(); + void pressed(); + void released(); + +private: + Q_DISABLE_COPY(QQuickOverlayAttached) + Q_DECLARE_PRIVATE(QQuickOverlayAttached) +}; + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickOverlay) +QML_DECLARE_TYPEINFO(QQuickOverlay, QML_HAS_ATTACHED_PROPERTIES) #endif // QQUICKOVERLAY_P_H diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 1ccd1040..38ca6edf 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -655,8 +655,16 @@ void QQuickPopupPrivate::createOverlay() if (!overlay) return; + QQmlComponent *component = nullptr; + QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(qmlAttachedPropertiesObject<QQuickOverlay>(q, false)); + if (overlayAttached) + component = modal ? overlayAttached->modal() : overlayAttached->modeless(); + + if (!component) + component = modal ? overlay->modal() : overlay->modeless(); + if (!dimmer) - dimmer = createDimmer(modal ? overlay->modal() : overlay->modeless(), q, overlay); + dimmer = createDimmer(component, q, overlay); resizeOverlay(); } diff --git a/tests/auto/controls/data/tst_drawer.qml b/tests/auto/controls/data/tst_drawer.qml index 11a57e2f..617e7677 100644 --- a/tests/auto/controls/data/tst_drawer.qml +++ b/tests/auto/controls/data/tst_drawer.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtTest 1.0 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 TestCase { id: testCase @@ -70,7 +70,7 @@ TestCase { compare(control.edge, Qt.LeftEdge) compare(control.position, 0.0) compare(control.dragMargin, Qt.styleHints.startDragDistance) - compare(control.parent, ApplicationWindow.overlay) + compare(control.parent, Overlay.overlay) } Component { diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index c8b3985c..296d026d 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -50,8 +50,8 @@ import QtQuick 2.4 import QtTest 1.0 -import QtQuick.Controls 2.2 -import QtQuick.Templates 2.2 as T +import QtQuick.Controls 2.3 +import QtQuick.Templates 2.3 as T TestCase { id: testCase @@ -1069,6 +1069,7 @@ TestCase { tryCompare(window, "active", true) compare(window.overlay.children.length, 0) + compare(window.overlay, window.Overlay.overlay) var firstOverlay = findOverlay(window, window.firstDrawer) verify(!firstOverlay) diff --git a/tests/auto/popup/tst_popup.cpp b/tests/auto/popup/tst_popup.cpp index 0193b769..48295e10 100644 --- a/tests/auto/popup/tst_popup.cpp +++ b/tests/auto/popup/tst_popup.cpp @@ -216,6 +216,15 @@ void tst_popup::overlay() QQuickPopup *popup = window->property("popup").value<QQuickPopup*>(); QVERIFY(popup); + QQuickOverlayAttached *overlayAttached = qobject_cast<QQuickOverlayAttached *>(qmlAttachedPropertiesObject<QQuickOverlay>(popup)); + QVERIFY(overlayAttached); + QCOMPARE(overlayAttached->overlay(), overlay); + + QSignalSpy overlayAttachedPressedSignal(overlayAttached, SIGNAL(pressed())); + QSignalSpy overlayAttachedReleasedSignal(overlayAttached, SIGNAL(released())); + QVERIFY(overlayAttachedPressedSignal.isValid()); + QVERIFY(overlayAttachedReleasedSignal.isValid()); + QQuickButton *button = window->property("button").value<QQuickButton*>(); QVERIFY(button); @@ -229,10 +238,14 @@ void tst_popup::overlay() QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), ++overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), overlayReleaseCount); + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), overlayReleaseCount); // no modal-popups open + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); popup->close(); QVERIFY(!popup->isVisible()); @@ -250,10 +263,14 @@ void tst_popup::overlay() QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), ++overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), overlayReleaseCount); + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), ++overlayReleaseCount); + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); QVERIFY(!popup->isVisible()); QCOMPARE(overlay->isVisible(), popup->isVisible()); @@ -279,10 +296,14 @@ void tst_popup::overlay() QTest::touchEvent(window, device.data()).press(0, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), ++overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), overlayReleaseCount); + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); QTest::touchEvent(window, device.data()).release(0, QPoint(1, 1)); QCOMPARE(overlayPressedSignal.count(), overlayPressCount); QCOMPARE(overlayReleasedSignal.count(), ++overlayReleaseCount); + QCOMPARE(overlayAttachedPressedSignal.count(), overlayPressCount); + QCOMPARE(overlayAttachedReleasedSignal.count(), overlayReleaseCount); QVERIFY(!popup->isVisible()); QCOMPARE(overlay->isVisible(), popup->isVisible()); |