diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-04-26 11:05:41 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-30 01:52:57 +0200 |
commit | 0e8af75e877d46cb656d03cf575804f2c17ec33f (patch) | |
tree | 6b3466202d1a62b7c5d7fb5aff904599ee8d3ca5 | |
parent | 1b48bb5602bd90dc78e1ff09207f682f6a43edd2 (diff) |
Ensure external value types are initialized before write
Ensure that the logic used when writing to a property having a value
type provided by an external module matches that used for properties
of internal value types.
Change-Id: I925b8b30a211ef813e2a51134411a162b0b146b5
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 15 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 20 | ||||
-rw-r--r-- | src/quick/util/qquickglobal.cpp | 27 | ||||
-rw-r--r-- | tests/auto/qml/qqmlvaluetypes/data/initializeByWrite.qml | 27 | ||||
-rw-r--r-- | tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp | 12 |
6 files changed, 97 insertions, 6 deletions
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index 1f8de4fae8..c5228d07c3 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -175,6 +175,20 @@ QVariant QQmlValueTypeProvider::createVariantFromString(int type, const QString return QVariant(); } +bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs) +{ + Q_ASSERT(lhs); + Q_ASSERT(rhs); + + QQmlValueTypeProvider *p = this; + do { + if (p->equal(type, lhs, rhs)) + return true; + } while ((p = p->next)); + + return false; +} + bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst, size_t n) { Q_ASSERT(src); @@ -226,6 +240,7 @@ bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_ bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; } bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; } bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; } +bool QQmlValueTypeProvider::equal(int, const void *, const void *) { return false; } bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; } bool QQmlValueTypeProvider::read(int, const void *, int, void *) { return false; } bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; } diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index 04711ae3fc..e5515b60cb 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -158,6 +158,7 @@ public: QVariant createVariantFromString(const QString &); QVariant createVariantFromString(int, const QString &, bool *); + bool equalValueType(int, const void *, const void *); bool storeValueType(int, const void *, void *, size_t); bool readValueType(int, const void *, int, void *); bool writeValueType(int, const void *, void *, size_t); @@ -176,6 +177,7 @@ private: virtual bool variantFromString(const QString &, QVariant *); virtual bool variantFromString(int, const QString &, QVariant *); + virtual bool equal(int, const void *, const void *); virtual bool store(int, const void *, void *, size_t); virtual bool read(int, const void *, int, void *); virtual bool write(int, const void *, void *, size_t); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index b39ca34739..97781617de 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -116,6 +116,8 @@ public: inline void setDataType(int t); + inline void ensureValueType(int); + private: int type; void *data[6]; // Large enough to hold all types @@ -409,6 +411,15 @@ void QQmlVMEVariant::setDataType(int t) type = t; } +void QQmlVMEVariant::ensureValueType(int t) +{ + if (type != t) { + cleanup(); + type = t; + QQml_valueTypeProvider()->initValueType(t, dataPtr(), dataSize()); + } +} + QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint() { callback = &vmecallback; @@ -645,12 +656,9 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) writeProperty(id, *reinterpret_cast<QVariant *>(a[0])); break; default: - if (! data[id].dataType()) - QQml_valueTypeProvider()->initValueType(t, data[id].dataPtr(), data[id].dataSize()); - needActivate = QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize()); - if (needActivate) { - data[id].setDataType(t); - } + data[id].ensureValueType(t); + needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr()); + QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize()); break; } } diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index b99cb7a1d4..6869d480d5 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -178,6 +178,13 @@ private: }; +// Note: The functions in this class provide handling only for the types +// that the QML engine will currently actually call them for, so many +// appear incompletely implemented. For some functions, the implementation +// would be obvious, but for others (particularly create and createFromString) +// the exact semantics are unknown. For this reason unused functionality +// has been omitted. + class QQuickValueTypeProvider : public QQmlValueTypeProvider { public: @@ -404,6 +411,26 @@ public: return false; } + template<typename T> + bool typedEqual(const void *lhs, const void *rhs) + { + return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs))); + } + + bool equal(int type, const void *lhs, const void *rhs) + { + switch (type) { + case QMetaType::QColor: + return typedEqual<QColor>(lhs, rhs); + case QMetaType::QVector3D: + return typedEqual<QVector3D>(lhs, rhs); + case QMetaType::QVector4D: + return typedEqual<QVector4D>(lhs, rhs); + } + + return false; + } + bool store(int type, const void *src, void *dst, size_t n) { switch (type) { diff --git a/tests/auto/qml/qqmlvaluetypes/data/initializeByWrite.qml b/tests/auto/qml/qqmlvaluetypes/data/initializeByWrite.qml new file mode 100644 index 0000000000..8493dd4d7e --- /dev/null +++ b/tests/auto/qml/qqmlvaluetypes/data/initializeByWrite.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 + +ListView { + property bool test: false + + width: 200 + height: 200 + model: 20 + + delegate: Text { + text: qsTr(props.titleText).arg(index) + color: props.titleColor + font.pointSize: props.titlePointSize + } + + property QtObject props: QtObject { + property string titleText: "List Item %1 Title" + property color titleColor: Qt.rgba(1, 0, 0, 0) + property int titlePointSize: 18 + } + + Component.onCompleted: { + test = (props.titleText == "List Item %1 Title") && + (props.titleColor == Qt.rgba(1, 0, 0, 0)) && + (props.titlePointSize == 18) + } +} diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 359653caa4..0c890dea74 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -94,6 +94,7 @@ private slots: void varAssignment(); void bindingsSpliceCorrectly(); void nonValueTypeComparison(); + void initializeByWrite(); private: QQmlEngine engine; @@ -1334,6 +1335,17 @@ void tst_qqmlvaluetypes::nonValueTypeComparison() delete object; } +void tst_qqmlvaluetypes::initializeByWrite() +{ + QQmlComponent component(&engine, testFileUrl("initializeByWrite.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; +} + QTEST_MAIN(tst_qqmlvaluetypes) #include "tst_qqmlvaluetypes.moc" |