aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-03-14 15:56:28 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-03-23 23:21:56 +0100
commitcc6bd22b61cff5b992b594b69552c8f41f65f13b (patch)
tree13aad8f781c767d793d29a1499f94383052d5578
parent00b59c391e88d37dd09f187000416a3501a1e009 (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.qdoc10
-rw-r--r--src/qml/qml/qqml.cpp19
-rw-r--r--src/qml/qml/qqml.h1
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp61
-rw-r--r--src/qml/qml/qqmlproxymetaobject_p.h2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp4
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() {