diff options
-rw-r--r-- | dist/changes-5.1.0 | 3 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 21 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 91 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 6 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp | 2 |
7 files changed, 119 insertions, 6 deletions
diff --git a/dist/changes-5.1.0 b/dist/changes-5.1.0 index cee8d4b382..4333c4a8dd 100644 --- a/dist/changes-5.1.0 +++ b/dist/changes-5.1.0 @@ -32,6 +32,9 @@ Third party components * Important Behavior Changes * **************************************************************************** + - A Window declared nested inside another Item or Window automatically + becomes transient for (centered upon) its parent's window, if x and y + were not explicitly specified **************************************************************************** * Library * diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index d110a01290..d31e142035 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2685,6 +2685,23 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o) } else { if (o->inherits("QGraphicsItem")) qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className()); + else { + QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o); + QQuickItem *item = that; + QQuickWindow *itemWindow = that->window(); + while (!itemWindow && item && item->parentItem()) { + item = item->parentItem(); + itemWindow = item->window(); + } + + if (thisWindow) { + if (itemWindow) + thisWindow->setTransientParent(itemWindow); + else + QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)), + thisWindow, SLOT(setTransientParent_helper(QQuickWindow*))); + } + } // XXX todo - do we really want this behavior? o->setParent(that); @@ -4413,8 +4430,8 @@ void QQuickItemPrivate::deliverDragEvent(QEvent *e) */ void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value) { - Q_UNUSED(change); - Q_UNUSED(value); + if (change == ItemSceneChange) + emit windowChanged(value.window); } #ifndef QT_NO_IM diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 040f9d6888..5dea86296f 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -355,6 +355,7 @@ Q_SIGNALS: void smoothChanged(bool); void antialiasingChanged(bool); void clipChanged(bool); + Q_REVISION(1) void windowChanged(QQuickWindow* window); // XXX todo void childrenChanged(); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 4789314e01..97a257614f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -414,7 +414,10 @@ void QQuickWindowPrivate::init(QQuickWindow *c) QQmlListProperty<QObject> QQuickWindowPrivate::data() { initContentItem(); - return QQuickItemPrivate::get(contentItem)->data(); + return QQmlListProperty<QObject>(q_func(), 0, QQuickWindowPrivate::data_append, + QQuickWindowPrivate::data_count, + QQuickWindowPrivate::data_at, + QQuickWindowPrivate::data_clear); } void QQuickWindowPrivate::initContentItem() @@ -846,7 +849,21 @@ void QQuickWindowPrivate::cleanup(QSGNode *n) import QtQuick.Window 2.1 \endcode - Restricting this import will allow you to have a QML environment without access to window system features. + Omitting this import will allow you to have a QML environment without + access to window system features. + + A Window can be declared inside an Item or inside another Window; in that + case the inner Window will automatically become "transient for" the outer + Window: that is, most platforms will show it centered upon the outer window + by default, and there may be other platform-dependent behaviors, depending + also on the \l flags. If the nested window is intended to be a dialog in + your application, you should also set \l flags to Qt.Dialog, because some + window managers will not provide the centering behavior without that flag. + You can also declare multiple windows inside a top-level \l QtObject, in which + case the windows will have no transient relationship. + + Alternatively you can set or bind \l x and \l y to position the Window + explicitly on the screen. */ /*! \class QQuickWindow @@ -1094,7 +1111,10 @@ QQuickItem *QQuickWindow::contentItem() const } /*! - Returns the item which currently has active focus. + \property QQuickWindow::activeFocusItem + + \brief The item which currently has active focus or \c null if there is + no item with active focus. */ QQuickItem *QQuickWindow::activeFocusItem() const { @@ -2037,6 +2057,64 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent return overThreshold; } +/*! + \qmlproperty list<Object> QtQuick.Window2::Window::data + \default + + The data property allows you to freely mix visual children, resources + and other Windows in a Window. + + If you assign another Window to the data list, the nested window will + become "transient for" the outer Window. + + If you assign an \l Item to the data list, it becomes a child of the + Window's \l contentItem, so that it appears inside the window. The item's + parent will be the window's contentItem, which is the root of the Item + ownership tree within that Window. + + If you assign any other object type, it is added as a resource. + + It should not generally be necessary to refer to the \c data property, + as it is the default property for Window and thus all child items are + automatically assigned to this property. + + \sa QWindow::transientParent() + */ + +void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o) +{ + if (!o) + return; + QQuickWindow *that = static_cast<QQuickWindow *>(property->object); + if (QQuickWindow *window = qmlobject_cast<QQuickWindow *>(o)) + window->setTransientParent(that); + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data(); + itemProperty.append(&itemProperty, o); +} + +int QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property) +{ + QQuickWindow *win = static_cast<QQuickWindow*>(property->object); + if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count) + return 0; + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data(); + return itemProperty.count(&itemProperty); +} + +QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, int i) +{ + QQuickWindow *win = static_cast<QQuickWindow*>(property->object); + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data(); + return itemProperty.at(&itemProperty, i); +} + +void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property) +{ + QQuickWindow *win = static_cast<QQuickWindow*>(property->object); + QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data(); + itemProperty.clear(&itemProperty); +} + bool QQuickWindowPrivate::isRenderable() const { const QQuickWindow *q = q_func(); @@ -2456,6 +2534,13 @@ void QQuickWindow::cleanupSceneGraph() d->renderer = 0; } +void QQuickWindow::setTransientParent_helper(QQuickWindow *window) +{ + setTransientParent(window); + disconnect(sender(), SIGNAL(windowChanged(QQuickWindow*)), + this, SLOT(setTransientParent_helper(QQuickWindow*))); +} + /*! Returns the opengl context used for rendering. diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index a2ba9e9fe0..3adc0be83b 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -162,6 +162,7 @@ protected: private Q_SLOTS: void maybeUpdate(); void cleanupSceneGraph(); + void setTransientParent_helper(QQuickWindow *window); private: friend class QQuickItem; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index ab772ca2bc..ed2ff3b902 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -224,6 +224,12 @@ public: static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event); + // data property + static void data_append(QQmlListProperty<QObject> *, QObject *); + static int data_count(QQmlListProperty<QObject> *); + static QObject *data_at(QQmlListProperty<QObject> *, int); + static void data_clear(QQmlListProperty<QObject> *); + private: static void cleanupNodesOnShutdown(QQuickItem *); }; diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index fa33f3f626..a959a60acf 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -585,7 +585,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() QWindow *secondWindow = qvariant_cast<QWindow*>(window->rootObject()->property("secondWindow")); secondWindow->setProperty("visible", true); - QTest::qWaitForWindowActive(secondWindow); + QTest::qWaitForWindowExposed(secondWindow); QVERIFY(!window->rootObject()->property("pressed").toBool()); QVERIFY(window->rootObject()->property("canceled").toBool()); |