From f1410debc7905e704b6ed16ae345e43765ef8ef5 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 13 Jan 2021 12:39:44 +0100 Subject: Add a freeze() method to QQmlPropertyMap After freezing a QQmlPropertyMap you cannot add any more properties, but in turn the property access is cached, and therefore faster. Task-number: QTBUG-57792 Change-Id: I2c6d768039c3b59eb2411194e463ee0de55f8bed Reviewed-by: Fabian Kosmale --- src/qml/qml/qqmlopenmetaobject.cpp | 24 +++++++++++++++------- src/qml/qml/qqmlopenmetaobject_p.h | 7 +++++-- src/qml/util/qqmlpropertymap.cpp | 16 +++++++++++++++ src/qml/util/qqmlpropertymap.h | 1 + .../qml/qqmlpropertymap/tst_qqmlpropertymap.cpp | 21 +++++++++++++++++++ 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index b5264fcdfc..ec2d57013f 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -172,8 +172,8 @@ void QQmlOpenMetaObjectTypePrivate::init(const QMetaObject *metaObj) class QQmlOpenMetaObjectPrivate { public: - QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q, bool _autoCreate, QObject *obj) - : q(_q), object(obj), autoCreate(_autoCreate) {} + QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q, QObject *obj) + : q(_q), object(obj) {} struct Property { private: @@ -243,12 +243,12 @@ public: QObject *object; QQmlRefPointer type; QVector *deferredPropertyNames = nullptr; - bool autoCreate; + bool autoCreate = true; bool cacheProperties = false; }; -QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bool automatic) -: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj)) +QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base) +: d(new QQmlOpenMetaObjectPrivate(this, obj)) { d->type.adopt(new QQmlOpenMetaObjectType(base ? base : obj->metaObject())); d->type->d->referers.insert(this); @@ -259,8 +259,8 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bo op->metaObject = this; } -QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *type, bool automatic) -: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj)) +QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *type) +: d(new QQmlOpenMetaObjectPrivate(this, obj)) { d->type = type; d->type->d->referers.insert(this); @@ -438,6 +438,16 @@ void QQmlOpenMetaObject::setCached(bool c) } } +bool QQmlOpenMetaObject::autoCreatesProperties() const +{ + return d->autoCreate; +} + +void QQmlOpenMetaObject::setAutoCreatesProperties(bool autoCreate) +{ + d->autoCreate = autoCreate; +} + int QQmlOpenMetaObject::createProperty(const char *name, const char *) { diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h index f6397c8c59..47bba085b5 100644 --- a/src/qml/qml/qqmlopenmetaobject_p.h +++ b/src/qml/qml/qqmlopenmetaobject_p.h @@ -93,8 +93,8 @@ class QQmlOpenMetaObjectPrivate; class Q_QML_PRIVATE_EXPORT QQmlOpenMetaObject : public QAbstractDynamicMetaObject { public: - QQmlOpenMetaObject(QObject *, const QMetaObject * = nullptr, bool = true); - QQmlOpenMetaObject(QObject *, QQmlOpenMetaObjectType *, bool = true); + QQmlOpenMetaObject(QObject *, const QMetaObject * = nullptr); + QQmlOpenMetaObject(QObject *, QQmlOpenMetaObjectType *); ~QQmlOpenMetaObject() override; QVariant value(const QByteArray &) const; @@ -115,6 +115,9 @@ public: // longer automatically called for new properties. void setCached(bool); + bool autoCreatesProperties() const; + void setAutoCreatesProperties(bool autoCreate); + QQmlOpenMetaObjectType *type() const; void emitPropertyNotification(const QByteArray &propertyName); diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp index e38cf3a2a9..2bf8ab0190 100644 --- a/src/qml/util/qqmlpropertymap.cpp +++ b/src/qml/util/qqmlpropertymap.cpp @@ -203,6 +203,22 @@ void QQmlPropertyMap::clear(const QString &key) d->mo->setValue(key.toUtf8(), QVariant()); } +/*! + \since 6.1 + + Disallows any further properties to be added to this property map. + Existing properties can be modified or cleared. + + In turn, an internal cache is turned on for the existing properties, which + may result in faster access from QML. + */ +void QQmlPropertyMap::freeze() +{ + Q_D(QQmlPropertyMap); + d->mo->setAutoCreatesProperties(false); + d->mo->setCached(true); +} + /*! Returns the value associated with \a key. diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h index 556754c021..de070673d7 100644 --- a/src/qml/util/qqmlpropertymap.h +++ b/src/qml/util/qqmlpropertymap.h @@ -62,6 +62,7 @@ public: void insert(const QString &key, const QVariant &value); void insert(const QVariantHash &values); void clear(const QString &key); + void freeze(); Q_INVOKABLE QStringList keys() const; diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp index 82930b3f4a..75ef397bba 100644 --- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp +++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp @@ -63,6 +63,7 @@ private slots: void QTBUG_35906(); void QTBUG_48136(); void lookupsInSubTypes(); + void freeze(); }; class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus @@ -574,6 +575,26 @@ void tst_QQmlPropertyMap::lookupsInSubTypes() QCOMPARE(object->property("newProperty").toInt(), 42); } +void tst_QQmlPropertyMap::freeze() +{ + QQmlPropertyMap map; + + map.insert(QLatin1String("key1"),100); + map.insert(QLatin1String("key2"),200); + QCOMPARE(map.keys().count(), 2); + QVERIFY(map.contains(QLatin1String("key1"))); + QCOMPARE(map.value(QLatin1String("key1")), QVariant(100)); + QCOMPARE(map.value(QLatin1String("key2")), QVariant(200)); + + map.freeze(); + map.insert(QLatin1String("key3"), 32); + QCOMPARE(map.keys().count(), 2); + QVERIFY(!map.contains("key3")); + + map.insert(QLatin1String("key1"), QStringLiteral("Hello World")); + QCOMPARE(map.value("key1").toString(), QStringLiteral("Hello World")); +} + QTEST_MAIN(tst_QQmlPropertyMap) #include "tst_qqmlpropertymap.moc" -- cgit v1.2.3