From 14e247e4b94df17ed62750b4468c2ac25aabe30f Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Wed, 9 May 2012 12:21:41 +1000 Subject: [PATCH] Fix composite type property support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The metatype changes caused a regression in composite type properties for which there was no autotest. In particular, declarative previously used the transitional QMetaType::registerType() function, whose implementation specifies a zero-size, which means that accessing a property of that type via QObject::property would fail. This commit adds some unit tests to track the issue, and also fixes the implementation of QQmlEnginePrivate::registerCompositeType to use the updated metatype registration functions. Task-number: QTBUG-25697 Change-Id: Ic4abc1711aee8cf4a50a2ef1769465ef73f5d022 Reviewed-by: Jędrzej Nowacki --- src/qml/qml/qqmlengine.cpp | 35 +++++------ .../auto/qml/qqmlproperty/data/SecondComponent.qml | 6 ++ .../data/componentDir/FirstComponent.qml | 5 ++ .../data/registeredCompositeTypeProperty.qml | 32 +++++++++ tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 68 ++++++++++++++++++++ 5 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 tests/auto/qml/qqmlproperty/data/SecondComponent.qml create mode 100644 tests/auto/qml/qqmlproperty/data/componentDir/FirstComponent.qml create mode 100644 tests/auto/qml/qqmlproperty/data/registeredCompositeTypeProperty.qml diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 849c83d..788d5ed 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1651,21 +1651,6 @@ QString QQmlEngine::offlineStoragePath() const return d->offlineStoragePath; } -static void voidptr_destructor(void *v) -{ - void **ptr = (void **)v; - delete ptr; -} - -static void *voidptr_constructor(const void *v) -{ - if (!v) { - return new void*; - } else { - return new void*(*(void **)v); - } -} - QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo) { Q_Q(QQmlEngine); @@ -1878,10 +1863,22 @@ void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data) QByteArray ptr = name + '*'; QByteArray lst = "QQmlListProperty<" + name + '>'; - int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor, - voidptr_constructor); - int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor, - voidptr_constructor); + int ptr_type = QMetaType::registerNormalizedType(ptr, + qMetaTypeDeleteHelper, + qMetaTypeCreateHelper, + qMetaTypeDestructHelper, + qMetaTypeConstructHelper, + sizeof(QObject*), + static_cast >(QtPrivate::QMetaTypeTypeFlags::Flags), + data->root); + int lst_type = QMetaType::registerNormalizedType(lst, + qMetaTypeDeleteHelper >, + qMetaTypeCreateHelper >, + qMetaTypeDestructHelper >, + qMetaTypeConstructHelper >, + sizeof(QQmlListProperty), + static_cast >(QtPrivate::QMetaTypeTypeFlags >::Flags), + static_cast(0)); data->addref(); diff --git a/tests/auto/qml/qqmlproperty/data/SecondComponent.qml b/tests/auto/qml/qqmlproperty/data/SecondComponent.qml new file mode 100644 index 0000000..45d81c9 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/SecondComponent.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Item { + property string a: "Hello, World" + property bool b: false +} diff --git a/tests/auto/qml/qqmlproperty/data/componentDir/FirstComponent.qml b/tests/auto/qml/qqmlproperty/data/componentDir/FirstComponent.qml new file mode 100644 index 0000000..1b7614d --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/componentDir/FirstComponent.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property int a: 10 +} diff --git a/tests/auto/qml/qqmlproperty/data/registeredCompositeTypeProperty.qml b/tests/auto/qml/qqmlproperty/data/registeredCompositeTypeProperty.qml new file mode 100644 index 0000000..92e1675 --- /dev/null +++ b/tests/auto/qml/qqmlproperty/data/registeredCompositeTypeProperty.qml @@ -0,0 +1,32 @@ +import QtQuick 2.0 +import "componentDir" + +Item { + id: root + + property FirstComponent first: FirstComponent { } + property FirstComponent second + property SecondComponent third: SecondComponent { } + + property list fclist: [ + FirstComponent { + a: 15 + } + ] + property list sclistOne: [ + SecondComponent { + a: "G'day, World" + }, + SecondComponent { }, + SecondComponent { + b: true + } + ] + property list sclistTwo + + Component.onCompleted: { + var c1 = Qt.createComponent("./componentDir/FirstComponent.qml"); + var o1 = c1.createObject(root); + second = o1; + } +} diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index a65693b..3957dee 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -135,6 +135,7 @@ private slots: void noContext(); void assignEmptyVariantMap(); void warnOnInvalidBinding(); + void registeredCompositeTypeProperty(); void copy(); private: @@ -189,6 +190,73 @@ void tst_qqmlproperty::qmlmetaproperty() delete obj; } +void tst_qqmlproperty::registeredCompositeTypeProperty() +{ + // Composite type properties + { + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml")); + QObject *obj = component.create(); + QVERIFY(obj); + + // create property accessors and check types. + QQmlProperty p1(obj, "first"); + QQmlProperty p2(obj, "second"); + QQmlProperty p3(obj, "third"); + QVERIFY(p1.propertyType() == p2.propertyType()); + QVERIFY(p1.propertyType() != p3.propertyType()); + + // check that the values are retrievable from CPP + QVariant first = obj->property("first"); + QVariant second = obj->property("second"); + QVariant third = obj->property("third"); + QVERIFY(first.isValid()); + QVERIFY(second.isValid()); + QVERIFY(third.isValid()); + // ensure that conversion from qobject-derived-ptr to qobject-ptr works. + QVERIFY(first.value()); + QVERIFY(second.value()); + QVERIFY(third.value()); + + // check that the values retrieved via QQmlProperty match. + QCOMPARE(p1.read(), first); + QCOMPARE(p2.read(), second); + QCOMPARE(p3.read(), third); + + delete obj; + } + + // List-of-composite-type type properties + { + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml")); + QObject *obj = component.create(); + QVERIFY(obj); + + // create list property accessors and check types + QQmlProperty lp1(obj, "fclist"); + QQmlProperty lp2(obj, "sclistOne"); + QQmlProperty lp3(obj, "sclistTwo"); + QVERIFY(lp1.propertyType() != lp2.propertyType()); + QVERIFY(lp2.propertyType() == lp3.propertyType()); + + // check that the list values are retrievable from CPP + QVariant firstList = obj->property("fclist"); + QVariant secondList = obj->property("sclistOne"); + QVariant thirdList = obj->property("sclistTwo"); + QVERIFY(firstList.isValid()); + QVERIFY(secondList.isValid()); + QVERIFY(thirdList.isValid()); + + // check that the values retrieved via QQmlProperty match. + QCOMPARE(lp1.read(), firstList); + QCOMPARE(lp2.read(), secondList); + QCOMPARE(lp3.read(), thirdList); + + delete obj; + } +} + class PropertyObject : public QObject { Q_OBJECT -- 1.7.2.5