diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-07 13:16:47 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-12 01:31:11 +0200 |
commit | 3422d4adda7480a44a063ab86447c2fe2792fe02 (patch) | |
tree | 21cd120a33e7a9df586f45896d50b5688fdbc782 | |
parent | 6fcaca378b84ada546dc62d72a53a71d0da86ef9 (diff) |
Component.incubateObject() autotest
Change-Id: I37f76d5b273ae4f032c4de5ac8fcbff4204b78fe
Reviewed-on: http://codereview.qt-project.org/6200
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Sanity-Review: Aaron Kennedy <aaron.kennedy@nokia.com>
3 files changed, 127 insertions, 5 deletions
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 8aeeb78a56..eafe8539df 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -1052,6 +1052,57 @@ void QDeclarativeComponent::createObject(QDeclarativeV8Function *args) args->returnValue(object); } +/*! + \qmlmethod object Component::incubateObject(Item parent, object properties, enum mode) + + Creates an incubator for instance of this component. Incubators allow new component + instances to be instantiated asynchronously and not cause freezes in the UI. + + The \a parent argument specifies the parent the created instance will have. Omitting the + parameter or passing null will create anobject with no parent. In this case, a reference + to the created object must be maintained by the application of the object will eventually + be garbage collected. + + The \a properties argument is specified as a map of property-value items which will be + set on the created object during its construction. \a mode may be Qt.Synchronous or + Qt.Asynchronous and controls whether the instance is created synchronously or asynchronously. + The default is asynchronously. In some circumstances, even if Qt.Synchronous is specified, + the incubator may create the object asynchronously. This happens if the component calling + incubateObject() is itself being created asynchronously. + + All three arguments are optional. + + If successful, the method returns an incubator, otherwise null. The incubator has the following + properties: + + \list + \i status The status of the incubator. Valid values are Component.Ready, Component.Loading and + Component.Error. + \i object The created object instance. Will only be available once the incubator is in the + Ready status. + \i onStatusChanged Specifies a callback function to be invoked when the status changes. The + status is passed as a parameter to the callback. + \i forceCompletion() Call to complete incubation synchronously. + \endlist + + The following example demonstrates how to use an incubator: + + \js + var component = Qt.createComponent("Button.qml"); + + var incubator = component.incubateObject(parent, { x: 10, y: 10 }); + if (incubator.status != Component.Ready) { + incubator.onStatusChanged = function(status) { + if (status == Component.Ready) { + print ("Object", incubator.object, "is now ready!"); + } + } + } else { + print ("Object", incubator.object, "is ready immediately!"); + } + \endjs +*/ + void QDeclarativeComponent::incubateObject(QDeclarativeV8Function *args) { Q_D(QDeclarativeComponent); @@ -1067,12 +1118,14 @@ void QDeclarativeComponent::incubateObject(QDeclarativeV8Function *args) if (args->Length() >= 2) { v8::Local<v8::Value> v = (*args)[1]; - if (!v->IsObject() || v->IsArray()) { + if (v->IsNull()) { + } else if (!v->IsObject() || v->IsArray()) { qmlInfo(this) << tr("createObject: value is not an object"); args->returnValue(v8::Null()); return; + } else { + valuemap = v8::Local<v8::Object>::Cast(v); } - valuemap = v8::Local<v8::Object>::Cast(v); } if (args->Length() >= 3) { @@ -1159,7 +1212,7 @@ QDeclarativeComponentExtension::QDeclarativeComponentExtension(QV8Engine *engine #define INITIALPROPERTIES_SOURCE \ "(function(object, values) {"\ "try {"\ - "for(var property in values) {"\ + "for(var property in values) {" \ "try {"\ "var properties = property.split(\".\");"\ "var o = object;"\ @@ -1242,7 +1295,7 @@ void QV8IncubatorResource::setInitialState(QObject *o) v8::Context::Scope scope(engine->context()); v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal); - v8::Handle<v8::Value> args[] = { me, valuemap }; + v8::Handle<v8::Value> args[] = { engine->newQObject(o), valuemap }; v8::Handle<v8::Function>::Cast(function)->Call(engine->global(), 2, args); qPersistentDispose(valuemap); diff --git a/tests/auto/declarative/qdeclarativecomponent/data/incubateObject.qml b/tests/auto/declarative/qdeclarativecomponent/data/incubateObject.qml new file mode 100644 index 0000000000..c11319db30 --- /dev/null +++ b/tests/auto/declarative/qdeclarativecomponent/data/incubateObject.qml @@ -0,0 +1,36 @@ +import QtQuick 2.0 + +Item{ + id: root + + property bool test1: false + property bool test2: false + + property var i + + Component{ + id: component + Item { + property int dummy: 13 + property int dummy2: 26 + } + } + + Component.onCompleted: { + i = component.incubateObject(null, { dummy2: 19 }); + + if (i.status != Component.Loading) return; + if (i.object != null) return; + + i.onStatusChanged = function(status) { + if (status != Component.Ready) return; + if (i.object == null) return; + if (i.object.dummy != 13) return; + if (i.object.dummy2 != 19) return; + test2 = true; + } + + test1 = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index fe947fd201..89148812c5 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -45,22 +45,42 @@ #include <QtDeclarative/qdeclarativecomponent.h> #include <QtDeclarative/qsgitem.h> #include <QtDeclarative/qdeclarativeproperty.h> +#include <QtDeclarative/qdeclarativeincubator.h> #include <qcolor.h> +#include "../../../shared/util.h" + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +class MyIC : public QObject, public QDeclarativeIncubationController +{ + Q_OBJECT +public: + MyIC() { startTimer(5); } +protected: + virtual void timerEvent(QTimerEvent*) { + incubateFor(5); + } +}; class tst_qdeclarativecomponent : public QObject { Q_OBJECT public: - tst_qdeclarativecomponent() { } + tst_qdeclarativecomponent() { engine.setIncubationController(&ic); } private slots: void null(); void loadEmptyUrl(); void qmlCreateObject(); void qmlCreateObjectWithProperties(); + void qmlIncubateObject(); private: QDeclarativeEngine engine; + MyIC ic; }; void tst_qdeclarativecomponent::null() @@ -91,6 +111,19 @@ void tst_qdeclarativecomponent::loadEmptyUrl() QCOMPARE(error.description(), QLatin1String("Invalid empty URL")); } +void tst_qdeclarativecomponent::qmlIncubateObject() +{ + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/incubateObject.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test1").toBool(), true); + QCOMPARE(object->property("test2").toBool(), false); + + QTRY_VERIFY(object->property("test2").toBool() == true); + + delete object; +} + void tst_qdeclarativecomponent::qmlCreateObject() { QDeclarativeEngine engine; |