diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2022-05-09 17:35:35 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2022-05-12 17:36:12 +0200 |
commit | 5cd59bff0c2f077ab47c40710a5267c06d3d2aa9 (patch) | |
tree | b3a1f34ce103f1834f20f5921c33f02ad646cff4 /src/qml/qml | |
parent | c8f9cb050df690696422df2f79f1124340037547 (diff) |
Support querying indirect extensions for a given object
Introduce a private version of qmlExtendedObject() that returns an
index-based extension (where 0 represents an extension on the leaf type
and N represents a (N - 1)th base type's extension)
Teach QQmlProxyMetaObject to distinguish different extension proxies.
Its custom metaCall can now query up to 128 extensions (should be enough
for the user needs)
Change-Id: I5520a1e84501f1f9fe6a8e77d8269009a12c255c
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqml.cpp | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject_p.h | 18 |
4 files changed, 32 insertions, 7 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 728250dcf2..3c9f930eb9 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -151,6 +151,11 @@ QObject *qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc QObject *qmlExtendedObject(QObject *object) { + return QQmlPrivate::qmlExtendedObject(object, 0); +} + +QObject *QQmlPrivate::qmlExtendedObject(QObject *object, int index) +{ if (!object) return nullptr; @@ -161,8 +166,8 @@ QObject *qmlExtendedObject(QObject *object) const int id = d->metaObject->metaCall( object, QMetaObject::CustomCall, - QQmlProxyMetaObject::ExtensionObjectId, &result); - if (id != QQmlProxyMetaObject::ExtensionObjectId) + QQmlProxyMetaObject::extensionObjectId(index), &result); + if (id != QQmlProxyMetaObject::extensionObjectId(index)) return nullptr; return static_cast<QObject *>(result); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 817f25c112..9754f9dcf3 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -1087,6 +1087,8 @@ namespace QQmlPrivate }; } + Q_QML_EXPORT QObject *qmlExtendedObject(QObject *, int); + } // namespace QQmlPrivate QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index e05c63794c..4844ca3720 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -144,11 +144,15 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void break; } - case QMetaObject::CustomCall: - if (id != ExtensionObjectId) + case QMetaObject::CustomCall: { + if ((id & ~MaxExtensionCount) != ExtensionObjectId) break; - a[0] = getProxy(0); + int index = id & MaxExtensionCount; + if (qsizetype(index) >= metaObjects->size()) + break; + a[0] = getProxy(index); return id; + } default: break; } diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h index a58818f22a..965d86c70f 100644 --- a/src/qml/qml/qqmlproxymetaobject_p.h +++ b/src/qml/qml/qqmlproxymetaobject_p.h @@ -65,8 +65,6 @@ QT_BEGIN_NAMESPACE class QQmlProxyMetaObject : public QDynamicMetaObjectData { public: - enum { ExtensionObjectId = std::numeric_limits<int>::min() }; - struct ProxyData { typedef QObject *(*CreateFunc)(QObject *); QMetaObject *metaObject; @@ -78,6 +76,13 @@ public: QQmlProxyMetaObject(QObject *, QList<ProxyData> *); ~QQmlProxyMetaObject(); + static constexpr int extensionObjectId(int id) noexcept + { + Q_ASSERT(id >= 0); + Q_ASSERT(id <= MaxExtensionCount); // MaxExtensionCount is a valid index + return ExtensionObjectId | id; + } + protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; QMetaObject *toDynamicMetaObject(QObject *) override; @@ -91,6 +96,15 @@ private: QDynamicMetaObjectData *parent; QMetaObject *metaObject; QObject *object; + + // ExtensionObjectId acts as a flag for whether we should interpret a + // QMetaObject::CustomCall as a call to fetch the extension object (see + // QQmlProxyMetaObject::metaCall()). MaxExtensionCount is a limit on how + // many extensions we can query via such mechanism + enum : int { + MaxExtensionCount = 127, // magic number so that low bits are all '1' + ExtensionObjectId = ~MaxExtensionCount, + }; }; QT_END_NAMESPACE |