diff options
author | Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com> | 2015-03-24 20:56:48 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@theqtcompany.com> | 2015-03-27 16:15:43 +0000 |
commit | de9145dcd904068256e28e130fdfda2e8014efe8 (patch) | |
tree | fd046cf9d9d571537de633740e2b689dc9a47d47 /src/controls/qquickmenu.cpp | |
parent | ea9e620a7f5bfbac63ccc9017732bb78db8e5356 (diff) | |
download | qtquickcontrols-de9145dcd904068256e28e130fdfda2e8014efe8.tar.gz |
Menu: Separate dismiss and destroy actions
This avoids issues when the action is triggered from a Menu and the slot
ends up processing pending events, effectively deleting an object while
one of its QML signal handlers is being executed. The reason being that
we used to call deleteLater() on the menu popup window while still in
the mouse event handler.
Now, we do the same thing in three separate steps. 1. Close/dismiss the
menu popups, 2. trigger the action, and 3. delete the popups. This keeps
the menu popups and their contents alive until we return from the action
triggered handler. We also need to take care of manually destroying any
popup we may create. Finally, the menu content creation in Menu.qml had
to be tweaked since we shouldn't rely on the popup visibility anymore.
Task-number: QTBUG-45182
Change-Id: I9f1155bbf74dd3353c6c4066a24abf1cd2c3a283
Reviewed-by: Caroline Chao <caroline.chao@theqtcompany.com>
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
Diffstat (limited to 'src/controls/qquickmenu.cpp')
-rw-r--r-- | src/controls/qquickmenu.cpp | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/src/controls/qquickmenu.cpp b/src/controls/qquickmenu.cpp index 1a125135..80b5607e 100644 --- a/src/controls/qquickmenu.cpp +++ b/src/controls/qquickmenu.cpp @@ -428,6 +428,7 @@ void QQuickMenu::__popup(const QRectF &targetRect, int atItemIndex, MenuType men connect(m_popupWindow, SIGNAL(visibleChanged(bool)), this, SLOT(windowVisibleChanged(bool))); connect(m_popupWindow, SIGNAL(geometryChanged()), this, SIGNAL(__popupGeometryChanged())); + connect(m_popupWindow, SIGNAL(willBeDeletedLater()), this, SLOT(clearPopupWindow())); m_popupWindow->setPosition(targetRect.x() + m_xOffset + renderOffset.x(), targetRect.y() + targetRect.height() + m_yOffset + renderOffset.y()); @@ -468,34 +469,57 @@ void QQuickMenu::__closeMenu() emit __menuClosed(); } +QQuickMenuPopupWindow *QQuickMenu::topMenuPopup() const +{ + QQuickMenuPopupWindow *topMenuWindow = m_popupWindow; + while (topMenuWindow) { + QQuickMenuPopupWindow *pw = qobject_cast<QQuickMenuPopupWindow *>(topMenuWindow->transientParent()); + if (!pw) + return topMenuWindow; + topMenuWindow = pw; + } + + return 0; +} + void QQuickMenu::__dismissMenu() { if (m_platformMenu) { m_platformMenu->dismiss(); - } else { - QQuickMenuPopupWindow *topMenuWindow = m_popupWindow; - while (topMenuWindow) { - QQuickMenuPopupWindow *pw = qobject_cast<QQuickMenuPopupWindow *>(topMenuWindow->transientParent()); - if (!pw) - topMenuWindow->dismissPopup(); - topMenuWindow = pw; - } + } else if (QQuickMenuPopupWindow *topPopup = topMenuPopup()) { + topPopup->dismissPopup(); } } void QQuickMenu::windowVisibleChanged(bool v) { if (!v) { - if (qobject_cast<QQuickMenuPopupWindow *>(m_popupWindow->transientParent())) { + if (m_popupWindow && qobject_cast<QQuickMenuPopupWindow *>(m_popupWindow->transientParent())) { m_popupWindow->transientParent()->setMouseGrabEnabled(true); m_popupWindow->transientParent()->setKeyboardGrabEnabled(true); } - m_popupWindow->deleteLater(); - m_popupWindow = 0; __closeMenu(); } } +void QQuickMenu::clearPopupWindow() +{ + m_popupWindow = 0; + emit __menuPopupDestroyed(); +} + +void QQuickMenu::__destroyMenuPopup() +{ + if (m_popupWindow) + m_popupWindow->setToBeDeletedLater(); +} + +void QQuickMenu::__destroyAllMenuPopups() { + QQuickMenuPopupWindow *popup = topMenuPopup(); + if (popup) + popup->setToBeDeletedLater(); +} + void QQuickMenu::itemIndexToListIndex(int itemIndex, int *listIndex, int *containerIndex) const { *listIndex = -1; |