aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2018-10-26 14:04:42 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-02-21 10:54:54 +0000
commit3b9ecd6174a7a6eacf22b5088b66b203160bfdbd (patch)
tree0228c5e6dc3cc6b3ff02ed0b87d1386be8dd68ce
parent407e2769c7b7909fdb2979090e71fa636f109a04 (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.cpp12
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h2
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp21
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;