diff --git a/cpp-generator/main.cpp b/cpp-generator/main.cpp index 3e3b105..4f7ac8f 100644 --- a/cpp-generator/main.cpp +++ b/cpp-generator/main.cpp @@ -115,13 +115,12 @@ static QString makeHeader(const QString& moduleName, const QString& className, c s << "#include \n"; s << "#include \n"; s << "#include \n"; - s << "#include \n"; - s << "#include \n"; s << "#include \n"; s << "#include \n"; s << "#include \"logos_types.h\"\n"; s << "#include \"logos_api.h\"\n"; - s << "#include \"logos_api_client.h\"\n\n"; + s << "#include \"logos_api_client.h\"\n"; + s << "#include \"logos_object.h\"\n\n"; s << "class " << className << " {\n"; s << "public:\n"; s << " explicit " << className << "(LogosAPI* api);\n\n"; @@ -129,17 +128,17 @@ static QString makeHeader(const QString& moduleName, const QString& className, c s << " using EventCallback = std::function;\n\n"; s << " bool on(const QString& eventName, RawEventCallback callback);\n"; s << " bool on(const QString& eventName, EventCallback callback);\n"; - s << " void setEventSource(QObject* source);\n"; - s << " QObject* eventSource() const;\n"; + s << " void setEventSource(LogosObject* source);\n"; + s << " LogosObject* eventSource() const;\n"; s << " void trigger(const QString& eventName);\n"; s << " void trigger(const QString& eventName, const QVariantList& data);\n"; s << " template\n"; s << " void trigger(const QString& eventName, Args&&... args) {\n"; s << " trigger(eventName, packVariantList(std::forward(args)...));\n"; s << " }\n"; - s << " void trigger(const QString& eventName, QObject* source, const QVariantList& data);\n"; + s << " void trigger(const QString& eventName, LogosObject* source, const QVariantList& data);\n"; s << " template\n"; - s << " void trigger(const QString& eventName, QObject* source, Args&&... args) {\n"; + s << " void trigger(const QString& eventName, LogosObject* source, Args&&... args) {\n"; s << " trigger(eventName, source, packVariantList(std::forward(args)...));\n"; s << " }\n\n"; // Methods @@ -181,7 +180,7 @@ static QString makeHeader(const QString& moduleName, const QString& className, c s << asyncCallbackType << " callback, Timeout timeout = Timeout());\n"; } s << "\nprivate:\n"; - s << " QObject* ensureReplica();\n"; + s << " LogosObject* ensureReplica();\n"; s << " template\n"; s << " static QVariantList packVariantList(Args&&... args) {\n"; s << " QVariantList list;\n"; @@ -193,8 +192,8 @@ static QString makeHeader(const QString& moduleName, const QString& className, c s << " LogosAPI* m_api;\n"; s << " LogosAPIClient* m_client;\n"; s << " QString m_moduleName;\n"; - s << " QPointer m_eventReplica;\n"; - s << " QPointer m_eventSource;\n"; + s << " LogosObject* m_eventReplica = nullptr;\n"; + s << " LogosObject* m_eventSource = nullptr;\n"; s << "};\n"; return h; } @@ -206,27 +205,27 @@ static QString makeSource(const QString& moduleName, const QString& className, c s << "#include \"" << headerBaseName << "\"\n\n"; s << "#include \n\n"; s << className << "::" << className << "(LogosAPI* api) : m_api(api), m_client(api->getClient(\"" << moduleName << "\")), m_moduleName(QStringLiteral(\"" << moduleName << "\")) {}\n\n"; - s << "QObject* " << className << "::ensureReplica() {\n"; + s << "LogosObject* " << className << "::ensureReplica() {\n"; s << " if (!m_eventReplica) {\n"; - s << " QObject* replica = m_client->requestObject(m_moduleName);\n"; + s << " LogosObject* replica = m_client->requestObject(m_moduleName);\n"; s << " if (!replica) {\n"; s << " qWarning() << \"" << className << ": failed to acquire remote object for events on\" << m_moduleName;\n"; s << " return nullptr;\n"; s << " }\n"; s << " m_eventReplica = replica;\n"; s << " }\n"; - s << " return m_eventReplica.data();\n"; + s << " return m_eventReplica;\n"; s << "}\n\n"; s << "bool " << className << "::on(const QString& eventName, RawEventCallback callback) {\n"; s << " if (!callback) {\n"; s << " qWarning() << \"" << className << ": ignoring empty event callback for\" << eventName;\n"; s << " return false;\n"; s << " }\n"; - s << " QObject* origin = ensureReplica();\n"; + s << " LogosObject* origin = ensureReplica();\n"; s << " if (!origin) {\n"; s << " return false;\n"; s << " }\n"; - s << " m_client->onEvent(origin, nullptr, eventName, callback);\n"; + s << " m_client->onEvent(origin, eventName, callback);\n"; s << " return true;\n"; s << "}\n\n"; s << "bool " << className << "::on(const QString& eventName, EventCallback callback) {\n"; @@ -238,11 +237,11 @@ static QString makeSource(const QString& moduleName, const QString& className, c s << " callback(data);\n"; s << " });\n"; s << "}\n\n"; - s << "void " << className << "::setEventSource(QObject* source) {\n"; + s << "void " << className << "::setEventSource(LogosObject* source) {\n"; s << " m_eventSource = source;\n"; s << "}\n\n"; - s << "QObject* " << className << "::eventSource() const {\n"; - s << " return m_eventSource.data();\n"; + s << "LogosObject* " << className << "::eventSource() const {\n"; + s << " return m_eventSource;\n"; s << "}\n\n"; s << "void " << className << "::trigger(const QString& eventName) {\n"; s << " trigger(eventName, QVariantList{});\n"; @@ -252,9 +251,9 @@ static QString makeSource(const QString& moduleName, const QString& className, c s << " qWarning() << \"" << className << ": no event source set for trigger\" << eventName;\n"; s << " return;\n"; s << " }\n"; - s << " m_client->onEventResponse(m_eventSource.data(), eventName, data);\n"; + s << " m_client->onEventResponse(m_eventSource, eventName, data);\n"; s << "}\n\n"; - s << "void " << className << "::trigger(const QString& eventName, QObject* source, const QVariantList& data) {\n"; + s << "void " << className << "::trigger(const QString& eventName, LogosObject* source, const QVariantList& data) {\n"; s << " if (!source) {\n"; s << " qWarning() << \"" << className << ": cannot trigger\" << eventName << \"with null source\";\n"; s << " return;\n"; @@ -409,12 +408,11 @@ static QString makeCoreManagerHeader() s << "#include \n"; s << "#include \n"; s << "#include \n"; - s << "#include \n"; - s << "#include \n"; s << "#include \n"; s << "#include \n"; s << "#include \"logos_api.h\"\n"; - s << "#include \"logos_api_client.h\"\n\n"; + s << "#include \"logos_api_client.h\"\n"; + s << "#include \"logos_object.h\"\n\n"; s << "class CoreManager {\n"; s << "public:\n"; s << " explicit CoreManager(LogosAPI* api);\n\n"; @@ -422,17 +420,17 @@ static QString makeCoreManagerHeader() s << " using EventCallback = std::function;\n\n"; s << " bool on(const QString& eventName, RawEventCallback callback);\n"; s << " bool on(const QString& eventName, EventCallback callback);\n"; - s << " void setEventSource(QObject* source);\n"; - s << " QObject* eventSource() const;\n"; + s << " void setEventSource(LogosObject* source);\n"; + s << " LogosObject* eventSource() const;\n"; s << " void trigger(const QString& eventName);\n"; s << " void trigger(const QString& eventName, const QVariantList& data);\n"; s << " template\n"; s << " void trigger(const QString& eventName, Args&&... args) {\n"; s << " trigger(eventName, packVariantList(std::forward(args)...));\n"; s << " }\n"; - s << " void trigger(const QString& eventName, QObject* source, const QVariantList& data);\n"; + s << " void trigger(const QString& eventName, LogosObject* source, const QVariantList& data);\n"; s << " template\n"; - s << " void trigger(const QString& eventName, QObject* source, Args&&... args) {\n"; + s << " void trigger(const QString& eventName, LogosObject* source, Args&&... args) {\n"; s << " trigger(eventName, source, packVariantList(std::forward(args)...));\n"; s << " }\n\n"; s << " void initialize(int argc, char* argv[]);\n"; @@ -447,7 +445,7 @@ static QString makeCoreManagerHeader() s << " bool unloadPlugin(const QString& pluginName);\n"; s << " QString processPlugin(const QString& filePath);\n\n"; s << "private:\n"; - s << " QObject* ensureReplica();\n"; + s << " LogosObject* ensureReplica();\n"; s << " template\n"; s << " static QVariantList packVariantList(Args&&... args) {\n"; s << " QVariantList list;\n"; @@ -459,8 +457,8 @@ static QString makeCoreManagerHeader() s << " LogosAPI* m_api;\n"; s << " LogosAPIClient* m_client;\n"; s << " QString m_moduleName;\n"; - s << " QPointer m_eventReplica;\n"; - s << " QPointer m_eventSource;\n"; + s << " LogosObject* m_eventReplica = nullptr;\n"; + s << " LogosObject* m_eventSource = nullptr;\n"; s << "};\n"; return h; } @@ -473,27 +471,27 @@ static QString makeCoreManagerSource(const QString& headerBaseName) s << "#include \n"; s << "#include \n\n"; s << "CoreManager::CoreManager(LogosAPI* api) : m_api(api), m_client(api->getClient(\"core_manager\")), m_moduleName(QStringLiteral(\"core_manager\")) {}\n\n"; - s << "QObject* CoreManager::ensureReplica() {\n"; + s << "LogosObject* CoreManager::ensureReplica() {\n"; s << " if (!m_eventReplica) {\n"; - s << " QObject* replica = m_client->requestObject(m_moduleName);\n"; + s << " LogosObject* replica = m_client->requestObject(m_moduleName);\n"; s << " if (!replica) {\n"; s << " qWarning() << \"CoreManager: failed to acquire remote object for events on\" << m_moduleName;\n"; s << " return nullptr;\n"; s << " }\n"; s << " m_eventReplica = replica;\n"; s << " }\n"; - s << " return m_eventReplica.data();\n"; + s << " return m_eventReplica;\n"; s << "}\n\n"; s << "bool CoreManager::on(const QString& eventName, RawEventCallback callback) {\n"; s << " if (!callback) {\n"; s << " qWarning() << \"CoreManager: ignoring empty event callback for\" << eventName;\n"; s << " return false;\n"; s << " }\n"; - s << " QObject* origin = ensureReplica();\n"; + s << " LogosObject* origin = ensureReplica();\n"; s << " if (!origin) {\n"; s << " return false;\n"; s << " }\n"; - s << " m_client->onEvent(origin, nullptr, eventName, callback);\n"; + s << " m_client->onEvent(origin, eventName, callback);\n"; s << " return true;\n"; s << "}\n\n"; s << "bool CoreManager::on(const QString& eventName, EventCallback callback) {\n"; @@ -505,11 +503,11 @@ static QString makeCoreManagerSource(const QString& headerBaseName) s << " callback(data);\n"; s << " });\n"; s << "}\n\n"; - s << "void CoreManager::setEventSource(QObject* source) {\n"; + s << "void CoreManager::setEventSource(LogosObject* source) {\n"; s << " m_eventSource = source;\n"; s << "}\n\n"; - s << "QObject* CoreManager::eventSource() const {\n"; - s << " return m_eventSource.data();\n"; + s << "LogosObject* CoreManager::eventSource() const {\n"; + s << " return m_eventSource;\n"; s << "}\n\n"; s << "void CoreManager::trigger(const QString& eventName) {\n"; s << " trigger(eventName, QVariantList{});\n"; @@ -519,9 +517,9 @@ static QString makeCoreManagerSource(const QString& headerBaseName) s << " qWarning() << \"CoreManager: no event source set for trigger\" << eventName;\n"; s << " return;\n"; s << " }\n"; - s << " m_client->onEventResponse(m_eventSource.data(), eventName, data);\n"; + s << " m_client->onEventResponse(m_eventSource, eventName, data);\n"; s << "}\n\n"; - s << "void CoreManager::trigger(const QString& eventName, QObject* source, const QVariantList& data) {\n"; + s << "void CoreManager::trigger(const QString& eventName, LogosObject* source, const QVariantList& data) {\n"; s << " if (!source) {\n"; s << " qWarning() << \"CoreManager: cannot trigger\" << eventName << \"with null source\";\n"; s << " return;\n"; diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 1bc57ed..3f4bbe2 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -28,6 +28,7 @@ set(SDK_SOURCES logos_mode.h logos_instance.h plugin_registry.h + logos_object.h logos_transport.h logos_transport_factory.cpp logos_transport_factory.h @@ -86,6 +87,7 @@ install(FILES logos_mode.h logos_instance.h plugin_registry.h + logos_object.h logos_transport.h logos_transport_factory.h logos_registry.h diff --git a/cpp/implementations/mock/mock_transport.cpp b/cpp/implementations/mock/mock_transport.cpp index 8f14255..1379d2c 100644 --- a/cpp/implementations/mock/mock_transport.cpp +++ b/cpp/implementations/mock/mock_transport.cpp @@ -1,5 +1,4 @@ #include "mock_transport.h" -#include "mock_store.h" #include // ── MockTransportHost ──────────────────────────────────────────────────────── @@ -33,42 +32,8 @@ bool MockTransportConnection::reconnect() return true; } -QObject* MockTransportConnection::requestObject(const QString& objectName, int /*timeoutMs*/) +LogosObject* MockTransportConnection::requestObject(const QString& objectName, int /*timeoutMs*/) { qDebug() << "MockTransportConnection: requestObject" << objectName; - return new MockObject(objectName); -} - -void MockTransportConnection::releaseObject(QObject* object) -{ - delete object; -} - -QVariant MockTransportConnection::callRemoteMethod(QObject* object, - const QString& /*authToken*/, - const QString& methodName, - const QVariantList& args, - int /*timeoutMs*/) -{ - MockObject* mockObj = qobject_cast(object); - if (!mockObj) { - qWarning() << "MockTransportConnection: callRemoteMethod called with non-MockObject"; - return QVariant(); - } - - qDebug() << "MockTransportConnection: callRemoteMethod" - << mockObj->moduleName() << "::" << methodName - << "args:" << args; - - return MockStore::instance().recordAndReturn(mockObj->moduleName(), methodName, args); -} - -bool MockTransportConnection::callInformModuleToken(QObject* /*object*/, - const QString& /*authToken*/, - const QString& moduleName, - const QString& /*token*/, - int /*timeoutMs*/) -{ - qDebug() << "MockTransportConnection: callInformModuleToken (no-op)" << moduleName; - return true; + return new MockLogosObject(objectName); } diff --git a/cpp/implementations/mock/mock_transport.h b/cpp/implementations/mock/mock_transport.h index c87fbd5..6b92dab 100644 --- a/cpp/implementations/mock/mock_transport.h +++ b/cpp/implementations/mock/mock_transport.h @@ -2,23 +2,51 @@ #define MOCK_TRANSPORT_H #include "../../logos_transport.h" -#include +#include "../../logos_object.h" +#include "mock_store.h" #include +#include /** - * @brief Lightweight QObject that carries the module name through the transport pipeline. + * @brief LogosObject implementation for mock mode. * - * MockTransportConnection::requestObject() returns one of these so that - * callRemoteMethod() can look up which module is being called. + * Stores the module name and delegates callMethod to MockStore. + * Event operations are no-ops in mock mode. */ -class MockObject : public QObject { - Q_OBJECT +class MockLogosObject : public LogosObject { public: - explicit MockObject(const QString& moduleName, QObject* parent = nullptr) - : QObject(parent), m_moduleName(moduleName) {} + explicit MockLogosObject(const QString& moduleName) + : m_moduleName(moduleName) {} const QString& moduleName() const { return m_moduleName; } + QVariant callMethod(const QString& /*authToken*/, + const QString& methodName, + const QVariantList& args, + int /*timeoutMs*/) override + { + return MockStore::instance().recordAndReturn(m_moduleName, methodName, args); + } + + bool informModuleToken(const QString& /*authToken*/, + const QString& moduleName, + const QString& /*token*/, + int /*timeoutMs*/) override + { + Q_UNUSED(moduleName) + return true; + } + + void onEvent(const QString& /*eventName*/, EventCallback /*callback*/) override {} + void disconnectEvents() override {} + void emitEvent(const QString& /*eventName*/, const QVariantList& /*data*/) override {} + + QJsonArray getMethods() override { return QJsonArray(); } + + void release() override { delete this; } + + quintptr id() const override { return reinterpret_cast(this); } + private: QString m_moduleName; }; @@ -38,23 +66,14 @@ public: /** * @brief Consumer-side transport for mock mode. * - * requestObject returns a MockObject tagged with the module name. - * callRemoteMethod records the call in MockStore and returns the - * configured return value. + * requestObject returns a MockLogosObject tagged with the module name. */ class MockTransportConnection : public LogosTransportConnection { public: bool connectToHost() override; bool isConnected() const override; bool reconnect() override; - QObject* requestObject(const QString& objectName, int timeoutMs) override; - void releaseObject(QObject* object) override; - QVariant callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int timeoutMs) override; - bool callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int timeoutMs) override; + LogosObject* requestObject(const QString& objectName, int timeoutMs) override; }; #endif // MOCK_TRANSPORT_H diff --git a/cpp/implementations/qt_local/local_transport.cpp b/cpp/implementations/qt_local/local_transport.cpp index cdbe8e3..a257e1c 100644 --- a/cpp/implementations/qt_local/local_transport.cpp +++ b/cpp/implementations/qt_local/local_transport.cpp @@ -2,8 +2,120 @@ #include "../../plugin_registry.h" #include "../../module_proxy.h" #include +#include -// --- LocalTransportHost --- +// ── LocalLogosObject ───────────────────────────────────────────────────────── + +namespace { + +class EventHelper : public QObject { + Q_OBJECT +public: + explicit EventHelper(QObject* parent = nullptr) : QObject(parent) {} + + void addCallback(const QString& eventName, LogosObject::EventCallback cb) { + m_callbacks[eventName].append(std::move(cb)); + } + +public slots: + void onEventResponse(const QString& eventName, const QVariantList& data) { + auto cbs = m_callbacks.value(eventName); + if (!cbs.isEmpty()) { + qDebug() << "[LogosObject] Local EventHelper: dispatching event" << eventName << "to" << cbs.size() << "callback(s)"; + } + for (const auto& cb : cbs) { + try { cb(eventName, data); } catch (...) {} + } + } + +private: + QHash> m_callbacks; +}; + +} // anonymous namespace + +class LocalLogosObject : public LogosObject { +public: + explicit LocalLogosObject(ModuleProxy* proxy) + : m_proxy(proxy), m_helper(nullptr) + { + qDebug() << "[LogosObject] Created LocalLogosObject wrapping ModuleProxy" << reinterpret_cast(proxy); + } + + ~LocalLogosObject() override { + qDebug() << "[LogosObject] Destroying LocalLogosObject" << reinterpret_cast(m_proxy); + delete m_helper; + } + + QVariant callMethod(const QString& authToken, + const QString& methodName, + const QVariantList& args, + int /*timeoutMs*/) override + { + if (!m_proxy) return QVariant(); + qDebug() << "[LogosObject] LocalLogosObject::callMethod" << methodName << "args:" << args.size(); + return m_proxy->callRemoteMethod(authToken, methodName, args); + } + + bool informModuleToken(const QString& authToken, + const QString& moduleName, + const QString& token, + int /*timeoutMs*/) override + { + if (!m_proxy) return false; + return m_proxy->informModuleToken(authToken, moduleName, token); + } + + void onEvent(const QString& eventName, EventCallback callback) override + { + if (!m_proxy) return; + + qDebug() << "[LogosObject] LocalLogosObject::onEvent subscribing to event:" << eventName; + if (!m_helper) { + m_helper = new EventHelper(); + QObject::connect(m_proxy, SIGNAL(eventResponse(QString,QVariantList)), + m_helper, SLOT(onEventResponse(QString,QVariantList))); + qDebug() << "[LogosObject] LocalLogosObject: connected EventHelper to ModuleProxy signals"; + } + m_helper->addCallback(eventName, std::move(callback)); + } + + void disconnectEvents() override + { + delete m_helper; + m_helper = nullptr; + } + + void emitEvent(const QString& eventName, const QVariantList& data) override + { + if (!m_proxy) return; + qDebug() << "[LogosObject] LocalLogosObject::emitEvent" << eventName << "data:" << data.size() << "items"; + QMetaObject::invokeMethod(m_proxy, "eventResponse", + Qt::QueuedConnection, + Q_ARG(QString, eventName), + Q_ARG(QVariantList, data)); + } + + QJsonArray getMethods() override + { + if (!m_proxy) return QJsonArray(); + return m_proxy->getPluginMethods(); + } + + void release() override + { + // Local mode: we don't own the ModuleProxy, just stop using it + disconnectEvents(); + } + + quintptr id() const override { return reinterpret_cast(m_proxy); } + +private: + ModuleProxy* m_proxy; + EventHelper* m_helper; +}; + +// ── LocalTransportHost ─────────────────────────────────────────────────────── bool LocalTransportHost::publishObject(const QString& name, QObject* object) { @@ -20,7 +132,7 @@ void LocalTransportHost::unpublishObject(const QString& name) } } -// --- LocalTransportConnection --- +// ── LocalTransportConnection ───────────────────────────────────────────────── bool LocalTransportConnection::connectToHost() { @@ -38,54 +150,22 @@ bool LocalTransportConnection::reconnect() return true; } -QObject* LocalTransportConnection::requestObject(const QString& objectName, int /*timeoutMs*/) +LogosObject* LocalTransportConnection::requestObject(const QString& objectName, int /*timeoutMs*/) { QObject* plugin = PluginRegistry::getPlugin(objectName); if (!plugin) { qWarning() << "LocalTransportConnection: Plugin not found in registry:" << objectName; return nullptr; } - qDebug() << "LocalTransportConnection: Found plugin:" << objectName; - return plugin; -} -void LocalTransportConnection::releaseObject(QObject* /*object*/) -{ - // Local mode: we don't own the object, so nothing to do -} - -QVariant LocalTransportConnection::callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int /*timeoutMs*/) -{ - if (!object) { - qWarning() << "LocalTransportConnection: Cannot call method on null object"; - return QVariant(); - } - - ModuleProxy* proxy = qobject_cast(object); + ModuleProxy* proxy = qobject_cast(plugin); if (!proxy) { - qWarning() << "LocalTransportConnection: Object is not a ModuleProxy"; - return QVariant(); + qWarning() << "LocalTransportConnection: Plugin is not a ModuleProxy:" << objectName; + return nullptr; } - return proxy->callRemoteMethod(authToken, methodName, args); + qDebug() << "[LogosObject] LocalTransportConnection: returning LocalLogosObject for:" << objectName; + return new LocalLogosObject(proxy); } -bool LocalTransportConnection::callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int /*timeoutMs*/) -{ - if (!object) { - qWarning() << "LocalTransportConnection: Cannot call informModuleToken on null object"; - return false; - } - - ModuleProxy* proxy = qobject_cast(object); - if (!proxy) { - qWarning() << "LocalTransportConnection: Object is not a ModuleProxy"; - return false; - } - - return proxy->informModuleToken(authToken, moduleName, token); -} +#include "local_transport.moc" diff --git a/cpp/implementations/qt_local/local_transport.h b/cpp/implementations/qt_local/local_transport.h index c18f6ef..51ee171 100644 --- a/cpp/implementations/qt_local/local_transport.h +++ b/cpp/implementations/qt_local/local_transport.h @@ -2,6 +2,9 @@ #define LOCAL_TRANSPORT_H #include "../../logos_transport.h" +#include "../../logos_object.h" + +class ModuleProxy; class LocalTransportHost : public LogosTransportHost { public: @@ -14,14 +17,7 @@ public: bool connectToHost() override; bool isConnected() const override; bool reconnect() override; - QObject* requestObject(const QString& objectName, int timeoutMs) override; - void releaseObject(QObject* object) override; - QVariant callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int timeoutMs) override; - bool callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int timeoutMs) override; + LogosObject* requestObject(const QString& objectName, int timeoutMs) override; }; #endif // LOCAL_TRANSPORT_H diff --git a/cpp/implementations/qt_remote/remote_transport.cpp b/cpp/implementations/qt_remote/remote_transport.cpp index 69241e7..9f22da5 100644 --- a/cpp/implementations/qt_remote/remote_transport.cpp +++ b/cpp/implementations/qt_remote/remote_transport.cpp @@ -7,8 +7,177 @@ #include #include #include +#include -// --- RemoteTransportHost --- +// ── RemoteLogosObject ──────────────────────────────────────────────────────── + +namespace { + +class RemoteEventHelper : public QObject { + Q_OBJECT +public: + explicit RemoteEventHelper(QObject* parent = nullptr) : QObject(parent) {} + + void addCallback(const QString& eventName, LogosObject::EventCallback cb) { + m_callbacks[eventName].append(std::move(cb)); + } + +public slots: + void onEventResponse(const QString& eventName, const QVariantList& data) { + auto cbs = m_callbacks.value(eventName); + if (!cbs.isEmpty()) { + qDebug() << "[LogosObject] Remote EventHelper: dispatching event" << eventName << "to" << cbs.size() << "callback(s) (via IPC)"; + } + for (const auto& cb : cbs) { + try { cb(eventName, data); } catch (...) {} + } + } + +private: + QHash> m_callbacks; +}; + +} // anonymous namespace + +class RemoteLogosObject : public LogosObject { +public: + explicit RemoteLogosObject(QObject* replica) + : m_replica(replica), m_helper(nullptr) + { + qDebug() << "[LogosObject] Created RemoteLogosObject wrapping QRemoteObjectReplica" << reinterpret_cast(replica); + } + + ~RemoteLogosObject() override { + qDebug() << "[LogosObject] Destroying RemoteLogosObject" << reinterpret_cast(m_replica); + delete m_helper; + } + + QVariant callMethod(const QString& authToken, + const QString& methodName, + const QVariantList& args, + int timeoutMs) override + { + if (!m_replica) { + qWarning() << "RemoteLogosObject: Cannot call method on null replica"; + return QVariant(); + } + qDebug() << "[LogosObject] RemoteLogosObject::callMethod" << methodName << "args:" << args.size(); + + QRemoteObjectPendingCall pendingCall; + bool success = QMetaObject::invokeMethod( + m_replica, + "callRemoteMethod", + Qt::DirectConnection, + Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall), + Q_ARG(QString, authToken), + Q_ARG(QString, methodName), + Q_ARG(QVariantList, args) + ); + + if (!success) { + qWarning() << "RemoteLogosObject: Failed to invoke callRemoteMethod on replica"; + return QVariant(); + } + + pendingCall.waitForFinished(timeoutMs); + + if (!pendingCall.isFinished() || pendingCall.error() != QRemoteObjectPendingCall::NoError) { + qWarning() << "RemoteLogosObject: callRemoteMethod failed or timed out:" << pendingCall.error(); + return QVariant(); + } + + return pendingCall.returnValue(); + } + + bool informModuleToken(const QString& authToken, + const QString& moduleName, + const QString& token, + int timeoutMs) override + { + if (!m_replica) { + qWarning() << "RemoteLogosObject: Cannot call informModuleToken on null replica"; + return false; + } + + QRemoteObjectPendingCall pendingCall; + bool success = QMetaObject::invokeMethod( + m_replica, + "informModuleToken", + Qt::DirectConnection, + Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall), + Q_ARG(QString, authToken), + Q_ARG(QString, moduleName), + Q_ARG(QString, token) + ); + + if (!success) { + qWarning() << "RemoteLogosObject: Failed to invoke informModuleToken on replica"; + return false; + } + + pendingCall.waitForFinished(timeoutMs); + + if (!pendingCall.isFinished() || pendingCall.error() != QRemoteObjectPendingCall::NoError) { + qWarning() << "RemoteLogosObject: informModuleToken failed or timed out:" << pendingCall.error(); + return false; + } + + return pendingCall.returnValue().toBool(); + } + + void onEvent(const QString& eventName, EventCallback callback) override + { + if (!m_replica) return; + + qDebug() << "[LogosObject] RemoteLogosObject::onEvent subscribing to event:" << eventName; + if (!m_helper) { + m_helper = new RemoteEventHelper(); + QObject::connect(m_replica, SIGNAL(eventResponse(QString,QVariantList)), + m_helper, SLOT(onEventResponse(QString,QVariantList))); + qDebug() << "[LogosObject] RemoteLogosObject: connected EventHelper to QRemoteObjectReplica signals (IPC)"; + } + m_helper->addCallback(eventName, std::move(callback)); + } + + void disconnectEvents() override + { + delete m_helper; + m_helper = nullptr; + } + + void emitEvent(const QString& eventName, const QVariantList& data) override + { + if (!m_replica) return; + qDebug() << "[LogosObject] RemoteLogosObject::emitEvent" << eventName << "data:" << data.size() << "items (via IPC)"; + QMetaObject::invokeMethod(m_replica, "eventResponse", + Qt::QueuedConnection, + Q_ARG(QString, eventName), + Q_ARG(QVariantList, data)); + } + + QJsonArray getMethods() override + { + // Remote introspection not implemented — callers should use + // the local module inspection tools (lm) instead. + return QJsonArray(); + } + + void release() override + { + disconnectEvents(); + delete m_replica; + m_replica = nullptr; + delete this; + } + + quintptr id() const override { return reinterpret_cast(m_replica); } + +private: + QObject* m_replica; + RemoteEventHelper* m_helper; +}; + +// ── RemoteTransportHost ────────────────────────────────────────────────────── RemoteTransportHost::RemoteTransportHost(const QString& registryUrl) : m_registryHost(nullptr) @@ -43,11 +212,9 @@ bool RemoteTransportHost::publishObject(const QString& name, QObject* object) void RemoteTransportHost::unpublishObject(const QString& /*name*/) { - // Qt Remote Objects doesn't require explicit unregistration; - // the host cleanup handles it on destruction. } -// --- RemoteTransportConnection --- +// ── RemoteTransportConnection ──────────────────────────────────────────────── RemoteTransportConnection::RemoteTransportConnection(const QString& registryUrl) : m_node(new QRemoteObjectNode()) @@ -115,7 +282,7 @@ bool RemoteTransportConnection::connectToRegistry() return m_connected; } -QObject* RemoteTransportConnection::requestObject(const QString& objectName, int timeoutMs) +LogosObject* RemoteTransportConnection::requestObject(const QString& objectName, int timeoutMs) { if (!m_connected) { qWarning() << "RemoteTransportConnection: Not connected. Cannot request object:" << objectName; @@ -137,82 +304,8 @@ QObject* RemoteTransportConnection::requestObject(const QString& objectName, int return nullptr; } - qDebug() << "RemoteTransportConnection: Acquired replica for:" << objectName - << "at" << QTime::currentTime().toString("hh:mm:ss.zzz"); - return replica; + qDebug() << "[LogosObject] RemoteTransportConnection: returning RemoteLogosObject for:" << objectName; + return new RemoteLogosObject(replica); } -void RemoteTransportConnection::releaseObject(QObject* object) -{ - delete object; -} - -QVariant RemoteTransportConnection::callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int timeoutMs) -{ - if (!object) { - qWarning() << "RemoteTransportConnection: Cannot call method on null object"; - return QVariant(); - } - - QRemoteObjectPendingCall pendingCall; - bool success = QMetaObject::invokeMethod( - object, - "callRemoteMethod", - Qt::DirectConnection, - Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall), - Q_ARG(QString, authToken), - Q_ARG(QString, methodName), - Q_ARG(QVariantList, args) - ); - - if (!success) { - qWarning() << "RemoteTransportConnection: Failed to invoke callRemoteMethod on replica"; - return QVariant(); - } - - pendingCall.waitForFinished(timeoutMs); - - if (!pendingCall.isFinished() || pendingCall.error() != QRemoteObjectPendingCall::NoError) { - qWarning() << "RemoteTransportConnection: callRemoteMethod failed or timed out:" << pendingCall.error(); - return QVariant(); - } - - return pendingCall.returnValue(); -} - -bool RemoteTransportConnection::callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int timeoutMs) -{ - if (!object) { - qWarning() << "RemoteTransportConnection: Cannot call informModuleToken on null object"; - return false; - } - - QRemoteObjectPendingCall pendingCall; - bool success = QMetaObject::invokeMethod( - object, - "informModuleToken", - Qt::DirectConnection, - Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall), - Q_ARG(QString, authToken), - Q_ARG(QString, moduleName), - Q_ARG(QString, token) - ); - - if (!success) { - qWarning() << "RemoteTransportConnection: Failed to invoke informModuleToken on replica"; - return false; - } - - pendingCall.waitForFinished(timeoutMs); - - if (!pendingCall.isFinished() || pendingCall.error() != QRemoteObjectPendingCall::NoError) { - qWarning() << "RemoteTransportConnection: informModuleToken failed or timed out:" << pendingCall.error(); - return false; - } - - return pendingCall.returnValue().toBool(); -} +#include "remote_transport.moc" diff --git a/cpp/implementations/qt_remote/remote_transport.h b/cpp/implementations/qt_remote/remote_transport.h index ae0cdab..6ce826e 100644 --- a/cpp/implementations/qt_remote/remote_transport.h +++ b/cpp/implementations/qt_remote/remote_transport.h @@ -2,6 +2,7 @@ #define REMOTE_TRANSPORT_H #include "../../logos_transport.h" +#include "../../logos_object.h" #include class QRemoteObjectRegistryHost; @@ -28,14 +29,7 @@ public: bool connectToHost() override; bool isConnected() const override; bool reconnect() override; - QObject* requestObject(const QString& objectName, int timeoutMs) override; - void releaseObject(QObject* object) override; - QVariant callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int timeoutMs) override; - bool callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int timeoutMs) override; + LogosObject* requestObject(const QString& objectName, int timeoutMs) override; private: bool connectToRegistry(); diff --git a/cpp/logos_api_client.cpp b/cpp/logos_api_client.cpp index d9df72d..d1a4d57 100644 --- a/cpp/logos_api_client.cpp +++ b/cpp/logos_api_client.cpp @@ -1,5 +1,6 @@ #include "logos_api_client.h" #include "logos_api_consumer.h" +#include "logos_object.h" #include "token_manager.h" LogosAPIClient::LogosAPIClient(const QString& module_to_talk_to, const QString& origin_module, TokenManager* token_manager, QObject *parent) @@ -12,10 +13,9 @@ LogosAPIClient::LogosAPIClient(const QString& module_to_talk_to, const QString& LogosAPIClient::~LogosAPIClient() { - // m_consumer will be deleted automatically as it's a child object } -QObject* LogosAPIClient::requestObject(const QString& objectName, Timeout timeout) +LogosObject* LogosAPIClient::requestObject(const QString& objectName, Timeout timeout) { return m_consumer->requestObject(objectName, timeout); } @@ -40,7 +40,6 @@ QVariant LogosAPIClient::invokeRemoteMethod(const QString& objectName, const QSt { qDebug() << "LogosAPIClient: invoking remote method" << objectName << methodName << "args_count:" << args.size(); - // Get the token for the module QString token = getToken(objectName); if (token.isEmpty() && objectName != "capability_module") { @@ -48,19 +47,7 @@ QVariant LogosAPIClient::invokeRemoteMethod(const QString& objectName, const QSt LogosAPIConsumer* packageManagerConsumer = new LogosAPIConsumer("capability_module", m_origin_module, m_token_manager, this); QString capabilityToken = getToken("capability_module"); QVariant result = packageManagerConsumer->invokeRemoteMethod(capabilityToken, "capability_module", "requestModule", QVariantList() << m_origin_module << objectName, timeout); - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; qDebug() << "LogosAPIClient: requestModule result for" << objectName << ":" << result.toString(); - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - qDebug() << "================================================"; - token = result.toString(); } @@ -99,91 +86,26 @@ QVariant LogosAPIClient::invokeRemoteMethod(const QString& objectName, const QSt return invokeRemoteMethod(objectName, methodName, QVariantList() << arg1 << arg2 << arg3 << arg4 << arg5, timeout); } -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariantList& args, - std::function callback, - Timeout timeout) +void LogosAPIClient::onEvent(LogosObject* originObject, const QString& eventName, std::function callback) { - if (!callback) { - return; - } - QString token = getToken(objectName); - if (token.isEmpty() && objectName != "capability_module") { - LogosAPIConsumer* apiConsumer = new LogosAPIConsumer("capability_module", m_origin_module, m_token_manager, this); - QString capabilityToken = getToken("capability_module"); - QVariant result = apiConsumer->invokeRemoteMethod(capabilityToken, "capability_module", "requestModule", QVariantList() << m_origin_module << objectName, timeout); - token = result.toString(); - } - m_consumer->invokeRemoteMethodAsync(token, objectName, methodName, args, callback, timeout); + m_consumer->onEvent(originObject, eventName, std::move(callback)); } -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg, std::function callback, Timeout timeout) +void LogosAPIClient::onEventResponse(LogosObject* object, const QString& eventName, const QVariantList& data) { - invokeRemoteMethodAsync(objectName, methodName, QVariantList() << arg, callback, timeout); -} - -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, std::function callback, Timeout timeout) -{ - invokeRemoteMethodAsync(objectName, methodName, QVariantList() << arg1 << arg2, callback, timeout); -} - -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - std::function callback, Timeout timeout) -{ - invokeRemoteMethodAsync(objectName, methodName, QVariantList() << arg1 << arg2 << arg3, callback, timeout); -} - -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - const QVariant& arg4, - std::function callback, Timeout timeout) -{ - invokeRemoteMethodAsync(objectName, methodName, QVariantList() << arg1 << arg2 << arg3 << arg4, callback, timeout); -} - -void LogosAPIClient::invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - const QVariant& arg4, const QVariant& arg5, - std::function callback, Timeout timeout) -{ - invokeRemoteMethodAsync(objectName, methodName, QVariantList() << arg1 << arg2 << arg3 << arg4 << arg5, callback, timeout); -} - -void LogosAPIClient::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName, std::function callback) -{ - m_consumer->onEvent(originObject, destinationObject, eventName, callback); -} - -void LogosAPIClient::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName) -{ - m_consumer->onEvent(originObject, destinationObject, eventName); -} - - - -void LogosAPIClient::invokeCallback(const QString& eventName, const QVariantList& data) -{ - m_consumer->invokeCallback(eventName, data); -} - -void LogosAPIClient::onEventResponse(QObject* replica, const QString& eventName, const QVariantList& data) -{ - // qDebug() << "LogosAPIClient: Received event:" << eventName << "with data:" << data; - qDebug() << "LogosAPIClient: Received event:" << eventName; + qDebug() << "[LogosObject] LogosAPIClient::onEventResponse" << eventName << "-> LogosObject::emitEvent"; if (eventName.isEmpty()) { qWarning() << "LogosAPIClient: Event name cannot be empty"; return; } - // qDebug() << "LogosAPIClient: Emitting event:" << eventName << "with data:" << data; - qDebug() << "LogosAPIClient: Emitting event:" << eventName; + if (!object) { + qWarning() << "LogosAPIClient: Cannot emit event on null object"; + return; + } - // emit the eventResponse signal of replica - QMetaObject::invokeMethod(replica, "eventResponse", Qt::QueuedConnection, Q_ARG(QString, eventName), Q_ARG(QVariantList, data)); + object->emitEvent(eventName, data); } bool LogosAPIClient::informModuleToken(const QString& authToken, const QString& moduleName, const QString& token) @@ -205,19 +127,12 @@ QString LogosAPIClient::getToken(const QString& module_name) { qDebug() << "LogosAPIClient: getToken for module:" << module_name; - // if (m_token_manager) { - QString token = m_token_manager->getToken(module_name); - if (!token.isEmpty()) { - qDebug() << "LogosAPIClient: Found token for module:" << module_name; - return token; - } - // } else { - // qDebug() << "LogosAPIClient: No token manager found - using default AUTH_TOKEN"; - // } + QString token = m_token_manager->getToken(module_name); + if (!token.isEmpty()) { + qDebug() << "LogosAPIClient: Found token for module:" << module_name; + return token; + } qDebug() << "LogosAPIClient: No token found for module:" << module_name; - - // TODO: this is breaking here for core_manager - // return AUTH_TOKEN; return ""; } diff --git a/cpp/logos_api_client.h b/cpp/logos_api_client.h index 13219e3..38ed61e 100644 --- a/cpp/logos_api_client.h +++ b/cpp/logos_api_client.h @@ -11,246 +11,76 @@ #include "logos_mode.h" class LogosAPIConsumer; +class LogosObject; class TokenManager; /** * @brief LogosAPIClient provides a high-level interface for remote method calls * * This class serves as a facade over LogosAPIConsumer, providing a clean interface - * for applications that need to call remote methods and handle events. It includes - * additional logic like token management and request routing. + * for applications that need to call remote methods and handle events. */ class LogosAPIClient : public QObject { Q_OBJECT public: - /** - * @brief Construct a new LogosAPIClient - * @param module_to_talk_to The name of the module to connect to - * @param origin_module The name of the originating module - * @param token_manager Pointer to the token manager instance - * @param parent Parent QObject - */ explicit LogosAPIClient(const QString& module_to_talk_to, const QString& origin_module, TokenManager* token_manager, QObject *parent = nullptr); - - /** - * @brief Destructor - */ ~LogosAPIClient(); /** - * @brief Request a remote object replica by name - * @param objectName The name of the remote object to acquire - * @param timeout Timeout to wait for the replica to be ready (default 20000ms) - * @return QObject* pointer to the replica, or nullptr if failed + * @brief Request a LogosObject handle by name + * @return LogosObject* handle, or nullptr if failed */ - QObject* requestObject(const QString& objectName, Timeout timeout = Timeout()); + LogosObject* requestObject(const QString& objectName, Timeout timeout = Timeout()); - /** - * @brief Check if the client is connected to the registry - * @return true if connected, false otherwise - */ bool isConnected() const; - - /** - * @brief Get the registry URL this client is connected to - * @return QString containing the registry URL - */ QString registryUrl() const; - - /** - * @brief Reconnect to the registry - * @return true if reconnection successful, false otherwise - */ bool reconnect(); - /** - * @brief Invoke a remote method on a remote object - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param args Arguments to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariantList& args = QVariantList(), Timeout timeout = Timeout()); - /** - * @brief Invoke a remote method on a remote object with a single argument - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param arg Argument to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariant& arg, Timeout timeout = Timeout()); - /** - * @brief Invoke a remote method on a remote object with two arguments - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param arg1 First argument to pass to the method - * @param arg2 Second argument to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariant& arg1, const QVariant& arg2, Timeout timeout = Timeout()); - /** - * @brief Invoke a remote method on a remote object with three arguments - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param arg1 First argument to pass to the method - * @param arg2 Second argument to pass to the method - * @param arg3 Third argument to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, Timeout timeout = Timeout()); - /** - * @brief Invoke a remote method on a remote object with four arguments - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param arg1 First argument to pass to the method - * @param arg2 Second argument to pass to the method - * @param arg3 Third argument to pass to the method - * @param arg4 Fourth argument to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, const QVariant& arg4, Timeout timeout = Timeout()); - /** - * @brief Invoke a remote method on a remote object with five arguments - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param arg1 First argument to pass to the method - * @param arg2 Second argument to pass to the method - * @param arg3 Third argument to pass to the method - * @param arg4 Fourth argument to pass to the method - * @param arg5 Fifth argument to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& objectName, const QString& methodName, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, const QVariant& arg4, const QVariant& arg5, Timeout timeout = Timeout()); /** - * @brief Invoke a remote method asynchronously; result or error is delivered via callback - * @param objectName The name of the remote object - * @param methodName The name of the method to call - * @param args Arguments to pass to the method - * @param callback Called when the call completes (typically on the main thread) - * @param timeout Timeout for replica acquisition and for the remote call (default 20000ms) - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariantList& args, - std::function callback, - Timeout timeout = Timeout()); - - /** - * @brief Invoke a remote method asynchronously with a single argument - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg, std::function callback, Timeout timeout = Timeout()); - - /** - * @brief Invoke a remote method asynchronously with two arguments - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, std::function callback, Timeout timeout = Timeout()); - - /** - * @brief Invoke a remote method asynchronously with three arguments - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - std::function callback, Timeout timeout = Timeout()); - - /** - * @brief Invoke a remote method asynchronously with four arguments - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - const QVariant& arg4, - std::function callback, Timeout timeout = Timeout()); - - /** - * @brief Invoke a remote method asynchronously with five arguments - */ - void invokeRemoteMethodAsync(const QString& objectName, const QString& methodName, - const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, - const QVariant& arg4, const QVariant& arg5, - std::function callback, Timeout timeout = Timeout()); - - /** - * @brief Register an event listener for the specified event name - * @param originObject The object that will emit the event - * @param destinationObject The object that will receive the event + * @brief Register an event listener via LogosObject's callback mechanism + * @param originObject The LogosObject that will emit the event * @param eventName The name of the event to listen for * @param callback Function to call when the event is triggered */ - void onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName, + void onEvent(LogosObject* originObject, const QString& eventName, std::function callback); - - /** - * @brief Register an event listener without callback (connects to destinationObject's slot) - * @param originObject The object that will emit the event - * @param destinationObject The object that will receive the event - * @param eventName The name of the event to listen for - */ - void onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName); - - /** - * @brief Emit an event response (for plugins that also act as event sources) - * @param replica The replica object that should receive the event + * @brief Emit an event on a LogosObject (for plugins that act as event sources) + * @param object The LogosObject to emit the event on * @param eventName The name of the event * @param data The event data */ - void onEventResponse(QObject* replica, const QString& eventName, const QVariantList& data); + void onEventResponse(LogosObject* object, const QString& eventName, const QVariantList& data); - /** - * @brief Inform a module about a token - * @param authToken Authentication token for the operation - * @param moduleName The name of the module - * @param token The token to inform the module about - * @return bool true if successful, false otherwise - */ bool informModuleToken(const QString& authToken, const QString& moduleName, const QString& token); - bool informModuleToken_module(const QString& authToken, const QString& originModule, const QString& moduleName, const QString& token); - /** - * @brief Get the token manager instance - * @return TokenManager* Pointer to the token manager - */ TokenManager* getTokenManager() const; - - /** - * @brief Get authentication token for a module - * @param module_name The module name to get token for - * @return QString containing the token - */ QString getToken(const QString& module_name); -public slots: - /** - * @brief Helper slot to invoke stored callbacks - * @param eventName The name of the event that was triggered - * @param data The event data to pass to the callback - */ - void invokeCallback(const QString& eventName, const QVariantList& data); - private: LogosAPIConsumer* m_consumer; QMap m_tokens; @@ -258,4 +88,4 @@ private: QString m_origin_module; }; -#endif // LOGOS_API_CLIENT_H \ No newline at end of file +#endif // LOGOS_API_CLIENT_H diff --git a/cpp/logos_api_consumer.cpp b/cpp/logos_api_consumer.cpp index 02bcb5d..60ac0d0 100644 --- a/cpp/logos_api_consumer.cpp +++ b/cpp/logos_api_consumer.cpp @@ -1,4 +1,5 @@ #include "logos_api_consumer.h" +#include "logos_object.h" #include "module_proxy.h" #include "logos_api_client.h" #include "token_manager.h" @@ -6,10 +7,6 @@ #include "logos_instance.h" #include "logos_transport.h" #include "logos_transport_factory.h" -#include -#include -#include -#include #include #include #include @@ -26,14 +23,9 @@ LogosAPIConsumer::LogosAPIConsumer(const QString& module_to_talk_to, const QStri LogosAPIConsumer::~LogosAPIConsumer() { - for (auto it = m_connections.begin(); it != m_connections.end(); ++it) { - QObject::disconnect(it.value()); - } - m_eventCallbacks.clear(); - m_connections.clear(); } -QObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout timeout) +LogosObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout timeout) { qDebug() << "LogosAPIConsumer: Requesting object:" << objectName << "at" << QTime::currentTime().toString("hh:mm:ss.zzz"); @@ -47,9 +39,9 @@ QObject* LogosAPIConsumer::requestObject(const QString& objectName, Timeout time return nullptr; } - QObject* object = m_transport->requestObject(objectName, timeout.ms); + LogosObject* object = m_transport->requestObject(objectName, timeout.ms); if (object) { - qDebug() << "LogosAPIConsumer: Successfully acquired object:" << objectName; + qDebug() << "[LogosObject] LogosAPIConsumer: acquired LogosObject for:" << objectName << "(id:" << object->id() << ")"; } return object; } @@ -75,147 +67,46 @@ QVariant LogosAPIConsumer::invokeRemoteMethod(const QString& authToken, const QS { qDebug() << "LogosAPIConsumer: Calling invokeRemoteMethod:" << objectName << methodName << "args_count:" << args.size() << "timeout:" << timeout.ms; - QObject* plugin = m_transport->requestObject(objectName, timeout.ms); + LogosObject* plugin = m_transport->requestObject(objectName, timeout.ms); if (!plugin) { qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << objectName; return QVariant(); } - QVariant result = m_transport->callRemoteMethod(plugin, authToken, methodName, args, timeout.ms); - m_transport->releaseObject(plugin); + qDebug() << "[LogosObject] LogosAPIConsumer: calling via LogosObject::callMethod" << methodName; + QVariant result = plugin->callMethod(authToken, methodName, args, timeout.ms); + plugin->release(); return result; } -void LogosAPIConsumer::invokeRemoteMethodAsync(const QString& authToken, const QString& objectName, const QString& methodName, - const QVariantList& args, - AsyncResultCallback callback, - Timeout timeout) +void LogosAPIConsumer::onEvent(LogosObject* originObject, const QString& eventName, std::function callback) { - if (!callback) { - qWarning() << "LogosAPIConsumer: invokeRemoteMethodAsync called with null callback"; + qDebug() << "[LogosObject] LogosAPIConsumer::onEvent registering for:" << eventName << "on LogosObject id:" << originObject; + + if (!originObject) { + qWarning() << "LogosAPIConsumer: Cannot register event on null object"; return; } - QObject* plugin = requestObject(objectName, timeout); - if (!plugin) { - qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << objectName; - QTimer::singleShot(0, this, [callback]() { callback(QVariant()); }); - return; - } + originObject->onEvent(eventName, std::move(callback)); - ModuleProxy* moduleProxy = qobject_cast(plugin); - if (moduleProxy) { - QVariant result = moduleProxy->callRemoteMethod(authToken, methodName, args); - if (!LogosModeConfig::isLocal()) { - delete plugin; - } - QTimer::singleShot(0, this, [callback, result]() { callback(result); }); - return; - } - - if (LogosModeConfig::isLocal()) { - qWarning() << "LogosAPIConsumer: Local mode requires ModuleProxy-wrapped objects"; - QTimer::singleShot(0, this, [callback]() { callback(QVariant()); }); - return; - } - - QRemoteObjectPendingCall pendingCall; - bool success = QMetaObject::invokeMethod( - plugin, - "callRemoteMethod", - Qt::DirectConnection, - Q_RETURN_ARG(QRemoteObjectPendingCall, pendingCall), - Q_ARG(QString, authToken), - Q_ARG(QString, methodName), - Q_ARG(QVariantList, args) - ); - - if (!success) { - qWarning() << "LogosAPIConsumer: Failed to invoke callRemoteMethod on replica for object:" << objectName; - delete plugin; - QTimer::singleShot(0, this, [callback]() { callback(QVariant()); }); - return; - } - - QRemoteObjectPendingCallWatcher* watcher = new QRemoteObjectPendingCallWatcher(pendingCall, this); - QPointer watcherRef(watcher); - QObject* pluginToDelete = plugin; - // Use QueuedConnection so the callback always runs on the consumer's (e.g. main) thread, - // even if the watcher emits finished() from an IO or worker thread. Otherwise the callback - // may never run or may run in a context where UI/consumer state is inaccessible. - connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, [watcherRef, callback, pluginToDelete]() { - QVariant result; - if (!watcherRef.isNull() && watcherRef->error() == QRemoteObjectPendingCall::NoError) { - result = watcherRef->returnValue(); - } - if (callback) callback(result); - delete pluginToDelete; - if (!watcherRef.isNull()) watcherRef->deleteLater(); - }, Qt::QueuedConnection); - QTimer::singleShot(timeout.ms, this, [watcherRef, callback, pluginToDelete]() { - if (!watcherRef.isNull() && !watcherRef->isFinished()) { - if (callback) callback(QVariant()); - delete pluginToDelete; - watcherRef->deleteLater(); - } - }); -} - -void LogosAPIConsumer::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName, std::function callback) -{ - qDebug() << "LogosAPIConsumer: Registering event listener for event:" << eventName; - - m_eventCallbacks[eventName].append(callback); - - if (!m_connections.contains(originObject)) { - auto connection = QObject::connect(originObject, SIGNAL(eventResponse(QString, QVariantList)), - this, SLOT(invokeCallback(QString, QVariantList))); - - if (connection) { - m_connections[originObject] = connection; - qDebug() << "LogosAPIConsumer: Created new connection for origin object"; - } else { - qWarning() << "LogosAPIConsumer: Failed to create connection for event:" << eventName; - } - } else { - qDebug() << "LogosAPIConsumer: Reusing existing connection for origin object"; - } - - qDebug() << "LogosAPIConsumer: Registered callback for event:" << eventName; -} - -void LogosAPIConsumer::invokeCallback(const QString& eventName, const QVariantList& data) -{ - for (const auto& callback : m_eventCallbacks[eventName]) { - try { - callback(eventName, data); - } catch (...) { - qWarning() << "LogosAPIConsumer: Exception in callback for event:" << eventName; - } - } -} - -void LogosAPIConsumer::onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName) -{ - qDebug() << "LogosAPIConsumer: Registering event listener for event:" << eventName << "(connecting to destination slot)"; - - QObject::connect(originObject, SIGNAL(eventResponse(QString, QVariantList)), - destinationObject, SLOT(onEventResponse(QString, QVariantList)), Qt::AutoConnection); + qDebug() << "[LogosObject] LogosAPIConsumer: event callback registered for:" << eventName; } bool LogosAPIConsumer::informModuleToken(const QString& authToken, const QString& moduleName, const QString& token) { qDebug() << "LogosAPIConsumer: Informing module token for module:" << moduleName << "with token:" << token; - QObject* plugin = m_transport->requestObject("capability_module", 20000); + LogosObject* plugin = m_transport->requestObject("capability_module", 20000); if (!plugin) { qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object: capability_module"; return false; } - bool result = m_transport->callInformModuleToken(plugin, authToken, moduleName, token, 20000); + qDebug() << "[LogosObject] LogosAPIConsumer: calling LogosObject::informModuleToken for" << moduleName; + bool result = plugin->informModuleToken(authToken, moduleName, token, 20000); qDebug() << "LogosAPIConsumer: informModuleToken completed with result:" << result; - m_transport->releaseObject(plugin); + plugin->release(); return result; } @@ -223,14 +114,15 @@ bool LogosAPIConsumer::informModuleToken_module(const QString& authToken, const { qDebug() << "LogosAPIConsumer: Informing module token for module:" << moduleName << "with token:" << token; - QObject* plugin = m_transport->requestObject(originModule, 20000); + LogosObject* plugin = m_transport->requestObject(originModule, 20000); if (!plugin) { qWarning() << "LogosAPIConsumer: Failed to acquire plugin/replica for object:" << originModule; return false; } - bool result = m_transport->callInformModuleToken(plugin, authToken, moduleName, token, 20000); + qDebug() << "[LogosObject] LogosAPIConsumer: calling LogosObject::informModuleToken for" << moduleName << "on" << originModule; + bool result = plugin->informModuleToken(authToken, moduleName, token, 20000); qDebug() << "LogosAPIConsumer: informModuleToken completed with result:" << result; - m_transport->releaseObject(plugin); + plugin->release(); return result; } diff --git a/cpp/logos_api_consumer.h b/cpp/logos_api_consumer.h index 1940fb9..20de3e5 100644 --- a/cpp/logos_api_consumer.h +++ b/cpp/logos_api_consumer.h @@ -13,6 +13,7 @@ #include "logos_mode.h" class LogosTransportConnection; +class LogosObject; class TokenManager; /** @@ -20,7 +21,7 @@ class TokenManager; * * This class is responsible for the consumer/client side functionality: * - Connecting to module registries via the transport layer - * - Requesting object handles + * - Requesting LogosObject handles * - Invoking methods on objects * - Handling events from objects */ @@ -29,55 +30,19 @@ class LogosAPIConsumer : public QObject Q_OBJECT public: - /** - * @brief Construct a new LogosAPIConsumer - * @param module_to_talk_to The name of the module to connect to - * @param origin_module The name of the originating module - * @param token_manager Pointer to the token manager instance - * @param parent Parent QObject - */ explicit LogosAPIConsumer(const QString& module_to_talk_to, const QString& origin_module, TokenManager* token_manager, QObject *parent = nullptr); - - /** - * @brief Destructor - cleans up connections and resources - */ ~LogosAPIConsumer(); /** - * @brief Request an object handle by name - * @param objectName The name of the object to acquire - * @param timeout Timeout to wait for the object to be ready (default 20000ms) - * @return QObject* pointer to the object, or nullptr if failed + * @brief Request a LogosObject handle by name + * @return LogosObject* handle, or nullptr if failed. Caller must call release() when done. */ - QObject* requestObject(const QString& objectName, Timeout timeout = Timeout()); + LogosObject* requestObject(const QString& objectName, Timeout timeout = Timeout()); - /** - * @brief Check if the consumer is connected to the registry - * @return true if connected, false otherwise - */ bool isConnected() const; - - /** - * @brief Get the registry URL this consumer is connected to - * @return QString containing the registry URL - */ QString registryUrl() const; - - /** - * @brief Reconnect to the registry - * @return true if reconnection successful, false otherwise - */ bool reconnect(); - /** - * @brief Invoke a method on a module object - * @param authToken Authentication token for the operation - * @param objectName The name of the object - * @param methodName The name of the method to call - * @param args Arguments to pass to the method - * @param timeout Timeout to wait for the result (default 20000ms) - * @return QVariant containing the result, or invalid QVariant if failed - */ QVariant invokeRemoteMethod(const QString& authToken, const QString& objectName, const QString& methodName, const QVariantList& args = QVariantList(), Timeout timeout = Timeout()); @@ -99,40 +64,16 @@ public: Timeout timeout = Timeout()); /** - * @brief Register an event listener for the specified event name - * @param originObject The object that will emit the event - * @param destinationObject The object that will receive the event + * @brief Register an event listener via LogosObject's callback mechanism + * @param originObject The LogosObject that will emit the event * @param eventName The name of the event to listen for * @param callback Function to call when the event is triggered */ - void onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName, + void onEvent(LogosObject* originObject, const QString& eventName, std::function callback); - - /** - * @brief Register an event listener without callback (connects to destinationObject's slot) - * @param originObject The object that will emit the event - * @param destinationObject The object that will receive the event - * @param eventName The name of the event to listen for - */ - void onEvent(QObject* originObject, QObject* destinationObject, const QString& eventName); public slots: - /** - * @brief Helper slot to invoke stored callbacks - * @param eventName The name of the event that was triggered - * @param data The event data to pass to the callback - */ - void invokeCallback(const QString& eventName, const QVariantList& data); - - /** - * @brief Inform a module about a token - * @param authToken Authentication token for the operation - * @param moduleName The name of the module - * @param token The token to inform the module about - * @return bool true if successful, false otherwise - */ bool informModuleToken(const QString& authToken, const QString& moduleName, const QString& token); - bool informModuleToken_module(const QString& authToken, const QString& originModule, const QString& moduleName, const QString& token); private: @@ -140,9 +81,6 @@ private: QString m_registryUrl; QMap m_tokens; TokenManager* m_token_manager; - - QHash>> m_eventCallbacks; - QHash m_connections; }; #endif // LOGOS_API_CONSUMER_H diff --git a/cpp/logos_api_provider.cpp b/cpp/logos_api_provider.cpp index 71517a9..3cb9389 100644 --- a/cpp/logos_api_provider.cpp +++ b/cpp/logos_api_provider.cpp @@ -1,4 +1,5 @@ #include "logos_api_provider.h" +#include "logos_object.h" #include "module_proxy.h" #include "logos_api.h" #include "logos_instance.h" @@ -87,16 +88,19 @@ bool LogosAPIProvider::saveToken(const QString& from_module_name, const QString& return m_moduleProxy->saveToken(from_module_name, token); } -void LogosAPIProvider::onEventResponse(QObject* replica, const QString& eventName, const QVariantList& data) +void LogosAPIProvider::onEventResponse(LogosObject* object, const QString& eventName, const QVariantList& data) { - qDebug() << "LogosAPIProvider: Received event:" << eventName; + qDebug() << "[LogosObject] LogosAPIProvider::onEventResponse" << eventName << "-> LogosObject::emitEvent"; if (eventName.isEmpty()) { qWarning() << "LogosAPIProvider: Event name cannot be empty"; return; } - qDebug() << "LogosAPIProvider: Emitting event:" << eventName; + if (!object) { + qWarning() << "LogosAPIProvider: Cannot emit event on null object"; + return; + } - QMetaObject::invokeMethod(replica, "eventResponse", Qt::QueuedConnection, Q_ARG(QString, eventName), Q_ARG(QVariantList, data)); + object->emitEvent(eventName, data); } diff --git a/cpp/logos_api_provider.h b/cpp/logos_api_provider.h index abdaaa5..863bdb4 100644 --- a/cpp/logos_api_provider.h +++ b/cpp/logos_api_provider.h @@ -9,6 +9,7 @@ #include class LogosTransportHost; +class LogosObject; class ModuleProxy; /** @@ -24,48 +25,28 @@ class LogosAPIProvider : public QObject Q_OBJECT public: - /** - * @brief Construct a new LogosAPIProvider - * @param module_name The name of this module - * @param parent Parent QObject - */ explicit LogosAPIProvider(const QString& module_name, QObject *parent = nullptr); - - /** - * @brief Destructor - unpublishes registered objects - */ ~LogosAPIProvider(); /** - * @brief Register an object to be available for access by consumers - * @param name The name to register the object under - * @param object The object to register - * @return true if registration successful, false otherwise + * @brief Register an object to be available for access by consumers. + * + * The provider side remains Qt-based: plugins are QObjects loaded via + * QPluginLoader. Internally this wraps them in a ModuleProxy. */ bool registerObject(const QString& name, QObject* object); - /** - * @brief Get the registry URL for this provider - * @return QString containing the registry URL - */ QString registryUrl() const; - - /** - * @brief Save a token from a module via the proxy - * @param from_module_name The name of the module providing the token - * @param token The token to save - * @return bool true if token was saved successfully, false otherwise - */ bool saveToken(const QString& from_module_name, const QString& token); public slots: /** * @brief Handle event responses from objects - * @param replica The replica object that should receive the event + * @param object The LogosObject that should receive the event * @param eventName The name of the event * @param data The event data */ - void onEventResponse(QObject* replica, const QString& eventName, const QVariantList& data); + void onEventResponse(LogosObject* object, const QString& eventName, const QVariantList& data); private: std::unique_ptr m_transport; diff --git a/cpp/logos_object.h b/cpp/logos_object.h new file mode 100644 index 0000000..7e1126d --- /dev/null +++ b/cpp/logos_object.h @@ -0,0 +1,99 @@ +#ifndef LOGOS_OBJECT_H +#define LOGOS_OBJECT_H + +#include +#include +#include +#include +#include +#include + +/** + * @brief Abstract interface for a module object handle. + * + * LogosObject decouples callers from the underlying transport mechanism. + * Each transport (local/Qt Remote Objects/mock/JSON-RPC/...) provides its + * own concrete subclass. Callers interact exclusively through this + * interface and never need to know the implementation type. + */ +class LogosObject { +public: + virtual ~LogosObject() = default; + + /** + * @brief Invoke a method on the remote/local module. + * @param authToken Authentication token for the operation + * @param methodName Method to call on the underlying module + * @param args Arguments for the method + * @param timeoutMs Maximum time to wait for the result + * @return The method result, or an invalid QVariant on failure + */ + virtual QVariant callMethod(const QString& authToken, + const QString& methodName, + const QVariantList& args, + int timeoutMs) = 0; + + /** + * @brief Deliver a module token to the underlying module. + * @param authToken Authentication token for the operation + * @param moduleName Target module name + * @param token The token to deliver + * @param timeoutMs Maximum time to wait for the result + * @return true if the token was delivered successfully + */ + virtual bool informModuleToken(const QString& authToken, + const QString& moduleName, + const QString& token, + int timeoutMs) = 0; + + using EventCallback = std::function; + + /** + * @brief Subscribe to events from this object. + * + * Qt-based implementations use QObject::connect internally; + * other implementations may use a different mechanism. + * + * @param eventName The event name to listen for + * @param callback Called when the event fires + */ + virtual void onEvent(const QString& eventName, EventCallback callback) = 0; + + /** + * @brief Remove all event subscriptions made via onEvent(). + */ + virtual void disconnectEvents() = 0; + + /** + * @brief Emit an event on this object. + * + * For Qt-based implementations this triggers the underlying + * QObject signal so that Qt Remote Objects can replicate it. + * + * @param eventName The event name + * @param data Event payload + */ + virtual void emitEvent(const QString& eventName, const QVariantList& data) = 0; + + /** + * @brief Return introspection data for the methods exposed by + * the underlying module. + */ + virtual QJsonArray getMethods() = 0; + + /** + * @brief Release resources associated with this handle. + * + * After calling release() the object must not be used again. + * Implementations that own the underlying resource (e.g. a + * QRemoteObjectReplica) will delete it here. + */ + virtual void release() = 0; + + /** + * @brief Stable identity value suitable for use as a hash key. + */ + virtual quintptr id() const = 0; +}; + +#endif // LOGOS_OBJECT_H diff --git a/cpp/logos_transport.h b/cpp/logos_transport.h index d52458e..9324bfe 100644 --- a/cpp/logos_transport.h +++ b/cpp/logos_transport.h @@ -6,6 +6,7 @@ #include class QObject; +class LogosObject; /** * @brief Abstract interface for the provider/server side of module transport. @@ -20,7 +21,7 @@ public: /** * @brief Publish an object so consumers can discover and invoke it * @param name The name to publish the object under - * @param object The QObject to publish + * @param object The QObject to publish (provider side remains Qt-based) * @return true if publishing succeeded */ virtual bool publishObject(const QString& name, QObject* object) = 0; @@ -35,8 +36,9 @@ public: /** * @brief Abstract interface for the consumer/client side of module transport. * - * Implementations handle how a consumer connects to a host, acquires object - * handles, and invokes methods on them. + * Implementations handle how a consumer connects to a host and acquires + * LogosObject handles. Method invocation, event subscription, and lifecycle + * management are handled by LogosObject itself. */ class LogosTransportConnection { public: @@ -60,44 +62,16 @@ public: virtual bool reconnect() = 0; /** - * @brief Acquire a handle to a named object from the host + * @brief Acquire a LogosObject handle to a named object from the host. + * + * The returned LogosObject encapsulates method invocation, event + * handling and lifecycle. Call LogosObject::release() when done. + * * @param objectName The published name of the object * @param timeoutMs Maximum time to wait for the object to become available - * @return QObject* handle, or nullptr on failure. Caller must use releaseObject() when done. + * @return LogosObject* handle, or nullptr on failure. */ - virtual QObject* requestObject(const QString& objectName, int timeoutMs) = 0; - - /** - * @brief Release a previously acquired object handle - * @param object The handle returned by requestObject() - */ - virtual void releaseObject(QObject* object) = 0; - - /** - * @brief Invoke callRemoteMethod on the given object handle - * @param object Handle from requestObject() - * @param authToken Authentication token - * @param methodName Method to call on the underlying module - * @param args Arguments for the method - * @param timeoutMs Maximum time to wait for the result - * @return The method result, or an invalid QVariant on failure - */ - virtual QVariant callRemoteMethod(QObject* object, const QString& authToken, - const QString& methodName, const QVariantList& args, - int timeoutMs) = 0; - - /** - * @brief Invoke informModuleToken on the given object handle - * @param object Handle from requestObject() - * @param authToken Authentication token - * @param moduleName Target module name - * @param token The token to deliver - * @param timeoutMs Maximum time to wait for the result - * @return true if the token was delivered successfully - */ - virtual bool callInformModuleToken(QObject* object, const QString& authToken, - const QString& moduleName, const QString& token, - int timeoutMs) = 0; + virtual LogosObject* requestObject(const QString& objectName, int timeoutMs) = 0; }; #endif // LOGOS_TRANSPORT_H diff --git a/docs/docs.md b/docs/docs.md index f9fbc51..b2694b8 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -295,7 +295,7 @@ Triggering an event: QVariantList data; data << timestamp << nick << message; -logosAPI->getClient("chat")->onEventResponse(this, "chatMessage", data); +emit eventResponse("chatMessage", data); ``` Triggering an event with the generated helpers: diff --git a/nix/include.nix b/nix/include.nix index 5d07e3b..a03638d 100644 --- a/nix/include.nix +++ b/nix/include.nix @@ -31,7 +31,7 @@ pkgs.stdenv.mkDerivation { for file in logos_types.cpp logos_types.h logos_api.cpp logos_api.h logos_api_client.cpp logos_api_client.h \ logos_api_consumer.cpp logos_api_consumer.h logos_api_provider.cpp logos_api_provider.h \ token_manager.cpp token_manager.h module_proxy.cpp module_proxy.h logos_mode.h \ - logos_instance.h \ + logos_instance.h logos_object.h \ logos_transport.h logos_transport_factory.h logos_transport_factory.cpp \ logos_registry.h logos_registry_factory.h logos_registry_factory.cpp \ plugin_registry.h; do