From 33f3d70c74564fb1e296537e14d1e0bddb4bb944 Mon Sep 17 00:00:00 2001 From: Maximilian Goldstein Date: Fri, 5 Feb 2021 15:14:42 +0100 Subject: qqmlproxymetaobject: Support invoking methods and slots Previously this just failed silently and returned garbage data. Change-Id: Ia8b72836aa0ccfd50fd18b0f813c2bf3a00801c5 Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlproxymetaobject.cpp | 84 +++++++++++++++++++++++-------------- src/qml/qml/qqmlproxymetaobject_p.h | 2 + 2 files changed, 55 insertions(+), 31 deletions(-) (limited to 'src/qml') diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp index c5cb2ec059..21d3c7ed05 100644 --- a/src/qml/qml/qqmlproxymetaobject.cpp +++ b/src/qml/qml/qqmlproxymetaobject.cpp @@ -65,6 +65,41 @@ QQmlProxyMetaObject::~QQmlProxyMetaObject() proxies = nullptr; } +QObject *QQmlProxyMetaObject::getProxy(int index) +{ + if (!proxies) { + if (!proxies) { + proxies = new QObject*[metaObjects->count()]; + ::memset(proxies, 0, + sizeof(QObject *) * metaObjects->count()); + } + } + + if (!proxies[index]) { + const ProxyData &data = metaObjects->at(index); + if (!data.createFunc) + return nullptr; + + QObject *proxy = data.createFunc(object); + const QMetaObject *metaObject = proxy->metaObject(); + proxies[index] = proxy; + + int localOffset = data.metaObject->methodOffset(); + int methodOffset = metaObject->methodOffset(); + int methods = metaObject->methodCount() - methodOffset; + + // ### - Can this be done more optimally? + for (int jj = 0; jj < methods; ++jj) { + QMetaMethod method = + metaObject->method(jj + methodOffset); + if (method.methodType() == QMetaMethod::Signal) + QQmlPropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj); + } + } + + return proxies[index]; +} + int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a) { Q_ASSERT(object == o); @@ -74,38 +109,13 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void id >= metaObjects->constLast().propertyOffset) { for (int ii = 0; ii < metaObjects->count(); ++ii) { - const ProxyData &data = metaObjects->at(ii); - if (id >= data.propertyOffset) { - if (!proxies) { - proxies = new QObject*[metaObjects->count()]; - ::memset(proxies, 0, - sizeof(QObject *) * metaObjects->count()); - } - - if (!proxies[ii]) { - if (!data.createFunc) - continue; - QObject *proxy = data.createFunc(object); - const QMetaObject *metaObject = proxy->metaObject(); - proxies[ii] = proxy; - - int localOffset = data.metaObject->methodOffset(); - int methodOffset = metaObject->methodOffset(); - int methods = metaObject->methodCount() - methodOffset; - - // ### - Can this be done more optimally? - for (int jj = 0; jj < methods; ++jj) { - QMetaMethod method = - metaObject->method(jj + methodOffset); - if (method.methodType() == QMetaMethod::Signal) - QQmlPropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj); - } - } - - int proxyOffset = proxies[ii]->metaObject()->propertyOffset(); - int proxyId = id - data.propertyOffset + proxyOffset; + 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; - return proxies[ii]->qt_metacall(c, proxyId, a); + return proxy->qt_metacall(c, localProxyId, a); } } } else if (c == QMetaObject::InvokeMetaMethod && @@ -114,6 +124,18 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void 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); + } + } } } diff --git a/src/qml/qml/qqmlproxymetaobject_p.h b/src/qml/qml/qqmlproxymetaobject_p.h index 2b7a980361..dfa5d44059 100644 --- a/src/qml/qml/qqmlproxymetaobject_p.h +++ b/src/qml/qml/qqmlproxymetaobject_p.h @@ -80,6 +80,8 @@ protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; private: + QObject *getProxy(int index); + QList *metaObjects; QObject **proxies; -- cgit v1.2.3