diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-06-16 14:55:00 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-06-23 17:51:53 +0000 |
commit | 8e147d3a5acad2aaedd03103340854e088f2029a (patch) | |
tree | 5dc2ba5c450a5544eb4ba1c468e12b3f774a7311 /src/quicktemplates2/qquickpopup.cpp | |
parent | 83c31defc6a8dce29073f626aa2aaf7b26e4f029 (diff) |
Move visual overlay background management to QQuickPopup
During the early days, there was only one visual overlay background
dimmer, so QQuickOverlay was the natural choice to manage it. It was
soon realized that multiple modal popups and drawers needed each their
own background dimming. Now the implementation becomes simpler when
each popup manages its own background dimming. This paves the road for
the upcoming changes making it possible to provide background dimming
without ApplicationWindow.
Task-number: QTBUG-61336
Change-Id: I621db4efe4aa74c147f81f7aee8affebddb00d49
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quicktemplates2/qquickpopup.cpp')
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 18579b90..1ccd1040 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -437,6 +437,9 @@ bool QQuickPopupPrivate::prepareEnterTransition() if (transitionState != EnterTransition) { popupItem->setParentItem(QQuickOverlay::overlay(window)); + if (dim) + createOverlay(); + showOverlay(); emit q->aboutToShow(); visible = true; transitionState = EnterTransition; @@ -461,6 +464,7 @@ bool QQuickPopupPrivate::prepareExitTransition() popupItem->setFocus(false); } transitionState = ExitTransition; + hideOverlay(); emit q->aboutToHide(); emit q->openedChanged(); } @@ -483,6 +487,7 @@ void QQuickPopupPrivate::finalizeExitTransition() positioner->setParentItem(nullptr); popupItem->setParentItem(nullptr); popupItem->setVisible(false); + destroyOverlay(); if (hadActiveFocusBeforeExitTransition && window) { if (!qobject_cast<QQuickPopupItem *>(window->activeFocusItem())) { @@ -603,6 +608,88 @@ void QQuickPopupPrivate::reposition() positioner->reposition(); } +static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQuickItem *parent) +{ + QQuickItem *item = nullptr; + if (component) { + QQmlContext *creationContext = component->creationContext(); + if (!creationContext) + creationContext = qmlContext(parent); + QQmlContext *context = new QQmlContext(creationContext, parent); + context->setContextObject(popup); + item = qobject_cast<QQuickItem*>(component->beginCreate(context)); + } + + // when there is no overlay component available (with plain QQuickWindow), + // use a plain QQuickItem as a fallback to block hover events + if (!item && popup->isModal()) + item = new QQuickItem; + + if (item) { + item->setOpacity(popup->isVisible() ? 1.0 : 0.0); + item->setParentItem(parent); + item->stackBefore(popup->popupItem()); + item->setZ(popup->z()); + if (popup->isModal()) { + item->setAcceptedMouseButtons(Qt::AllButtons); +#if QT_CONFIG(cursor) + item->setCursor(Qt::ArrowCursor); +#endif +#if QT_CONFIG(quicktemplates2_hover) + // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8 + item->setAcceptHoverEvents(true); + // item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects()); + // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents); +#endif + } + if (component) + component->completeCreate(); + } + return item; +} + +void QQuickPopupPrivate::createOverlay() +{ + Q_Q(QQuickPopup); + QQuickOverlay *overlay = QQuickOverlay::overlay(window); + if (!overlay) + return; + + if (!dimmer) + dimmer = createDimmer(modal ? overlay->modal() : overlay->modeless(), q, overlay); + resizeOverlay(); +} + +void QQuickPopupPrivate::destroyOverlay() +{ + if (dimmer) { + dimmer->setParentItem(nullptr); + dimmer->deleteLater(); + dimmer = nullptr; + } +} + +void QQuickPopupPrivate::toggleOverlay() +{ + destroyOverlay(); + if (dim) + createOverlay(); +} + +void QQuickPopupPrivate::showOverlay() +{ + // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors + if (dim && dimmer) + QQmlProperty::write(dimmer, QStringLiteral("opacity"), 1.0); +} + +void QQuickPopupPrivate::hideOverlay() +{ + // use QQmlProperty instead of QQuickItem::setOpacity() to trigger QML Behaviors + if (dim && dimmer) + QQmlProperty::write(dimmer, QStringLiteral("opacity"), 0.0); +} + void QQuickPopupPrivate::resizeOverlay() { if (!dimmer) @@ -1660,6 +1747,8 @@ void QQuickPopup::setModal(bool modal) if (d->modal == modal) return; d->modal = modal; + if (d->complete && d->visible) + d->toggleOverlay(); emit modalChanged(); if (!d->hasDim) { @@ -1693,6 +1782,8 @@ void QQuickPopup::setDim(bool dim) return; d->dim = dim; + if (d->complete && d->visible) + d->toggleOverlay(); emit dimChanged(); } |