diff options
| author | Petri Virkkunen <petri.virkkunen@qt.io> | 2025-05-08 12:26:28 +0300 |
|---|---|---|
| committer | Petri Virkkunen <petri.virkkunen@qt.io> | 2025-06-30 12:42:57 +0300 |
| commit | 62cf01a1071eb2f545c841c90e38cc62ad603a93 (patch) | |
| tree | bcd158c4623a1e567be7c6e5a9b3cba277d7a847 /src/quick/platform/android/qandroidquickviewembedding.cpp | |
| parent | 2b0eaf5c2128a7b1443d153fdacdcebb77aac3c2 (diff) | |
Android: QQ4A: Add support for multiple signal arguments in QML
This commit adds support for QML signals with multiple arguments to be
used in the QQ4A context.
In the QtQuickView[Content] layer, this commit adds a new overload for
the connectSignalListener API. This new overload takes a Class<?>[]
parameter instead of the Class<T> parameter of the old API. To support
this, the corresponding QtAndroidQuickViewEmbedding native function has
been replaced with one that takes a jclass array as well. There is a
new implementation for the old single-class-argument API that calls the
new API, instead of reimplementing the logic in two places.
Signal connection and disconnection logic has been moved to
QAndroidViewSignalManager, which is called from the
QtAndroidQuickViewEmbedding namespace native functions.
In QAndroidViewSignalManager, the signal connection now happens by
connecting to the qt_metacall QMetaObject function, which the class has
overridden.
In QAndroidViewSignalManager::qt_metacall, the signal is handled by
detecting the type of signal and parsing the data sent by the signal,
either by reading the property of the sender of the signal that the
signal is linked to, or parsing the void* arguments passed into
qt_metacall.
Task-number: QTBUG-124489
Change-Id: I416bb266b3ffe5c947264d942b1afe3349bca2d7
Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/quick/platform/android/qandroidquickviewembedding.cpp')
| -rw-r--r-- | src/quick/platform/android/qandroidquickviewembedding.cpp | 126 |
1 files changed, 4 insertions, 122 deletions
diff --git a/src/quick/platform/android/qandroidquickviewembedding.cpp b/src/quick/platform/android/qandroidquickviewembedding.cpp index 293667f23b..24aabbcb87 100644 --- a/src/quick/platform/android/qandroidquickviewembedding.cpp +++ b/src/quick/platform/android/qandroidquickviewembedding.cpp @@ -156,17 +156,9 @@ namespace QtAndroidQuickViewEmbedding } int addRootObjectSignalListener(JNIEnv *env, jobject, jlong windowReference, jstring signalName, - jclass argType, jobject listener) + QJniArray<jclass> argTypes, jobject listener) { Q_ASSERT(env); - static QHash<QByteArray, int> javaToQMetaType = { - { "java/lang/Void", QMetaType::Type::Void }, - { "java/lang/String", QMetaType::Type::QString }, - { "java/lang/Integer", QMetaType::Type::Int }, - { "java/lang/Double", QMetaType::Type::Double }, - { "java/lang/Float", QMetaType::Type::Float }, - { "java/lang/Boolean", QMetaType::Type::Bool } - }; auto [view, rootObject] = getViewAndRootObject(windowReference); if (!rootObject) { @@ -176,97 +168,8 @@ namespace QtAndroidQuickViewEmbedding } QAndroidViewSignalManager *signalManager = view->signalManager(); - const QByteArray javaArgClass = QJniObject(argType).className(); - const char *qArgName = - QMetaType(javaToQMetaType.value(javaArgClass, QMetaType::Type::UnknownType)).name(); - const QString signalMethodName = QJniObject(signalName).toString(); - - const QMetaObject *metaObject = rootObject->metaObject(); - int signalIndex = -1; - int propertyIndex = -1; - - QByteArray signalSignature = QMetaObject::normalizedSignature(qPrintable( - QStringLiteral("%1(%2)").arg(signalMethodName).arg(QLatin1StringView(qArgName)))); - signalIndex = metaObject->indexOfSignal(signalSignature.constData()); - - // Try to check if the signal is a parameterless notifier of a property - // or a property name itself. - if (signalIndex == -1) { - signalSignature = QMetaObject::normalizedSignature( - qPrintable(QStringLiteral("%1()").arg(signalMethodName))); - for (int i = 0; i < metaObject->propertyCount(); ++i) { - QMetaProperty metaProperty = metaObject->property(i); - QMetaMethod notifyMethod = metaProperty.notifySignal(); - - if (signalSignature == notifyMethod.methodSignature()) { - signalIndex = metaObject->property(i).notifySignalIndex(); - propertyIndex = i; - break; - } else if (signalMethodName == QLatin1StringView(metaProperty.name())) { - signalIndex = metaObject->property(i).notifySignalIndex(); - signalSignature = notifyMethod.methodSignature(); - propertyIndex = i; - break; - } - } - } - - if (signalIndex == -1) - return -1; - - const QMetaObject *helperMetaObject = signalManager->metaObject(); - QByteArray helperSignalSignature = signalSignature; - helperSignalSignature.replace(0, signalSignature.indexOf('('), "forwardSignal"); - int helperSlotIndex = helperMetaObject->indexOfSlot(helperSignalSignature.constData()); - if (helperSlotIndex == -1) - return -1; - - // Return the id if the signal is already connected to the same listener. - QJniObject listenerJniObject(listener); - if (signalManager->connectionInfoMap.contains(signalSignature)) { - auto connectionInfos = signalManager->connectionInfoMap.values(signalSignature); - auto isSameListener = - [listenerJniObject]( - const QAndroidViewSignalManager::ConnectionInfo &connectionInfo) { - return connectionInfo.listener == listenerJniObject; - }; - auto iterator = std::find_if(connectionInfos.constBegin(), - connectionInfos.constEnd(), - isSameListener); - if (iterator != connectionInfos.end()) { - qWarning("Signal listener with the ID of %i is already connected to %s signal.", - iterator->id, - signalSignature.constData()); - return iterator->id; - } - } - - QMetaMethod signalMethod = metaObject->method(signalIndex); - QMetaMethod signalForwarderMethod = helperMetaObject->method(helperSlotIndex); - signalManager->connectionHandleCounter++; - - QMetaObject::Connection connection; - if (signalManager->connectionInfoMap.contains(signalSignature)) { - const int existingId = signalManager->connectionInfoMap.value(signalSignature).id; - connection = signalManager->connections[existingId]; - } else { - connection = QObject::connect(rootObject, - signalMethod, - signalManager, - signalForwarderMethod); - } - - QAndroidViewSignalManager::ConnectionInfo connectionInfo; - connectionInfo.listener = listenerJniObject; - connectionInfo.javaArgType = javaArgClass; - connectionInfo.propertyIndex = propertyIndex; - connectionInfo.signalSignature = signalSignature; - connectionInfo.id = signalManager->connectionHandleCounter; - - signalManager->connectionInfoMap.insert(signalSignature, connectionInfo); - signalManager->connections.insert(connectionInfo.id, connection); - - return connectionInfo.id; + return signalManager->addConnection(QJniObject(signalName).toString(), argTypes, + QJniObject(listener), *rootObject); } bool removeRootObjectSignalListener(JNIEnv *, jobject, jlong windowReference, @@ -278,28 +181,7 @@ namespace QtAndroidQuickViewEmbedding uninitializedViewMessage); return false; } - - QAndroidViewSignalManager *signalManager = view->signalManager(); - if (!signalManager->connections.contains(signalListenerId)) - return false; - - QByteArray signalSignature; - for (auto listenerInfoIter = signalManager->connectionInfoMap.begin(); - listenerInfoIter != signalManager->connectionInfoMap.end();) { - if (listenerInfoIter->id == signalListenerId) { - signalSignature = listenerInfoIter->signalSignature; - signalManager->connectionInfoMap.erase(listenerInfoIter); - break; - } else { - ++listenerInfoIter; - } - } - - // disconnect if its the last listener associated with the signal signatures - if (!signalManager->connectionInfoMap.contains(signalSignature)) - rootObject->disconnect(signalManager->connections.value(signalListenerId)); - - signalManager->connections.remove(signalListenerId); + view->signalManager()->removeConnection(signalListenerId); return true; } |
