aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-04-26 11:05:41 +1000
committerQt by Nokia <qt-info@nokia.com>2012-04-30 01:52:57 +0200
commit0e8af75e877d46cb656d03cf575804f2c17ec33f (patch)
tree6b3466202d1a62b7c5d7fb5aff904599ee8d3ca5
parent1b48bb5602bd90dc78e1ff09207f682f6a43edd2 (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.cpp15
-rw-r--r--src/qml/qml/qqmlglobal_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp20
-rw-r--r--src/quick/util/qquickglobal.cpp27
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/initializeByWrite.qml27
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp12
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"