diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-03-14 15:56:28 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-03-23 23:21:56 +0100 |
commit | cc6bd22b61cff5b992b594b69552c8f41f65f13b (patch) | |
tree | 13aad8f781c767d793d29a1499f94383052d5578 | |
parent | 00b59c391e88d37dd09f187000416a3501a1e009 (diff) |
Add public API for retrieving the extension object
Change-Id: I28bc1c177cb78d85d844c7a5cd5b6710db8fd65d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r-- | src/qml/doc/src/qmlfunctions.qdoc | 10 | ||||
-rw-r--r-- | src/qml/qml/qqml.cpp | 19 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject.cpp | 61 | ||||
-rw-r--r-- | src/qml/qml/qqmlproxymetaobject_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 4 |
6 files changed, 74 insertions, 23 deletions
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index b8524b3e93..5209027c84 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -992,6 +992,16 @@ */ /*! + \fn QObject *qmlExtendedObject(const QObject *base) + \relates QQmlEngine + + This function returns the extension object that belongs to \a base, if there is any. + Otherwise it returns \c nullptr. + + \sa QML_EXTENDED +*/ + +/*! \fn int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *(*callback)(QQmlEngine *, QJSEngine *)) \relates QQmlEngine diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index d8d366a716..8859dea711 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -149,6 +149,25 @@ QObject *qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc return resolveAttachedProperties(func, data, object, create); } +QObject *qmlExtendedObject(QObject *object) +{ + if (!object) + return nullptr; + + void *result = nullptr; + QObjectPrivate *d = QObjectPrivate::get(object); + if (!d->metaObject) + return nullptr; + + const int id = d->metaObject->metaCall( + object, QMetaObject::CustomCall, + QQmlProxyMetaObject::ExtensionObjectId, &result); + if (id != QQmlProxyMetaObject::ExtensionObjectId) + return nullptr; + + return static_cast<QObject *>(result); +} + int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName, diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index b20b8dc5d3..752efd7268 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -615,6 +615,7 @@ Q_QML_EXPORT QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *, const QMetaObject *); Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc func, bool create = true); +Q_QML_EXPORT QObject *qmlExtendedObject(QObject *); //The C++ version of protected namespaces in qmldir Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion); diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index 33b216ee78..53db6e71af 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -104,39 +104,54 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void { Q_ASSERT(object == o); - if ((c == QMetaObject::ReadProperty || - c == QMetaObject::WriteProperty) && - id >= metaObjects->constLast().propertyOffset) { + switch (c) { + case QMetaObject::ReadProperty: + case QMetaObject::WriteProperty: { + if (id < metaObjects->constLast().propertyOffset) + break; for (int ii = 0; ii < metaObjects->count(); ++ii) { const int globalPropertyOffset = metaObjects->at(ii).propertyOffset; - if (id >= globalPropertyOffset) { - QObject *proxy = getProxy(ii); - const int localProxyOffset = proxy->metaObject()->propertyOffset(); - const int localProxyId = id - globalPropertyOffset + localProxyOffset; + if (id < globalPropertyOffset) + continue; - return proxy->qt_metacall(c, localProxyId, a); - } + QObject *proxy = getProxy(ii); + const int localProxyOffset = proxy->metaObject()->propertyOffset(); + const int localProxyId = id - globalPropertyOffset + localProxyOffset; + return proxy->qt_metacall(c, localProxyId, a); } - } else if (c == QMetaObject::InvokeMetaMethod && - id >= metaObjects->constLast().methodOffset) { + break; + } + case QMetaObject::InvokeMetaMethod: { + if (id < metaObjects->constLast().methodOffset) + break; + QMetaMethod m = object->metaObject()->method(id); if (m.methodType() == QMetaMethod::Signal) { QMetaObject::activate(object, id, a); return -1; - } else { - for (int ii = 0; ii < metaObjects->count(); ++ii) { - const int globalMethodOffset = metaObjects->at(ii).methodOffset; - if (id >= globalMethodOffset) { - QObject *proxy = getProxy(ii); - - const int localMethodOffset = proxy->metaObject()->methodOffset(); - const int localMethodId = id - globalMethodOffset + localMethodOffset; - - return proxy->qt_metacall(c, localMethodId, a); - } - } } + + for (int ii = 0; ii < metaObjects->count(); ++ii) { + const int globalMethodOffset = metaObjects->at(ii).methodOffset; + if (id < globalMethodOffset) + continue; + + QObject *proxy = getProxy(ii); + const int localMethodOffset = proxy->metaObject()->methodOffset(); + const int localMethodId = id - globalMethodOffset + localMethodOffset; + return proxy->qt_metacall(c, localMethodId, a); + } + + break; + } + case QMetaObject::CustomCall: + if (id != ExtensionObjectId) + break; + a[0] = getProxy(0); + return id; + default: + break; } if (parent) diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h index 3eb25caa7b..a58818f22a 100644 --- a/src/qml/qml/qqmlproxymetaobject_p.h +++ b/src/qml/qml/qqmlproxymetaobject_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE class QQmlProxyMetaObject : public QDynamicMetaObjectData { public: + enum { ExtensionObjectId = std::numeric_limits<int>::min() }; + struct ProxyData { typedef QObject *(*CreateFunc)(QObject *); QMetaObject *metaObject; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 16d569c9a1..8472462bb0 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -5657,6 +5657,10 @@ void tst_qqmllanguage::extendedForeignTypes() QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended")); QCOMPARE(o->property("extendedInvokable").toInt(), 123); QCOMPARE(o->property("extendedSlot").toInt(), 456); + + QObject *extension = qmlExtendedObject(extended); + QVERIFY(extension != nullptr); + QVERIFY(qobject_cast<Extension *>(extension) != nullptr); } void tst_qqmllanguage::foreignTypeSingletons() { |