From 0f4266fbbc45fc311051d9bfb014fb162c383c3e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge <shawn.rutledge@digia.com> Date: Fri, 24 Oct 2014 09:56:41 +0200 Subject: [PATCH] Dialogs: detect and handle dynamic creation with Window parent When instantiating via Qt.createQmlObject('Dialog { }', window, "path") the dialog's parent will be the Window. That was an unanticipated use case, but also a simpler one: if the platform does not support multiple windows, then we only need to construct the dialog and its decoration on top of that window's contentItem. Or if there is to be a separate dialog window, then it should be transient for the main window. Also rearranged the parenting strategy around the fact that the application is always within a QQuickWindow: parentWindow() is responsible for finding it, and it's not necessary to recursively go up the Item hierarchy to find the root item if we are sure that there is a window, because the root item is that window's contentItem. Task-number: QTBUG-38578 Change-Id: I79e0cf44f789701f5d40e5e9d0449a55947be907 Reviewed-by: Liang Qi <liang.qi@theqtcompany.com> --- src/dialogs/qquickabstractdialog.cpp | 52 +++++++++++++++++----------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/dialogs/qquickabstractdialog.cpp b/src/dialogs/qquickabstractdialog.cpp index 7c5ef3341..6cad340f7 100644 --- a/src/dialogs/qquickabstractdialog.cpp +++ b/src/dialogs/qquickabstractdialog.cpp @@ -35,6 +35,7 @@ #include "qquickitem.h" #include <private/qguiapplication_p.h> +#include <private/qqmlglobal_p.h> #include <QWindow> #include <QQmlComponent> #include <QQuickWindow> @@ -109,22 +110,28 @@ void QQuickAbstractDialog::setVisible(bool v) connect(win, SIGNAL(heightChanged(int)), this, SLOT(windowGeometryChanged())); } - QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); - - // If the platform does not support multiple windows, but the dialog is - // implemented as an Item, then try to decorate it as a fake window and make it visible. - if (parentItem && !m_dialogWindow && !m_windowDecoration) { - if (m_decorationComponent) { - if (m_decorationComponent->isLoading()) - connect(m_decorationComponent, SIGNAL(statusChanged(QQmlComponent::Status)), - this, SLOT(decorationLoaded())); - else - decorationLoaded(); + if (!m_dialogWindow) { + if (Q_UNLIKELY(!parentWindow())) { + qWarning("cannot set dialog visible: no window"); + return; } - // Window decoration wasn't possible, so just reparent it into the scene - else { - m_contentItem->setParentItem(parentItem); - m_contentItem->setZ(10000); + m_dialogWindow = parentWindow(); + + // If the platform does not support multiple windows, but the dialog is + // implemented as an Item, then try to decorate it as a fake window and make it visible. + if (!m_windowDecoration) { + if (m_decorationComponent) { + if (m_decorationComponent->isLoading()) + connect(m_decorationComponent, SIGNAL(statusChanged(QQmlComponent::Status)), + this, SLOT(decorationLoaded())); + else + decorationLoaded(); // do the reparenting of contentItem on top of it + } + // Window decoration wasn't possible, so just reparent it into the scene + else { + m_contentItem->setParentItem(parentWindow()->contentItem()); + m_contentItem->setZ(10000); + } } } } @@ -168,9 +175,9 @@ void QQuickAbstractDialog::setVisible(bool v) void QQuickAbstractDialog::decorationLoaded() { bool ok = false; - QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); - while (parentItem->parentItem() && !parentItem->parentItem()->inherits("QQuickRootItem")) - parentItem = parentItem->parentItem(); + Q_ASSERT(parentWindow()); + QQuickItem *parentItem = parentWindow()->contentItem(); + Q_ASSERT(parentItem); if (m_decorationComponent->isError()) { qWarning() << m_decorationComponent->errors(); } else { @@ -252,9 +259,12 @@ void QQuickAbstractDialog::implicitHeightChanged() QQuickWindow *QQuickAbstractDialog::parentWindow() { - QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); - if (parentItem) - m_parentWindow = parentItem->window(); + if (!m_parentWindow) { + // Usually a dialog is declared inside an Item; but if its QObject parent + // is a Window, that's the window we are interested in. (QTBUG-38578) + QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); + m_parentWindow = (parentItem ? parentItem->window() : qmlobject_cast<QQuickWindow *>(parent())); + } return m_parentWindow; } -- GitLab