Commit 0f4266fb authored by Shawn Rutledge's avatar Shawn Rutledge
Browse files

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: default avatarLiang Qi <liang.qi@theqtcompany.com>
Showing with 31 additions and 21 deletions
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "qquickitem.h" #include "qquickitem.h"
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <private/qqmlglobal_p.h>
#include <QWindow> #include <QWindow>
#include <QQmlComponent> #include <QQmlComponent>
#include <QQuickWindow> #include <QQuickWindow>
...@@ -109,22 +110,28 @@ void QQuickAbstractDialog::setVisible(bool v) ...@@ -109,22 +110,28 @@ void QQuickAbstractDialog::setVisible(bool v)
connect(win, SIGNAL(heightChanged(int)), this, SLOT(windowGeometryChanged())); connect(win, SIGNAL(heightChanged(int)), this, SLOT(windowGeometryChanged()));
} }
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); if (!m_dialogWindow) {
if (Q_UNLIKELY(!parentWindow())) {
// If the platform does not support multiple windows, but the dialog is qWarning("cannot set dialog visible: no window");
// implemented as an Item, then try to decorate it as a fake window and make it visible. return;
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();
} }
// Window decoration wasn't possible, so just reparent it into the scene m_dialogWindow = parentWindow();
else {
m_contentItem->setParentItem(parentItem); // If the platform does not support multiple windows, but the dialog is
m_contentItem->setZ(10000); // 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) ...@@ -168,9 +175,9 @@ void QQuickAbstractDialog::setVisible(bool v)
void QQuickAbstractDialog::decorationLoaded() void QQuickAbstractDialog::decorationLoaded()
{ {
bool ok = false; bool ok = false;
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); Q_ASSERT(parentWindow());
while (parentItem->parentItem() && !parentItem->parentItem()->inherits("QQuickRootItem")) QQuickItem *parentItem = parentWindow()->contentItem();
parentItem = parentItem->parentItem(); Q_ASSERT(parentItem);
if (m_decorationComponent->isError()) { if (m_decorationComponent->isError()) {
qWarning() << m_decorationComponent->errors(); qWarning() << m_decorationComponent->errors();
} else { } else {
...@@ -252,9 +259,12 @@ void QQuickAbstractDialog::implicitHeightChanged() ...@@ -252,9 +259,12 @@ void QQuickAbstractDialog::implicitHeightChanged()
QQuickWindow *QQuickAbstractDialog::parentWindow() QQuickWindow *QQuickAbstractDialog::parentWindow()
{ {
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); if (!m_parentWindow) {
if (parentItem) // Usually a dialog is declared inside an Item; but if its QObject parent
m_parentWindow = parentItem->window(); // 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; return m_parentWindow;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment