From aa40f956bab22678b62f630af97f51f9e8fab9f8 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Thu, 27 Jan 2011 16:34:07 +1000 Subject: Fix righ-to-left support in text components. In text, textEdit and textInput, the layout of the text should automatically align to the right if the it is deemed to be right-to-left text. Task-number: QTBUG-15880 Reviewed-by: Bea Lam --- src/declarative/qml/qdeclarativecomponent.cpp | 67 +++++++++++++++++----- src/declarative/qml/qdeclarativecomponent.h | 1 + src/declarative/qml/qdeclarativecomponent_p.h | 2 + .../data/createObjectWithScript.qml | 21 +++++++ .../tst_qdeclarativecomponent.cpp | 28 +++++++++ 5 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml 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 #include #include #include #include +#include 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 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 #include #include +#include +#include #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(); + QVERIFY(testObject1); + QVERIFY(testObject1->parent() == object); + QCOMPARE(testObject1->property("x").value(), 17); + QCOMPARE(testObject1->property("y").value(), 17); + QCOMPARE(testObject1->property("color").value(), QColor(255,255,255)); + + QObject *testObject2 = object->property("declarativeitem").value(); + QVERIFY(testObject2); + QVERIFY(testObject2->parent() == object); + QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2"); + QCOMPARE(testObject2->property("x").value(), 17); + QCOMPARE(testObject2->property("y").value(), 17); + QCOMPARE(testObject2->property("testBool").value(), true); + QCOMPARE(testObject2->property("testInt").value(), 17); + QCOMPARE(testObject2->property("testObject").value(), object); +} + QTEST_MAIN(tst_qdeclarativecomponent) #include "tst_qdeclarativecomponent.moc" -- cgit v0.12