From 60fc8b70748fb9ad9bcddcfd0daca88957328c8b Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 8 Apr 2014 17:24:45 +0200 Subject: [PATCH] refs #199, featuring proxy to server side DBus signals. So far we only could send server to proxy side signals, causing inconsistencies between remote and local contexts --- src/blackcore/context.cpp | 21 ++++++++++ src/blackcore/context_application.h | 46 +++++++++++++++++++-- src/blackcore/context_application_impl.cpp | 7 ++++ src/blackcore/context_application_impl.h | 3 ++ src/blackcore/context_application_proxy.cpp | 20 ++++++++- src/blackcore/context_application_proxy.h | 3 ++ 6 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/blackcore/context.cpp b/src/blackcore/context.cpp index eb1a03c5c..fa32f5edd 100644 --- a/src/blackcore/context.cpp +++ b/src/blackcore/context.cpp @@ -1,4 +1,5 @@ #include "context.h" +#include namespace BlackCore { @@ -48,6 +49,26 @@ namespace BlackCore return this->getRuntime()->getIContextSimulator(); } + void CContext::reEmitSignalFromProxy(const QString &signalName) + { + if (signalName.isEmpty()) return; + if (this->usingLocalObjects()) + { + // resent in implementation + QString sn = signalName; + if (!sn.endsWith("()")) sn.append("()"); + const QMetaObject *metaObject = this->metaObject(); + int signalId = metaObject->indexOfSignal(sn.toUtf8().constData()); + Q_ASSERT(signalId >= 0); + void *a[] = { 0 }; + QMetaObject::activate(this, signalId, a); + } + else + { + Q_ASSERT_X(false, "signalFromProxy", "Proxy needs to override method"); + } + } + const IContextSimulator *CContext::getIContextSimulator() const { return this->getRuntime()->getIContextSimulator(); diff --git a/src/blackcore/context_application.h b/src/blackcore/context_application.h index 150aa90cf..3e19efa77 100644 --- a/src/blackcore/context_application.h +++ b/src/blackcore/context_application.h @@ -7,7 +7,7 @@ #define BLACKCORE_CONTEXTAPPLICATION_H #include "blackcore/context.h" -#include "blackmisc/statusmessage.h" +#include "blackmisc/statusmessagelist.h" #include #define BLACKCORE_CONTEXTAPPLICATION_INTERFACENAME "net.vatsim.PilotClient.BlackCore.ContextApplication" @@ -29,6 +29,15 @@ namespace BlackCore public: + //! What output to redirect + enum RedirectionLevel + { + RedirectNone, + RedirectAllOutput, + RedirectWarningAndAbove, + RedirectError + }; + //! Service name static const QString &InterfaceName() { @@ -46,20 +55,51 @@ namespace BlackCore //! Destructor virtual ~IContextApplication() {} + //! Output redirection (redirect my output) + virtual RedirectionLevel getOutputRedirectionLevel() const = 0; + + //! Output redirection (redirect my output) + virtual void setOutputRedirectionLevel(RedirectionLevel level) = 0; + + //! Redirected output generated by others + virtual RedirectionLevel getStreamingForRedirectedOutputLevel() const = 0; + + //! Redirected output generated by others + virtual void setStreamingForRedirectedOutputLevel(RedirectionLevel level) = 0; + signals: //! \brief Status message + //! \remarks not to be called directly, use IContextApplication::sendStatusMessage void statusMessage(const BlackMisc::CStatusMessage &message); + //! Send status messages + //! \remarks not to be called directly, use IContextApplication::sendStatusMessages + void statusMessages(const BlackMisc::CStatusMessageList &messages); + + //! Redirect output streams as by qDebug(), qWarning(), qCritical() + //! \remarks context mode is an important means to avoid infinite redirect loops + //! never output redirected stream messages from the same context again + void redirectedOutput(const BlackMisc::CStatusMessage &message, qint64 contextId); + //! Widget GUI is about to start - void widgetGuiStarting() const; + void widgetGuiStarting(); //! Widget GUI is about to terminate - void widgetGuiTerminating() const; + void widgetGuiTerminating(); public slots: //! \brief Ping a token, used to check if application is alive virtual qint64 ping(qint64 token) const = 0; + + //! \copydoc CContext::reEmitSignalFromProxy + virtual void signalFromProxy(const QString &signalName) = 0; + + //! \brief Status message + virtual void sendStatusMessage(const BlackMisc::CStatusMessage &message) = 0; + + //! Send status messages + virtual void sendStatusMessages(const BlackMisc::CStatusMessageList &messages) = 0; }; } diff --git a/src/blackcore/context_application_impl.cpp b/src/blackcore/context_application_impl.cpp index 989170e69..d46066c5c 100644 --- a/src/blackcore/context_application_impl.cpp +++ b/src/blackcore/context_application_impl.cpp @@ -27,4 +27,11 @@ namespace BlackCore { return token; } + * Re-emit signal + */ + void CContextApplication::signalFromProxy(const QString &signalName) + { + CContext::reEmitSignalFromProxy(signalName); + } + } // namespace diff --git a/src/blackcore/context_application_impl.h b/src/blackcore/context_application_impl.h index 3beb95846..98cf65d8c 100644 --- a/src/blackcore/context_application_impl.h +++ b/src/blackcore/context_application_impl.h @@ -23,6 +23,9 @@ namespace BlackCore Q_OBJECT friend class CRuntime; + //! \copydoc CContext::reEmitSignalFromProxy + virtual void signalFromProxy(const QString &signalName) override; + protected: //! Constructor CContextApplication(CRuntimeConfig::ContextMode mode, CRuntime *runtime); diff --git a/src/blackcore/context_application_proxy.cpp b/src/blackcore/context_application_proxy.cpp index cf317fe34..593f5fa22 100644 --- a/src/blackcore/context_application_proxy.cpp +++ b/src/blackcore/context_application_proxy.cpp @@ -26,12 +26,20 @@ namespace BlackCore */ void CContextApplicationProxy::relaySignals(const QString &serviceName, QDBusConnection &connection) { + // signals originating from impl side connection.connect(serviceName, IContextApplication::ObjectPath(), IContextApplication::InterfaceName(), "statusMessage", this, SIGNAL(statusMessage(BlackMisc::CStatusMessage))); connection.connect(serviceName, IContextApplication::ObjectPath(), IContextApplication::InterfaceName(), - "widgetGuiStarting", this, SIGNAL(widgetGuiStarting())); + "statusMessages", this, SIGNAL(statusMessages(BlackMisc::CStatusMessageList))); connection.connect(serviceName, IContextApplication::ObjectPath(), IContextApplication::InterfaceName(), - "widgetGuiTerminating", this, SIGNAL(widgetGuiTerminating())); + "redirectedOutput", this, SIGNAL(redirectedOutput(BlackMisc::CStatusMessage, qint64))); + + // 1. No need to connect widgetGuiTerminating, only orginates from Proxy side / or is local + // 2. No need to connect widgetGuiStarting + + // signals originating from proxy side + connect(this, &CContextApplicationProxy::widgetGuiStarting, [this] { this->signalFromProxy("widgetGuiStarting");}); + connect(this, &CContextApplicationProxy::widgetGuiTerminating, [this] { this->signalFromProxy("widgetGuiTerminating");}); } /* @@ -43,4 +51,12 @@ namespace BlackCore return t; } + /* + * Signal from proxy + */ + void CContextApplicationProxy::signalFromProxy(const QString &signalName) + { + this->m_dBusInterface->callDBus(QLatin1Literal("signalFromProxy"), signalName); + } + } // namespace diff --git a/src/blackcore/context_application_proxy.h b/src/blackcore/context_application_proxy.h index d7f123814..435172f87 100644 --- a/src/blackcore/context_application_proxy.h +++ b/src/blackcore/context_application_proxy.h @@ -28,6 +28,9 @@ namespace BlackCore //! \copydoc IContextApplication::ping() virtual qint64 ping(qint64 token) const override; + //! \copydoc CContext::reEmitSignalFromProxy + void signalFromProxy(const QString &signalName) override; + protected: //! Constructor CContextApplicationProxy(CRuntimeConfig::ContextMode mode, CRuntime *runtime) : IContextApplication(mode, runtime), m_dBusInterface(nullptr) {}