diff options
| author | Soheil Armin <[email protected]> | 2024-04-20 16:16:01 +0300 |
|---|---|---|
| committer | Soheil Armin <[email protected]> | 2024-05-22 15:53:55 +0300 |
| commit | 1163e6a420968508b67e803c3e1f197d5b97cc52 (patch) | |
| tree | bddf3dd931d0d9dee97e3bcbed9354919c6071ef | |
| parent | 7d2e12243f7d418a9bf52673c393fc60ed1b4365 (diff) | |
Android: Rename and split SignalHelper into new header and source files
SignalHelper renamed to QAndroidViewSignalManger
SignalInfo nested struct renamed to ConnectionInfo
And QAndroidViewSignalManger split into new header and source
files.
Task-number: QTBUG-124488
Change-Id: I77ab8bf995043993224a6c5cafce5ac57dca59d9
Reviewed-by: Assam Boudjelthia <[email protected]>
| -rw-r--r-- | src/quick/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/quick/platform/android/qandroidquickviewembedding.cpp | 154 | ||||
| -rw-r--r-- | src/quick/platform/android/qandroidquickviewembedding_p.h | 34 | ||||
| -rw-r--r-- | src/quick/platform/android/qandroidviewsignalmanager.cpp | 100 | ||||
| -rw-r--r-- | src/quick/platform/android/qandroidviewsignalmanager_p.h | 64 |
5 files changed, 201 insertions, 152 deletions
diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt index ce0322f4ce..f83a400c59 100644 --- a/src/quick/CMakeLists.txt +++ b/src/quick/CMakeLists.txt @@ -562,6 +562,7 @@ qt_internal_extend_target(Quick CONDITION QT_FEATURE_metal qt_internal_extend_target(Quick CONDITION ANDROID SOURCES platform/android/qandroidquickviewembedding.cpp platform/android/qandroidquickviewembedding_p.h + platform/android/qandroidviewsignalmanager.cpp platform/android/qandroidviewsignalmanager_p.h ) if (ANDROID) add_subdirectory(jar) diff --git a/src/quick/platform/android/qandroidquickviewembedding.cpp b/src/quick/platform/android/qandroidquickviewembedding.cpp index dbe6c69767..f6d4f04b22 100644 --- a/src/quick/platform/android/qandroidquickviewembedding.cpp +++ b/src/quick/platform/android/qandroidquickviewembedding.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtQuick/private/qandroidquickviewembedding_p.h> +#include <QtQuick/private/qandroidviewsignalmanager_p.h> #include <QtCore/qcoreapplication.h> #include <QtCore/qjnienvironment.h> @@ -54,7 +55,7 @@ namespace QtAndroidQuickViewEmbedding QWindow *parentWindow = reinterpret_cast<QWindow *>(parentWindowReference); QQuickView *view = new QQuickView(parentWindow); QQmlEngine *engine = view->engine(); - new SignalHelper(view); + new QAndroidViewSignalManager(view); QObject::connect(view, &QQuickView::statusChanged, [qtViewObject](QQuickView::Status status) { qtViewObject.callMethod<void>("handleStatusChange", status); @@ -194,7 +195,7 @@ namespace QtAndroidQuickViewEmbedding return -1; } - SignalHelper *signalHelper = view->findChild<SignalHelper *>(); + QAndroidViewSignalManager *signalManager = view->findChild<QAndroidViewSignalManager *>(); const QByteArray javaArgClass = QJniObject(argType).className(); const char *qArgName = QMetaType(javaToQMetaType.value(javaArgClass, QMetaType::Type::UnknownType)).name(); @@ -233,7 +234,7 @@ namespace QtAndroidQuickViewEmbedding if (signalIndex == -1) return -1; - const QMetaObject *helperMetaObject = signalHelper->metaObject(); + const QMetaObject *helperMetaObject = signalManager->metaObject(); QByteArray helperSignalSignature = signalSignature; helperSignalSignature.replace(0, signalSignature.indexOf('('), "forwardSignal"); int helperSlotIndex = helperMetaObject->indexOfSlot(helperSignalSignature.constData()); @@ -242,15 +243,17 @@ namespace QtAndroidQuickViewEmbedding // Return the id if the signal is already connected to the same listener. QJniObject listenerJniObject(listener); - if (signalHelper->listenersMap.contains(signalSignature)) { - auto listenerInfos = signalHelper->listenersMap.values(signalSignature); - auto isSameListener = [listenerJniObject](const SignalHelper::ListenerInfo &listenerInfo) { - return listenerInfo.listener == listenerJniObject; - }; - auto iterator = std::find_if(listenerInfos.constBegin(), - listenerInfos.constEnd(), + 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 != listenerInfos.end()) { + if (iterator != connectionInfos.end()) { qWarning("Signal listener with the ID of %i is already connected to %s signal.", iterator->id, signalSignature.constData()); @@ -260,30 +263,30 @@ namespace QtAndroidQuickViewEmbedding QMetaMethod signalMethod = metaObject->method(signalIndex); QMetaMethod signalForwarderMethod = helperMetaObject->method(helperSlotIndex); - signalHelper->connectionHandleCounter++; + signalManager->connectionHandleCounter++; QMetaObject::Connection connection; - if (signalHelper->listenersMap.contains(signalSignature)) { - connection = signalHelper - ->connections[signalHelper->listenersMap.value(signalSignature).id]; + if (signalManager->connectionInfoMap.contains(signalSignature)) { + const int existingId = signalManager->connectionInfoMap.value(signalSignature).id; + connection = signalManager->connections[existingId]; } else { connection = QObject::connect(rootObject, signalMethod, - signalHelper, + signalManager, signalForwarderMethod); } - SignalHelper::ListenerInfo listenerInfo; - listenerInfo.listener = listenerJniObject; - listenerInfo.javaArgType = javaArgClass; - listenerInfo.propertyIndex = propertyIndex; - listenerInfo.signalSignature = signalSignature; - listenerInfo.id = signalHelper->connectionHandleCounter; + QAndroidViewSignalManager::ConnectionInfo connectionInfo; + connectionInfo.listener = listenerJniObject; + connectionInfo.javaArgType = javaArgClass; + connectionInfo.propertyIndex = propertyIndex; + connectionInfo.signalSignature = signalSignature; + connectionInfo.id = signalManager->connectionHandleCounter; - signalHelper->listenersMap.insert(signalSignature, listenerInfo); - signalHelper->connections.insert(listenerInfo.id, connection); + signalManager->connectionInfoMap.insert(signalSignature, connectionInfo); + signalManager->connections.insert(connectionInfo.id, connection); - return listenerInfo.id; + return connectionInfo.id; } bool removeRootObjectSignalListener(JNIEnv *, jobject, jlong windowReference, @@ -296,16 +299,16 @@ namespace QtAndroidQuickViewEmbedding return false; } - SignalHelper *signalHelper = view->findChild<SignalHelper *>(); - if (!signalHelper->connections.contains(signalListenerId)) + QAndroidViewSignalManager *signalManager = view->findChild<QAndroidViewSignalManager *>(); + if (!signalManager->connections.contains(signalListenerId)) return false; QByteArray signalSignature; - for (auto listenerInfoIter = signalHelper->listenersMap.begin(); - listenerInfoIter != signalHelper->listenersMap.end();) { + for (auto listenerInfoIter = signalManager->connectionInfoMap.begin(); + listenerInfoIter != signalManager->connectionInfoMap.end();) { if (listenerInfoIter->id == signalListenerId) { signalSignature = listenerInfoIter->signalSignature; - signalHelper->listenersMap.erase(listenerInfoIter); + signalManager->connectionInfoMap.erase(listenerInfoIter); break; } else { ++listenerInfoIter; @@ -313,98 +316,13 @@ namespace QtAndroidQuickViewEmbedding } // disconnect if its the last listener associated with the signal signatures - if (!signalHelper->listenersMap.contains(signalSignature)) - rootObject->disconnect(signalHelper->connections.value(signalListenerId)); + if (!signalManager->connectionInfoMap.contains(signalSignature)) + rootObject->disconnect(signalManager->connections.value(signalListenerId)); - signalHelper->connections.remove(signalListenerId); + signalManager->connections.remove(signalListenerId); return true; } - void SignalHelper::forwardSignal() - { - invokeListener(sender(), senderSignalIndex(), QVariant()); - } - - void SignalHelper::forwardSignal(int signalValue) - { - invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); - } - - void SignalHelper::forwardSignal(bool signalValue) - { - invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); - } - - void SignalHelper::forwardSignal(double signalValue) - { - invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); - } - - void SignalHelper::forwardSignal(float signalValue) - { - invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); - } - - void SignalHelper::forwardSignal(QString signalValue) - { - invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); - } - - void SignalHelper::invokeListener(QObject *sender, int senderSignalIndex, QVariant signalValue) - { - using namespace QtJniTypes; - - const QMetaObject *metaObject = sender->metaObject(); - const QMetaMethod signalMethod = metaObject->method(senderSignalIndex); - - for (auto listenerInfoIter = listenersMap.constFind(signalMethod.methodSignature()); - listenerInfoIter != listenersMap.constEnd() && - listenerInfoIter.key() == signalMethod.methodSignature(); - ++listenerInfoIter) { - const ListenerInfo listenerInfo = *listenerInfoIter; - const QByteArray javaArgType = listenerInfo.javaArgType; - QJniObject jSignalMethodName = - QJniObject::fromString(QLatin1StringView(signalMethod.name())); - - if (listenerInfo.propertyIndex != -1 && javaArgType != Traits<Void>::className()) - signalValue = metaObject->property(listenerInfo.propertyIndex).read(sender); - - int valueTypeId = signalValue.typeId(); - QJniObject jValue; - - switch (valueTypeId) { - case QMetaType::Type::UnknownType: - break; - case QMetaType::Type::Int: - jValue = qVariantToJniObject<Integer,jint>(signalValue); - break; - case QMetaType::Type::Double: - jValue = qVariantToJniObject<Double,jdouble>(signalValue); - break; - case QMetaType::Type::Float: - jValue = qVariantToJniObject<Float,jfloat>(signalValue); - break; - case QMetaType::Type::Bool: - jValue = qVariantToJniObject<Boolean,jboolean>(signalValue); - break; - case QMetaType::Type::QString: - jValue = QJniObject::fromString(get<QString>(std::move(signalValue))); - break; - default: - qWarning("Mismatching argument types between QML signal (%s) and the Java function " - "(%s). Sending null as argument.", - signalMethod.methodSignature().constData(), javaArgType.constData()); - } - - QNativeInterface::QAndroidApplication::runOnAndroidMainThread( - [listenerInfo, jSignalMethodName, jValue]() { - listenerInfo.listener.callMethod<void, jstring, jobject>("onSignalEmitted", - jSignalMethodName.object<jstring>(), - jValue.object()); - }); - } - } - bool registerNatives(QJniEnvironment& env) { return env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtQuickView>::className(), {Q_JNI_NATIVE_SCOPED_METHOD(createQuickView, diff --git a/src/quick/platform/android/qandroidquickviewembedding_p.h b/src/quick/platform/android/qandroidquickviewembedding_p.h index ace387a7f1..c20585c5d0 100644 --- a/src/quick/platform/android/qandroidquickviewembedding_p.h +++ b/src/quick/platform/android/qandroidquickviewembedding_p.h @@ -41,40 +41,6 @@ namespace QtAndroidQuickViewEmbedding bool removeRootObjectSignalListener(JNIEnv *env, jobject, jlong parentWindowReference, jint signalListenerId); Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(removeRootObjectSignalListener) - - class SignalHelper : public QObject - { - Q_OBJECT - public: - struct ListenerInfo - { - ListenerInfo() : propertyIndex(-1) { } - int id; - QJniObject listener; - QByteArray javaArgType; - QByteArray signalSignature; - int propertyIndex; - }; - - int connectionHandleCounter; - explicit SignalHelper(QQuickView *parent) : QObject(parent), connectionHandleCounter(0) { } - QMultiMap<QByteArray, ListenerInfo> listenersMap; - QHash<int, QMetaObject::Connection> connections; - void invokeListener(QObject *sender, int senderSignalIndex, QVariant signalValue); - - template<typename JT, typename T> - inline QJniObject qVariantToJniObject(const QVariant& v) { - return QJniObject(QtJniTypes::Traits<JT>::className(), get<T>(std::move(v))); - }; - - public slots: - void forwardSignal(); - void forwardSignal(int); - void forwardSignal(double); - void forwardSignal(float); - void forwardSignal(bool); - void forwardSignal(QString); - }; }; QT_END_NAMESPACE diff --git a/src/quick/platform/android/qandroidviewsignalmanager.cpp b/src/quick/platform/android/qandroidviewsignalmanager.cpp new file mode 100644 index 0000000000..60599aae3d --- /dev/null +++ b/src/quick/platform/android/qandroidviewsignalmanager.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include <QtQuick/private/qandroidviewsignalmanager_p.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_JNI_CLASS(Void, "java/lang/Void"); +Q_DECLARE_JNI_CLASS(Integer, "java/lang/Integer"); +Q_DECLARE_JNI_CLASS(Double, "java/lang/Double"); +Q_DECLARE_JNI_CLASS(Float, "java/lang/Float"); +Q_DECLARE_JNI_CLASS(Boolean, "java/lang/Boolean"); + +void QAndroidViewSignalManager::forwardSignal() +{ + invokeListener(sender(), senderSignalIndex(), QVariant()); +} + +void QAndroidViewSignalManager::forwardSignal(int signalValue) +{ + invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); +} + +void QAndroidViewSignalManager::forwardSignal(bool signalValue) +{ + invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); +} + +void QAndroidViewSignalManager::forwardSignal(double signalValue) +{ + invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); +} + +void QAndroidViewSignalManager::forwardSignal(float signalValue) +{ + invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); +} + +void QAndroidViewSignalManager::forwardSignal(QString signalValue) +{ + invokeListener(sender(), senderSignalIndex(), QVariant(signalValue)); +} + +void QAndroidViewSignalManager::invokeListener(QObject *sender, int senderSignalIndex, + QVariant signalValue) +{ + using namespace QtJniTypes; + + const QMetaObject *metaObject = sender->metaObject(); + const QMetaMethod signalMethod = metaObject->method(senderSignalIndex); + + for (auto connectionInfoIter = connectionInfoMap.constFind(signalMethod.methodSignature()); + connectionInfoIter != connectionInfoMap.constEnd() + && connectionInfoIter.key() == signalMethod.methodSignature(); + ++connectionInfoIter) { + const ConnectionInfo connectionInfo = *connectionInfoIter; + const QByteArray javaArgType = connectionInfo.javaArgType; + QJniObject jSignalMethodName = + QJniObject::fromString(QLatin1StringView(signalMethod.name())); + + if (connectionInfo.propertyIndex != -1 && javaArgType != Traits<Void>::className()) + signalValue = metaObject->property(connectionInfo.propertyIndex).read(sender); + + int valueTypeId = signalValue.typeId(); + QJniObject jValue; + + switch (valueTypeId) { + case QMetaType::Type::UnknownType: + break; + case QMetaType::Type::Int: + jValue = qVariantToJniObject<Integer, jint>(signalValue); + break; + case QMetaType::Type::Double: + jValue = qVariantToJniObject<Double, jdouble>(signalValue); + break; + case QMetaType::Type::Float: + jValue = qVariantToJniObject<Float, jfloat>(signalValue); + break; + case QMetaType::Type::Bool: + jValue = qVariantToJniObject<Boolean, jboolean>(signalValue); + break; + case QMetaType::Type::QString: + jValue = QJniObject::fromString(get<QString>(std::move(signalValue))); + break; + default: + qWarning("Mismatching argument types between QML signal (%s) and the Java function " + "(%s). Sending null as argument.", + signalMethod.methodSignature().constData(), javaArgType.constData()); + } + + QNativeInterface::QAndroidApplication::runOnAndroidMainThread( + [connectionInfo, jSignalMethodName, jValue]() { + connectionInfo.listener.callMethod<void, jstring, jobject>( + "onSignalEmitted", jSignalMethodName.object<jstring>(), + jValue.object()); + }); + } +} + +QT_END_NAMESPACE diff --git a/src/quick/platform/android/qandroidviewsignalmanager_p.h b/src/quick/platform/android/qandroidviewsignalmanager_p.h new file mode 100644 index 0000000000..80dfc823fb --- /dev/null +++ b/src/quick/platform/android/qandroidviewsignalmanager_p.h @@ -0,0 +1,64 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QANDROIDVIEWSIGNALMANAGER_P_H +#define QANDROIDVIEWSIGNALMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtCore/qjnitypes.h> +#include <QtQuick/qquickview.h> + +QT_BEGIN_NAMESPACE + +class QAndroidViewSignalManager : public QObject +{ + Q_OBJECT +public: + struct ConnectionInfo + { + int id; + QJniObject listener; + QByteArray javaArgType; + QByteArray signalSignature; + int propertyIndex{ -1 }; + }; + + explicit QAndroidViewSignalManager(QQuickView *parent) + : QObject(parent), connectionHandleCounter(0) + { + } + void invokeListener(QObject *sender, int senderSignalIndex, QVariant signalValue); + + int connectionHandleCounter; + QMultiMap<QByteArray, ConnectionInfo> connectionInfoMap; + QHash<int, QMetaObject::Connection> connections; + + template <typename JT, typename T> + inline QJniObject qVariantToJniObject(const QVariant &v) + { + return QJniObject(QtJniTypes::Traits<JT>::className(), get<T>(std::move(v))); + }; + +public slots: + void forwardSignal(); + void forwardSignal(int); + void forwardSignal(double); + void forwardSignal(float); + void forwardSignal(bool); + void forwardSignal(QString); +}; + +QT_END_NAMESPACE + +#endif // QANDROIDVIEWSIGNALMANAGER_P_H |
