diff --git a/src/dialogs/qquickabstractdialog.cpp b/src/dialogs/qquickabstractdialog.cpp index 7c5ef33411d0957089ba1340c5810aba68f0b207..6cad340f7efa3edc27d9cd88bd5b5f8ca4435923 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; }