aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@digia.com>2013-03-27 09:57:59 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-04-10 21:20:08 +0200
commitccbf0560b36515630328be44a20f4fe62eaec531 (patch)
treebb67970cb1cd91c42186914bb1fa6d4a0594ea31
parent8190355557c13bba836cef49585556f0c823f672 (diff)
a nested Window automatically becomes transient for its parent
If you declare Window { Window {}} or Window { Item { Window {}}} the inner window will automatically become transient for the outer one. The transient relationship must be set before the inner window becomes visible though, so declaring visible: true doesn't always work, depending on initialization order. It's OK if you assign visible (or call show()) later on when the user needs to see the transient window for the first time. Also added documentation. Change-Id: I888c3b9da6d44d11516227c085bcc12a5ccb5e81 Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com> Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
-rw-r--r--dist/changes-5.1.03
-rw-r--r--src/quick/items/qquickitem.cpp21
-rw-r--r--src/quick/items/qquickitem.h1
-rw-r--r--src/quick/items/qquickwindow.cpp91
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quick/items/qquickwindow_p.h6
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp2
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());