aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2012-06-12 10:16:47 +1000
committerQt by Nokia <qt-info@nokia.com>2012-06-12 03:22:11 +0200
commite8206bf6ab6ef62b5dd24bf002aa56edecbcec97 (patch)
treeeaf05e69ed3233f2eb215d3e9aeb114b8cb62f43
parentfb41baa0e8bfab231a2fc1f42ad2d6ffab93ccfc (diff)
Allow Loader to load non-Item types.
Loader has a more convenient API for loading/unloading components than the dynamic object creation APIs. Remove the Item-only restriction. Change-Id: I6f9ecc8514ff1e814f7e56a3386814ba211b7e4f Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
-rw-r--r--src/quick/items/qquickloader.cpp81
-rw-r--r--src/quick/items/qquickloader_p.h4
-rw-r--r--src/quick/items/qquickloader_p_p.h1
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp11
4 files changed, 56 insertions, 41 deletions
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 5406016da8..04e248e81a 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -56,7 +56,7 @@ static const QQuickItemPrivate::ChangeTypes watchedChanges
= QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
QQuickLoaderPrivate::QQuickLoaderPrivate()
- : item(0), component(0), itemContext(0), incubator(0), updatingSize(false),
+ : item(0), object(0), component(0), itemContext(0), incubator(0), updatingSize(false),
active(true), loadingFromSource(false), asynchronous(false)
{
}
@@ -118,13 +118,18 @@ void QQuickLoaderPrivate::clear()
// the Loader to load a different item.
item->setParentItem(0);
item->setVisible(false);
- item->deleteLater();
item = 0;
}
+ if (object) {
+ object->deleteLater();
+ object = 0;
+ }
}
void QQuickLoaderPrivate::initResize()
{
+ if (!item)
+ return;
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
p->addItemChangeListener(this, watchedChanges);
_q_updateSize();
@@ -158,10 +163,9 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const
\ingroup qtquick-utility
\inherits Item
- \brief Allows dynamical loading of an item-based subtree from a URL or Component
+ \brief Allows dynamic loading of a subtree from a URL or Component
- Loader is used to dynamically load visual QML components. For loading non-visual
- components, see \l {Dynamic Object Management in QML}.
+ Loader is used to dynamically load QML components.
Loader can load a
QML file (using the \l source property) or a \l Component object (using
@@ -175,17 +179,18 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const
\snippet qml/loader/simple.qml 0
- The loaded item can be accessed using the \l item property.
+ The loaded object can be accessed using the \l item property.
If the \l source or \l sourceComponent changes, any previously instantiated
items are destroyed. Setting \l source to an empty string or setting
- \l sourceComponent to \c undefined destroys the currently loaded item,
+ \l sourceComponent to \c undefined destroys the currently loaded object,
freeing resources and leaving the Loader empty.
\section2 Loader sizing behavior
- Loader is like any other visual item and must be positioned and sized
- accordingly to become visible.
+ If the source component is not an Item type, Loader does not
+ apply any special sizing rules. When used to load visual types,
+ Loader applies the following sizing rules:
\list
\li If an explicit size is not specified for the Loader, the Loader
@@ -213,9 +218,9 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const
\endtable
- \section2 Receiving signals from loaded items
+ \section2 Receiving signals from loaded objects
- Any signals emitted from the loaded item can be received using the
+ Any signals emitted from the loaded object can be received using the
\l Connections element. For example, the following \c application.qml
loads \c MyItem.qml, and is able to receive the \c message signal from
the loaded item through a \l Connections object:
@@ -260,6 +265,8 @@ qreal QQuickLoaderPrivate::getImplicitHeight() const
\c event.accepted to \c true so that the event is not propagated to the
parent \l Rectangle.
+ Since QtQuick 2.0 Loader can also load non-visual components.
+
\sa {dynamic-object-creation}{Dynamic Object Creation}
*/
@@ -326,8 +333,11 @@ void QQuickLoader::setActive(bool newVal)
// the Loader to load a different item.
d->item->setParentItem(0);
d->item->setVisible(false);
- d->item->deleteLater();
d->item = 0;
+ }
+ if (d->object) {
+ d->object->deleteLater();
+ d->object = 0;
emit itemChanged();
}
emit statusChanged();
@@ -341,10 +351,10 @@ void QQuickLoader::setActive(bool newVal)
\qmlproperty url QtQuick2::Loader::source
This property holds the URL of the QML component to instantiate.
- Note the QML component must be an \l{Item}-based component. The loader
- cannot load non-visual components.
+ Since QtQuick 2.0 Loader is able to load any type of object; it
+ is not restricted to Item types.
- To unload the currently loaded item, set this property to an empty string,
+ To unload the currently loaded object, set this property to an empty string,
or set \l sourceComponent to \c undefined. Setting \c source to a
new URL will also cause the item created by the previous URL to be unloaded.
@@ -413,9 +423,12 @@ void QQuickLoader::loadFromSource()
}
\endqml
- To unload the currently loaded item, set this property to an empty string
+ To unload the currently loaded object, set this property to an empty string
or \c undefined.
+ Since QtQuick 2.0 Loader is able to load any type of object; it
+ is not restricted to Item types.
+
\sa source, progress
*/
@@ -597,9 +610,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
item->setWidth(q->width());
if (heightValid && !QQuickItemPrivate::get(item)->heightValid)
item->setHeight(q->height());
- QQml_setParent_noEvent(itemContext, obj);
- QQml_setParent_noEvent(item, q);
item->setParentItem(q);
+ }
+ if (obj) {
+ QQml_setParent_noEvent(itemContext, obj);
+ QQml_setParent_noEvent(obj, q);
itemContext = 0;
}
@@ -623,18 +638,10 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status)
return;
if (status == QQmlIncubator::Ready) {
- QObject *obj = incubator->object();
- item = qmlobject_cast<QQuickItem*>(obj);
- if (item) {
- emit q->itemChanged();
- initResize();
- } else {
- qmlInfo(q) << QQuickLoader::tr("Loader does not support loading non-visual elements.");
- delete itemContext;
- itemContext = 0;
- delete obj;
- emit q->itemChanged();
- }
+ object = incubator->object();
+ item = qmlobject_cast<QQuickItem*>(object);
+ emit q->itemChanged();
+ initResize();
incubator->clear();
} else if (status == QQmlIncubator::Error) {
if (!incubator->errors().isEmpty())
@@ -757,7 +764,7 @@ QQuickLoader::Status QQuickLoader::status() const
}
}
- if (d->item)
+ if (d->object)
return Ready;
return d->source.isEmpty() ? Null : Error;
@@ -797,7 +804,7 @@ qreal QQuickLoader::progress() const
{
Q_D(const QQuickLoader);
- if (d->item)
+ if (d->object)
return 1.0;
if (d->component)
@@ -868,13 +875,15 @@ void QQuickLoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
}
/*!
- \qmlproperty Item QtQuick2::Loader::item
- This property holds the top-level item that is currently loaded.
+ \qmlproperty object QtQuick2::Loader::item
+ This property holds the top-level object that is currently loaded.
+
+ Since QtQuick 2.0 Loader can load any object type.
*/
-QQuickItem *QQuickLoader::item() const
+QObject *QQuickLoader::item() const
{
Q_D(const QQuickLoader);
- return d->item;
+ return d->object;
}
void QQuickLoader::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index c5f544b0e8..ff6e897509 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -57,7 +57,7 @@ class Q_AUTOTEST_EXPORT QQuickLoader : public QQuickImplicitSizeItem
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QQmlComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceComponentChanged)
- Q_PROPERTY(QQuickItem *item READ item NOTIFY itemChanged)
+ Q_PROPERTY(QObject *item READ item NOTIFY itemChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
@@ -85,7 +85,7 @@ public:
bool asynchronous() const;
void setAsynchronous(bool a);
- QQuickItem *item() const;
+ QObject *item() const;
Q_SIGNALS:
void itemChanged();
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 0978911315..2f82fa9f64 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -104,6 +104,7 @@ public:
QUrl source;
QQuickItem *item;
+ QObject *object;
QQmlComponent *component;
QQmlContext *itemContext;
QQuickLoaderIncubator *incubator;
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 69c75d6187..e7cef8c063 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -783,12 +783,17 @@ void tst_QQuickLoader::deleteComponentCrash()
void tst_QQuickLoader::nonItem()
{
QQmlComponent component(&engine, testFileUrl("nonItem.qml"));
- QString err = testFileUrl("nonItem.qml").toString() + ":3:1: QML Loader: Loader does not support loading non-visual elements.";
- QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
QVERIFY(loader);
- QVERIFY(loader->item() == 0);
+ QVERIFY(loader->item());
+
+ QCOMPARE(loader, loader->item()->parent());
+
+ QPointer<QObject> item = loader->item();
+ loader->setActive(false);
+ QVERIFY(!loader->item());
+ QTRY_VERIFY(!item);
delete loader;
}