diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2018-10-26 14:04:42 +0200 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2019-02-21 10:54:54 +0000 |
commit | 3b9ecd6174a7a6eacf22b5088b66b203160bfdbd (patch) | |
tree | 0228c5e6dc3cc6b3ff02ed0b87d1386be8dd68ce | |
parent | 407e2769c7b7909fdb2979090e71fa636f109a04 (diff) |
QQmlPropertyCache: support setting an explicit metaObject revision
When creating a QQmlPropertyCache for a QMetaObject, there were
currently no way to specify which revision to use. Normally this
is not needed, since when creating property caches for types
declared in QML, the correct revision would be filled in later, based
on the import version found in the QML file.
But sometimes we need to create a QQmlPropertyCache for a QMetaObject
created in C++, that has no associated QML file and import version.
And if that meta object has revisioned properties, we need to
specify which revision of the meta object the cache should represent.
Otherwise, the revision would just be 0, which means that revisoned
properties would not be found by the V4 runtime later.
As an example, QQmlAdaptorModel has a set of classes that wraps various
models (QAIM, arrays, etc). When a new delegate item is created by a
view, an instance of a model class will be created as well (from C++).
This instance will be set as context object for the delegate
item, enabling properties such as index, row, column and model roles.
But since row and column should a revision (currently they
don't), we need to be able to specify that the property cache should
have a revision that matches the import version of the view. That way, we
can ensure that they don't shadow any existing row and column properties
that might exist in the application from before, and as such, cause
regressions.
This patch will add an extra argument to the constructor that lets
you specify which revision of the QMetaObject to use.
Task-number: QTBUG-70031
Change-Id: I1c245a0c8b6f071e35865966fedc97f2839cd2f3
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp | 21 |
3 files changed, 33 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 95bdcf13e8..629717dd9f 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -252,12 +252,22 @@ QQmlPropertyCache::QQmlPropertyCache() /*! Creates a new QQmlPropertyCache of \a metaObject. */ -QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject) +QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision) : QQmlPropertyCache() { Q_ASSERT(metaObject); update(metaObject); + + if (metaObjectRevision > 0) { + // Set the revision of the meta object that this cache describes to be + // 'metaObjectRevision'. This is useful when constructing a property cache + // from a type that was created directly in C++, and not through QML. For such + // types, the revision for each recorded QMetaObject would normally be zero, which + // would exclude any revisioned properties. + for (int metaObjectOffset = 0; metaObjectOffset < allowedRevisionCache.size(); ++metaObjectOffset) + allowedRevisionCache[metaObjectOffset] = metaObjectRevision; + } } QQmlPropertyCache::~QQmlPropertyCache() diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 0785910cec..a7cbd506f9 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -394,7 +394,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount { public: QQmlPropertyCache(); - QQmlPropertyCache(const QMetaObject *); + QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0); ~QQmlPropertyCache() override; void update(const QMetaObject *); diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp index f577a091eb..69c6ce2d35 100644 --- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp +++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp @@ -45,6 +45,7 @@ public: private slots: void properties(); void propertiesDerived(); + void revisionedProperties(); void methods(); void methodsDerived(); void signalHandlers(); @@ -84,11 +85,13 @@ class DerivedObject : public BaseObject Q_OBJECT Q_PROPERTY(int propertyC READ propertyC NOTIFY propertyCChanged) Q_PROPERTY(QString propertyD READ propertyD NOTIFY propertyDChanged) + Q_PROPERTY(int propertyE READ propertyE NOTIFY propertyEChanged REVISION 1) public: DerivedObject(QObject *parent = nullptr) : BaseObject(parent) {} int propertyC() const { return 0; } QString propertyD() const { return QString(); } + int propertyE() const { return 0; } public Q_SLOTS: void slotB() {} @@ -96,6 +99,7 @@ public Q_SLOTS: Q_SIGNALS: void propertyCChanged(); void propertyDChanged(); + Q_REVISION(1) void propertyEChanged(); void signalB(); }; @@ -149,6 +153,23 @@ void tst_qqmlpropertycache::propertiesDerived() QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyD")); } +void tst_qqmlpropertycache::revisionedProperties() +{ + // Check that if you create a QQmlPropertyCache from a QMetaObject together + // with an explicit revision, the cache will then, and only then, report a + // property with a matching revision as available. + DerivedObject object; + const QMetaObject *metaObject = object.metaObject(); + + QQmlRefPointer<QQmlPropertyCache> cacheWithoutVersion(new QQmlPropertyCache(metaObject)); + QQmlRefPointer<QQmlPropertyCache> cacheWithVersion(new QQmlPropertyCache(metaObject, 1)); + QQmlPropertyData *data; + + QVERIFY((data = cacheProperty(cacheWithoutVersion, "propertyE"))); + QCOMPARE(cacheWithoutVersion->isAllowedInRevision(data), false); + QCOMPARE(cacheWithVersion->isAllowedInRevision(data), true); +} + void tst_qqmlpropertycache::methods() { QQmlEngine engine; |