summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp67
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h1
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h2
-rw-r--r--tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml21
-rw-r--r--tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp28
5 files changed, 106 insertions, 13 deletions
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index 8865ddd..bd6e2d8 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -54,11 +54,13 @@
#include "private/qdeclarativescriptparser_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeenginedebug_p.h"
+#include <QtScript/qscriptvalueiterator.h>
#include <QStack>
#include <QStringList>
#include <QtCore/qdebug.h>
#include <QApplication>
+#include <qdeclarativeinfo.h>
QT_BEGIN_NAMESPACE
@@ -613,7 +615,7 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
}
/*!
- \qmlmethod object Component::createObject(Item parent)
+ \qmlmethod object Component::createObject(Item parent, Script valuemap = null)
Creates and returns an object instance of this component that will have the given
\a parent. Returns null if object creation fails.
@@ -631,6 +633,12 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
it is not destroyed by the garbage collector. This is regardless of Item.parent being set afterwards,
since setting the Item parent does not change object ownership; only the graphical parent is changed.
+ Since QtQuick 1.1, a map of property values can be optionally passed to the method that applies values to the object's properties
+ before its creation is finalised. This will avoid binding issues that can occur when the object is
+ instantiated before property bindings have been set. For example:
+
+ \code component.createObject(parent, {"x": 100, "y": 100, "specialProperty": someObject}); \endcode
+
Dynamically created instances can be deleted with the \c destroy() method.
See \l {Dynamic Object Management in QML} for more information.
*/
@@ -646,25 +654,46 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
QScriptValue QDeclarativeComponent::createObject(QObject* parent)
{
Q_D(QDeclarativeComponent);
- QDeclarativeContext* ctxt = creationContext();
- if(!ctxt && d->engine)
- ctxt = d->engine->rootContext();
+ return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
+}
+
+/*!
+ \internal
+ Overloadable method allows properties to be set during creation
+*/
+QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
+{
+ Q_D(QDeclarativeComponent);
+
+ if (valuemap.isObject() && !valuemap.isArray()) {
+ qmlInfo(this) << tr("creatObject: value is not an object");
+ return QScriptValue(QScriptValue::NullValue);
+ }
+ return d->createObject(parent, valuemap);
+}
+
+QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
+{
+ Q_Q(QDeclarativeComponent);
+ QDeclarativeContext* ctxt = q->creationContext();
+ if(!ctxt && engine)
+ ctxt = engine->rootContext();
if (!ctxt)
return QScriptValue(QScriptValue::NullValue);
- QObject* ret = beginCreate(ctxt);
+ QObject* ret = q->beginCreate(ctxt);
if (!ret) {
- completeCreate();
+ q->completeCreate();
return QScriptValue(QScriptValue::NullValue);
}
- if (parent) {
- ret->setParent(parent);
+ if (publicParent) {
+ ret->setParent(publicParent);
QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
bool needParent = false;
for (int ii = 0; ii < functions.count(); ++ii) {
- QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent);
+ QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
if (res == QDeclarativePrivate::Parented) {
needParent = false;
break;
@@ -673,14 +702,26 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent)
}
}
- if (needParent)
+ if (needParent)
qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
}
- completeCreate();
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine);
+ QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
QDeclarativeData::get(ret, true)->setImplicitDestructible();
- return priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
+ QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
+
+ if (valuemap.isObject() && !valuemap.isArray()) {
+ //Iterate through and assign properties
+ QScriptValueIterator it(valuemap);
+ while (it.hasNext()) {
+ it.next();
+ newObject.setProperty(it.name(), it.value(), QScriptValue::KeepExistingFlags);
+ }
+ }
+
+ q->completeCreate();
+
+ return newObject;
}
/*!
diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h
index 6f28f2e..3d318c3 100644
--- a/src/declarative/qml/qdeclarativecomponent.h
+++ b/src/declarative/qml/qdeclarativecomponent.h
@@ -110,6 +110,7 @@ Q_SIGNALS:
protected:
QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent);
Q_INVOKABLE QScriptValue createObject(QObject* parent);
+ Q_INVOKABLE QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning
private:
QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent);
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index 02a6ce8..f8bec2b 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -116,6 +116,8 @@ public:
ConstructionState *state);
static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state);
+ QScriptValue createObject(QObject *publicParent, const QScriptValue valuemap);
+
QDeclarativeEngine *engine;
QDeclarativeGuardedContextData creationContext;
diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml
new file mode 100644
index 0000000..60d4c44
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml
@@ -0,0 +1,21 @@
+import QtQuick 1.0
+
+Item{
+ id: root
+ property QtObject declarativerectangle : null
+ property QtObject declarativeitem : null
+ Component{id: a; Rectangle{} }
+ Component{
+ id: b
+ Item{
+ property bool testBool: false
+ property int testInt: null
+ property QtObject testObject: null
+ }
+ }
+
+ Component.onCompleted: {
+ root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white"});
+ root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root});
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
index 4db538e..829b762 100644
--- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
+++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp
@@ -44,6 +44,8 @@
#include <QtGui/qgraphicsitem.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeitem.h>
+#include <qcolor.h>
#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
@@ -60,6 +62,7 @@ private slots:
void null();
void loadEmptyUrl();
void qmlCreateObject();
+ void qmlCreatObjectWithScript();
private:
QDeclarativeEngine engine;
@@ -118,6 +121,31 @@ void tst_qdeclarativecomponent::qmlCreateObject()
QCOMPARE(testObject3->metaObject()->className(), "QDeclarativeGraphicsWidget");
}
+void tst_qdeclarativecomponent::qmlCreatObjectWithScript()
+{
+ QDeclarativeEngine engine;
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/createObjectWithScript.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QObject *testObject1 = object->property("declarativerectangle").value<QObject*>();
+ QVERIFY(testObject1);
+ QVERIFY(testObject1->parent() == object);
+ QCOMPARE(testObject1->property("x").value<int>(), 17);
+ QCOMPARE(testObject1->property("y").value<int>(), 17);
+ QCOMPARE(testObject1->property("color").value<QColor>(), QColor(255,255,255));
+
+ QObject *testObject2 = object->property("declarativeitem").value<QObject*>();
+ QVERIFY(testObject2);
+ QVERIFY(testObject2->parent() == object);
+ QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2");
+ QCOMPARE(testObject2->property("x").value<int>(), 17);
+ QCOMPARE(testObject2->property("y").value<int>(), 17);
+ QCOMPARE(testObject2->property("testBool").value<bool>(), true);
+ QCOMPARE(testObject2->property("testInt").value<int>(), 17);
+ QCOMPARE(testObject2->property("testObject").value<QObject*>(), object);
+}
+
QTEST_MAIN(tst_qdeclarativecomponent)
#include "tst_qdeclarativecomponent.moc"