diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-05 17:52:00 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-12 20:58:14 +0100 |
commit | e35b82922398e09779a162592cdedd50677e63cf (patch) | |
tree | 0f28e7e8bbf011c16399c9b84917dc5dda70f88f | |
parent | e3cca3df718d8ff298d2d73ce4d6139a3ba620f9 (diff) |
QQmlListReference: Allow construction from a QVariant
Currently there is no public API to transform a QVariant holding a
QQmlListProperty into a QQmlListReference. We cannot pass
QQmlListProperty itself as that is templated. The metatype-based casting
is somewhat evil, but not more so than what we already have in the other
ctor.
Change-Id: I2d56499b1fd188613bc71016cb00ec23081d3cea
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
-rw-r--r-- | src/qml/qml/qqmllist.cpp | 36 | ||||
-rw-r--r-- | src/qml/qml/qqmllist.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp | 22 |
3 files changed, 59 insertions, 0 deletions
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index cffdf7c907..fe0b820a1e 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -120,6 +120,42 @@ QQmlListReference::QQmlListReference() } /*! +\since 6.1 + +Constructs a QQmlListReference from a QVariant \a variant containing a QQmlListProperty. If +\a variant does not contain a list property, an invalid QQmlListReference is created. If the object +owning the list property is destroyed after the reference is constructed, it will automatically +become invalid. That is, it is safe to hold QQmlListReference instances even after the object is +deleted. + +The \a engine is required to look up the element type, which may be a dynamically created QML type. +If it's omitted, only pre-registered types are available. +*/ +QQmlListReference::QQmlListReference(const QVariant &variant, QQmlEngine *engine) + : d(nullptr) +{ + const QMetaType t = variant.metaType(); + if (!(t.flags() & QMetaType::IsQmlList)) + return; + + QQmlEnginePrivate *p = engine ? QQmlEnginePrivate::get(engine) : nullptr; + const int listType = p ? p->listType(t.id()) : QQmlMetaType::listType(t.id()); + if (listType == -1) + return; + + d = new QQmlListReferencePrivate; + d->propertyType = t.id(); + d->elementType = p + ? p->rawMetaObjectForType(listType) + : QQmlMetaType::qmlType(listType).baseMetaObject(); + + d->property.~QQmlListProperty(); + t.construct(&d->property, variant.constData()); + + d->object = d->property.object; +} + +/*! Constructs a QQmlListReference for \a object's \a property. If \a property is not a list property, an invalid QQmlListReference is created. If \a object is destroyed after the reference is constructed, it will automatically become invalid. That is, it is safe to hold diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h index 3cc353ef30..abf4ec6ebf 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -197,6 +197,7 @@ class Q_QML_EXPORT QQmlListReference { public: QQmlListReference(); + explicit QQmlListReference(const QVariant &variant, QQmlEngine *engine = nullptr); QQmlListReference(QObject *, const char *property, QQmlEngine * = nullptr); QQmlListReference(const QQmlListReference &); QQmlListReference &operator=(const QQmlListReference &); diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp index bf5ee92374..c6accb3908 100644 --- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp +++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp @@ -179,6 +179,17 @@ void tst_qqmllistreference::qmllistreference() tt.data.append(&tt); QCOMPARE(r.count(), 1); + + const QMetaObject *m = tt.metaObject(); + const int index = m->indexOfProperty("data"); + const QMetaProperty prop = m->property(index); + const QVariant var = prop.read(&tt); + + QQmlListReference fromVar(var); + QVERIFY(fromVar.isValid()); + QCOMPARE(fromVar.count(), 1); + fromVar.append(&tt); + QCOMPARE(tt.data.count(), 2); } void tst_qqmllistreference::qmllistreference_invalid() @@ -805,6 +816,17 @@ void tst_qqmllistreference::engineTypes() QVERIFY(ref.listElementType()); QVERIFY(ref.listElementType() != &QObject::staticMetaObject); + + const QMetaObject *m = o->metaObject(); + const int index = m->indexOfProperty("myList"); + const QMetaProperty prop = m->property(index); + const QVariant var = prop.read(o); + + QQmlListReference fromVar(var, &engine); + QVERIFY(fromVar.isValid()); + QCOMPARE(fromVar.count(), 2); + QCOMPARE(fromVar.listElementType(), ref.listElementType()); + delete o; } |