diff options
-rw-r--r-- | src/imports/controls/ApplicationWindow.qml | 6 | ||||
-rw-r--r-- | src/imports/controls/material/ApplicationWindow.qml | 7 | ||||
-rw-r--r-- | src/imports/controls/universal/ApplicationWindow.qml | 6 | ||||
-rw-r--r-- | src/imports/templates/plugins.qmltypes | 4 | ||||
-rw-r--r-- | src/quicktemplates2/qquickapplicationwindow.cpp | 25 | ||||
-rw-r--r-- | src/quicktemplates2/qquickoverlay.cpp | 108 | ||||
-rw-r--r-- | src/quicktemplates2/qquickoverlay_p.h | 13 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 45 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p.h | 6 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopup_p_p.h | 2 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_popup.qml | 55 |
11 files changed, 215 insertions, 62 deletions
diff --git a/src/imports/controls/ApplicationWindow.qml b/src/imports/controls/ApplicationWindow.qml index cc30c601..98de8946 100644 --- a/src/imports/controls/ApplicationWindow.qml +++ b/src/imports/controls/ApplicationWindow.qml @@ -43,7 +43,11 @@ T.ApplicationWindow { color: "#ffffff" - overlay.background: Rectangle { + overlay.modal: Rectangle { color: "#7f28282a" } + + overlay.modeless: Rectangle { + color: "#1f28282a" + } } diff --git a/src/imports/controls/material/ApplicationWindow.qml b/src/imports/controls/material/ApplicationWindow.qml index a09cd89f..db27f25b 100644 --- a/src/imports/controls/material/ApplicationWindow.qml +++ b/src/imports/controls/material/ApplicationWindow.qml @@ -44,7 +44,12 @@ T.ApplicationWindow { color: Material.backgroundColor - overlay.background: Rectangle { + overlay.modal: Rectangle { + color: window.Material.backgroundDimColor + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + overlay.modeless: Rectangle { color: window.Material.backgroundDimColor Behavior on opacity { NumberAnimation { duration: 150 } } } diff --git a/src/imports/controls/universal/ApplicationWindow.qml b/src/imports/controls/universal/ApplicationWindow.qml index 664229a3..70bd403c 100644 --- a/src/imports/controls/universal/ApplicationWindow.qml +++ b/src/imports/controls/universal/ApplicationWindow.qml @@ -44,7 +44,11 @@ T.ApplicationWindow { color: Universal.background - overlay.background: Rectangle { + overlay.modal: Rectangle { + color: window.Universal.baseLowColor + } + + overlay.modeless: Rectangle { color: window.Universal.baseLowColor } diff --git a/src/imports/templates/plugins.qmltypes b/src/imports/templates/plugins.qmltypes index af573750..b4155841 100644 --- a/src/imports/templates/plugins.qmltypes +++ b/src/imports/templates/plugins.qmltypes @@ -491,7 +491,8 @@ Module { name: "QQuickOverlay" defaultProperty: "data" prototype: "QQuickItem" - Property { name: "background"; type: "QQuickItem"; isPointer: true } + Property { name: "modal"; type: "QQuickItem"; isPointer: true } + Property { name: "modeless"; type: "QQuickItem"; isPointer: true } Signal { name: "pressed" } Signal { name: "released" } } @@ -591,6 +592,7 @@ Module { Property { name: "focus"; type: "bool" } Property { name: "activeFocus"; type: "bool"; isReadonly: true } Property { name: "modal"; type: "bool" } + Property { name: "dim"; type: "bool" } Property { name: "visible"; type: "bool" } Property { name: "opacity"; type: "double" } Property { name: "scale"; type: "double" } diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 7191d57f..1611ebaf 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -446,13 +446,30 @@ QQuickItem *QQuickApplicationWindow::activeFocusControl() const /*! \qmlpropertygroup QtQuick.Controls::ApplicationWindow::overlay \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay - \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay.background + \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay.modal + \qmlproperty Item QtQuick.Controls::ApplicationWindow::overlay.modeless - This property holds the window overlay item and its background that implements the - background dimming when any modal popups are open. Popups are automatically + This property holds the window overlay item. Popups are automatically reparented to the overlay. - \sa Popup + \table + \header + \li Property + \li Description + \row + \li overlay.modal + \li This property holds a visual item that implements background + dimming for modal popups. It is stacked below the top-most open + modal popup, or hidden when there are no modal popups open. + \row + \li overlay.modeless + \li This property holds a visual item that implements background + dimming for modeless popups. It is stacked below the top-most + open modeless dimming popup, or hidden when there are no modeless + dimming popups open. + \endtable + + \sa Popup::modal, Popup::dim */ QQuickOverlay *QQuickApplicationWindow::overlay() const { diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index 07db8d27..24d10e9c 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -53,9 +53,10 @@ public: void popupAboutToShow(); void popupAboutToHide(); void drawerPositionChange(); - void resizeBackground(); + void resizeOverlay(QQuickItem *overlay); - QQuickItem *background; + QQuickItem *modal; + QQuickItem *modeless; QVector<QQuickDrawer *> drawers; QVector<QQuickPopup *> popups; QPointer<QQuickPopup> mouseGrabberPopup; @@ -65,52 +66,71 @@ public: void QQuickOverlayPrivate::popupAboutToShow() { Q_Q(QQuickOverlay); - if (!background) - return; - QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender()); - if (!popup || !popup->isModal()) + if (!popup) return; // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors - QQmlProperty::write(background, QStringLiteral("opacity"), 1.0); + if (popup->isModal()) { + if (modal) { + modal->setZ(popup->z()); + modal->stackBefore(popup->popupItem()); + QQmlProperty::write(modal, QStringLiteral("opacity"), 1.0); + } + } else if (popup->dim()) { + if (modeless) { + modeless->setZ(popup->z()); + modeless->stackBefore(popup->popupItem()); + QQmlProperty::write(modeless, QStringLiteral("opacity"), 1.0); + } + } } void QQuickOverlayPrivate::popupAboutToHide() { Q_Q(QQuickOverlay); - if (!background || modalPopups > 1) - return; - QQuickPopup *popup = qobject_cast<QQuickPopup *>(q->sender()); - if (!popup || !popup->isModal()) + if (!popup) return; // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors - QQmlProperty::write(background, QStringLiteral("opacity"), 0.0); + if (popup->isModal()) { + if (modal && modalPopups <= 1) + QQmlProperty::write(modal, QStringLiteral("opacity"), 0.0); + } else if (popup->dim()) { + if (modeless) + QQmlProperty::write(modeless, QStringLiteral("opacity"), 0.0); + } } void QQuickOverlayPrivate::drawerPositionChange() { Q_Q(QQuickOverlay); QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(q->sender()); - if (!background || !drawer || !drawer->isModal()) + if (!drawer) return; // call QQuickItem::setOpacity() directly to avoid triggering QML Behaviors // which would make the fading feel laggy compared to the drawer movement - background->setOpacity(drawer->position()); + if (drawer->isModal()) { + if (modal) + modal->setOpacity(drawer->position()); + } else if (drawer->dim()) { + if (modeless) + modeless->setOpacity(drawer->position()); + } } -void QQuickOverlayPrivate::resizeBackground() +void QQuickOverlayPrivate::resizeOverlay(QQuickItem *overlay) { Q_Q(QQuickOverlay); - background->setWidth(q->width()); - background->setHeight(q->height()); + overlay->setWidth(q->width()); + overlay->setHeight(q->height()); } QQuickOverlayPrivate::QQuickOverlayPrivate() : - background(nullptr), + modal(nullptr), + modeless(nullptr), modalPopups(0) { } @@ -123,30 +143,50 @@ QQuickOverlay::QQuickOverlay(QQuickItem *parent) setVisible(false); } +QQuickItem *QQuickOverlay::modal() const +{ + Q_D(const QQuickOverlay); + return d->modal; +} + +void QQuickOverlay::setModal(QQuickItem *modal) +{ + Q_D(QQuickOverlay); + if (d->modal == modal) + return; + + delete d->modal; + d->modal = modal; + if (modal) { + modal->setOpacity(0.0); + modal->setParentItem(this); + if (isComponentComplete()) + d->resizeOverlay(modal); + } + emit modalChanged(); +} -QQuickItem *QQuickOverlay::background() const +QQuickItem *QQuickOverlay::modeless() const { Q_D(const QQuickOverlay); - return d->background; + return d->modeless; } -void QQuickOverlay::setBackground(QQuickItem *background) +void QQuickOverlay::setModeless(QQuickItem *modeless) { Q_D(QQuickOverlay); - if (d->background == background) + if (d->modeless == modeless) return; - delete d->background; - d->background = background; - if (background) { - background->setOpacity(0.0); - background->setParentItem(this); - if (qFuzzyIsNull(background->z())) - background->setZ(-1); + delete d->modeless; + d->modeless = modeless; + if (modeless) { + modeless->setOpacity(0.0); + modeless->setParentItem(this); if (isComponentComplete()) - d->resizeBackground(); + d->resizeOverlay(modeless); } - emit backgroundChanged(); + emit modelessChanged(); } void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data) @@ -197,8 +237,10 @@ void QQuickOverlay::geometryChanged(const QRectF &newGeometry, const QRectF &old { Q_D(QQuickOverlay); QQuickItem::geometryChanged(newGeometry, oldGeometry); - if (d->background) - d->resizeBackground(); + if (d->modal) + d->resizeOverlay(d->modal); + if (d->modeless) + d->resizeOverlay(d->modeless); } bool QQuickOverlay::event(QEvent *event) diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h index 78916036..4b6cb9c7 100644 --- a/src/quicktemplates2/qquickoverlay_p.h +++ b/src/quicktemplates2/qquickoverlay_p.h @@ -58,16 +58,21 @@ class QQuickOverlayPrivate; class Q_QUICKTEMPLATES2_EXPORT QQuickOverlay : public QQuickItem { Q_OBJECT - Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL) + Q_PROPERTY(QQuickItem *modal READ modal WRITE setModal NOTIFY modalChanged FINAL) + Q_PROPERTY(QQuickItem *modeless READ modeless WRITE setModeless NOTIFY modelessChanged FINAL) public: explicit QQuickOverlay(QQuickItem *parent = nullptr); - QQuickItem *background() const; - void setBackground(QQuickItem *background); + QQuickItem *modal() const; + void setModal(QQuickItem *modal); + + QQuickItem *modeless() const; + void setModeless(QQuickItem *modeless); Q_SIGNALS: - void backgroundChanged(); + void modalChanged(); + void modelessChanged(); void pressed(); void released(); diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 13e562d0..5b10bb12 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -121,6 +121,8 @@ QQuickPopupPrivate::QQuickPopupPrivate() : QObjectPrivate() , focus(false) , modal(false) + , dim(false) + , hasDim(false) , visible(false) , complete(false) , hasTopMargin(false) @@ -1520,6 +1522,49 @@ void QQuickPopup::setModal(bool modal) return; d->modal = modal; emit modalChanged(); + + if (!d->hasDim) { + setDim(modal); + d->hasDim = false; + } +} + +/*! + \qmlproperty bool QtQuick.Controls::Popup::dim + + This property holds whether the popup dims the background. + + Unless explicitly set, this property follows the value of \l modal. To + return to the default value, set this property to \c undefined. + + \sa modal +*/ +bool QQuickPopup::dim() const +{ + Q_D(const QQuickPopup); + return d->dim; +} + +void QQuickPopup::setDim(bool dim) +{ + Q_D(QQuickPopup); + d->hasDim = true; + + if (d->dim == dim) + return; + + d->dim = dim; + emit dimChanged(); +} + +void QQuickPopup::resetDim() +{ + Q_D(QQuickPopup); + if (!d->hasDim) + return; + + setDim(d->modal); + d->hasDim = false; } /*! diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h index e1219a2c..27123ae5 100644 --- a/src/quicktemplates2/qquickpopup_p.h +++ b/src/quicktemplates2/qquickpopup_p.h @@ -105,6 +105,7 @@ class Q_QUICKTEMPLATES2_EXPORT QQuickPopup : public QObject, public QQmlParserSt Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL) Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL) Q_PROPERTY(bool modal READ isModal WRITE setModal NOTIFY modalChanged FINAL) + Q_PROPERTY(bool dim READ dim WRITE setDim RESET resetDim NOTIFY dimChanged FINAL) Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged FINAL) @@ -227,6 +228,10 @@ public: bool isModal() const; void setModal(bool modal); + bool dim() const; + void setDim(bool dim); + void resetDim(); + bool isVisible() const; void setVisible(bool visible); @@ -306,6 +311,7 @@ Q_SIGNALS: void focusChanged(); void activeFocusChanged(); void modalChanged(); + void dimChanged(); void visibleChanged(); void opacityChanged(); void scaleChanged(); diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index a765998a..7d367812 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -176,6 +176,8 @@ public: bool focus; bool modal; + bool dim; + bool hasDim; bool visible; bool complete; bool hasTopMargin; diff --git a/tests/auto/controls/data/tst_popup.qml b/tests/auto/controls/data/tst_popup.qml index b63bc826..b28a31e8 100644 --- a/tests/auto/controls/data/tst_popup.qml +++ b/tests/auto/controls/data/tst_popup.qml @@ -869,17 +869,24 @@ TestCase { Component { id: overlayTest ApplicationWindow { - property alias popup1: popup1 - property alias popup2: popup2 + property alias modalPopup: modalPopup + property alias modelessPopup: modelessPopup + property alias plainPopup: plainPopup visible: true Popup { - id: popup1 + id: modalPopup modal: true exit: Transition { PauseAnimation { duration: 200 } } } Popup { - id: popup2 - modal: true + id: modelessPopup + dim: true + exit: Transition { PauseAnimation { duration: 200 } } + } + Popup { + id: plainPopup + enter: Transition { PauseAnimation { duration: 200 } } + exit: Transition { PauseAnimation { duration: 200 } } } } } @@ -890,18 +897,32 @@ TestCase { window.requestActivate() tryCompare(window, "active", true) - compare(window.overlay.background.opacity, 0.0) - - window.popup1.open() - compare(window.popup1.visible, true) - compare(window.popup2.visible, false) - tryCompare(window.overlay.background, "opacity", 1.0) - - window.popup1.close() - window.popup2.open() - compare(window.popup2.visible, true) - tryCompare(window.popup1, "visible", false) - compare(window.overlay.background.opacity, 1.0) + compare(window.overlay.modal.opacity, 0.0) + compare(window.overlay.modeless.opacity, 0.0) + + window.modalPopup.open() + compare(window.modalPopup.visible, true) + tryCompare(window.overlay.modal, "opacity", 1.0) + + window.modelessPopup.open() + compare(window.modelessPopup.visible, true) + tryCompare(window.overlay.modeless, "opacity", 1.0) + + window.modelessPopup.close() + tryCompare(window.modelessPopup, "visible", false) + tryCompare(window.overlay.modeless, "opacity", 0.0) + + compare(window.modalPopup.visible, true) + compare(window.overlay.modal.opacity, 1.0) + + window.modalPopup.close() + tryCompare(window.modalPopup, "visible", false) + tryCompare(window.overlay.modal, "opacity", 0.0) + + window.plainPopup.open() + tryCompare(window.plainPopup, "visible", true) + compare(window.overlay.modal.opacity, 0.0) + compare(window.overlay.modeless.opacity, 0.0) window.destroy() } |