aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-05 17:52:00 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-12 20:58:14 +0100
commite35b82922398e09779a162592cdedd50677e63cf (patch)
tree0f28e7e8bbf011c16399c9b84917dc5dda70f88f
parente3cca3df718d8ff298d2d73ce4d6139a3ba620f9 (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.cpp36
-rw-r--r--src/qml/qml/qqmllist.h1
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp22
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;
}