From d451419b0d65909ec1b98e0ef72f48f07a48d046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Fri, 28 Aug 2020 16:12:02 +0200 Subject: [PATCH 01/12] Standardize facelift argument exchange Change-Id: Ifd09ce0e4b16a6a060d2a2634adc614f56b3a139 --- .../templates/IPCAdapter.template.cpp | 35 +++ .../facelift/templates/IPCCommon.template.h | 13 - .../IPCDBusServiceAdapter.template.h | 9 +- .../facelift/templates/IPCProxy.template.cpp | 23 ++ .../templates/IPCProxyAdapter.template.cpp | 168 +++++++---- .../templates/IPCProxyAdapter.template.h | 19 +- .../templates/IPCServiceAdapter.template.cpp | 172 +++++++----- .../templates/IPCServiceAdapter.template.h | 9 +- .../templates/ImplementationBase.template.h | 1 + .../facelift/templates/Module.template.cpp | 7 - .../facelift/templates/Service.template.cpp | 1 + codegen/facelift/templates/Service.template.h | 4 +- codegen/facelift/templates/Struct.template.h | 47 +++- src/ipc/dbus/CMakeLists.txt | 1 + src/ipc/dbus/DBusIPCCommon.h | 20 +- src/ipc/dbus/DBusIPCMessage.cpp | 39 ++- src/ipc/dbus/DBusIPCMessage.h | 7 +- src/ipc/dbus/DBusIPCProxy.h | 57 ++-- src/ipc/dbus/DBusIPCProxyBinder.cpp | 46 +-- src/ipc/dbus/DBusIPCProxyBinder.h | 70 ++--- src/ipc/dbus/DBusManager.cpp | 8 + src/ipc/dbus/DBusObjectRegistry.cpp | 2 +- src/ipc/dbus/DBusRequestHandler.h | 6 +- src/ipc/dbus/IPCDBusServiceAdapter.h | 29 ++ src/ipc/dbus/IPCDBusServiceAdapterBase.cpp | 67 ++--- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 93 ++----- .../ipc-common/AppendDBUSSignatureFunction.h | 68 ----- src/ipc/ipc-common/CMakeLists.txt | 13 - src/ipc/ipc-common/DBusSignatureHelper.h | 141 ---------- .../IPCAdapterModelPropertyHandler.h | 41 ++- src/ipc/ipc-common/IPCProxyBase.h | 3 +- src/ipc/ipc-common/IPCProxyBaseBase.cpp | 47 ---- src/ipc/ipc-common/IPCProxyBaseBase.h | 51 ---- src/ipc/ipc-common/IPCProxyModelProperty.h | 127 ++++----- src/ipc/ipc-common/IPCTypeHandler.h | 262 ------------------ src/ipc/ipc-common/IPCTypeRegisterHandler.h | 149 ---------- src/ipc/ipc-common/InputPayLoad.cpp | 43 --- src/ipc/ipc-common/InputPayLoad.h | 69 ----- src/ipc/ipc-common/OutputPayLoad.cpp | 39 --- src/ipc/ipc-common/OutputPayLoad.h | 69 ----- .../ipc-common/SerializeParameterFunction.h | 67 ----- src/ipc/ipc-common/ipc-common.h | 24 -- src/ipc/ipc-common/ipc-serialization.cpp | 31 --- src/ipc/ipc-common/ipc-serialization.h | 78 ------ src/ipc/local/FaceliftIPCCommon.h | 9 +- src/ipc/local/LocalIPC-serialization.h | 113 ++------ src/ipc/local/LocalIPCMessage.cpp | 33 +-- src/ipc/local/LocalIPCMessage.h | 21 +- src/ipc/local/LocalIPCProxy.h | 36 --- src/ipc/local/LocalIPCProxyBase.h | 11 + src/ipc/local/LocalIPCProxyBinder.cpp | 28 +- src/ipc/local/LocalIPCProxyBinder.h | 12 +- src/ipc/local/LocalIPCRequestHandler.h | 7 +- src/ipc/local/LocalIPCServiceAdapter.h | 11 + src/ipc/local/LocalIPCServiceAdapterBase.cpp | 40 +-- src/ipc/local/LocalIPCServiceAdapterBase.h | 36 +-- src/model/CMakeLists.txt | 1 + src/model/FaceliftEnum.h | 41 +++ 58 files changed, 813 insertions(+), 1861 deletions(-) delete mode 100644 src/ipc/ipc-common/AppendDBUSSignatureFunction.h delete mode 100644 src/ipc/ipc-common/DBusSignatureHelper.h delete mode 100644 src/ipc/ipc-common/IPCProxyBaseBase.cpp delete mode 100644 src/ipc/ipc-common/IPCProxyBaseBase.h delete mode 100644 src/ipc/ipc-common/IPCTypeHandler.h delete mode 100644 src/ipc/ipc-common/IPCTypeRegisterHandler.h delete mode 100644 src/ipc/ipc-common/InputPayLoad.cpp delete mode 100644 src/ipc/ipc-common/InputPayLoad.h delete mode 100644 src/ipc/ipc-common/OutputPayLoad.cpp delete mode 100644 src/ipc/ipc-common/OutputPayLoad.h delete mode 100644 src/ipc/ipc-common/SerializeParameterFunction.h delete mode 100644 src/ipc/ipc-common/ipc-serialization.cpp delete mode 100644 src/ipc/ipc-common/ipc-serialization.h diff --git a/codegen/facelift/templates/IPCAdapter.template.cpp b/codegen/facelift/templates/IPCAdapter.template.cpp index 331dacf7..7a67e9f6 100644 --- a/codegen/facelift/templates/IPCAdapter.template.cpp +++ b/codegen/facelift/templates/IPCAdapter.template.cpp @@ -39,10 +39,29 @@ #include "InterfaceManager.h" #ifdef DBUS_IPC_ENABLED +#include #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusAdapter.h" +{% for struct in module.structs %} +#include "{{struct.fullyQualifiedPath}}.h" +{% endfor %} + +{% for enum in module.enums %} +#include "{{enum.fullyQualifiedPath}}.h" +{% endfor %} + {% for property in interface.referencedInterfaceTypes %} #include "{{property.fullyQualifiedPath}}{% if generateAsyncProxy %}Async{% endif %}IPCDBusAdapter.h" {% endfor %} + +{% for type in interface.referencedTypes %} +{% if (not type.is_primitive) %} +{% if (not type.is_model) %} +{% if (not type.is_interface) %} +{{type.requiredInclude}} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} #endif {{module.namespaceCppOpen}} @@ -80,6 +99,22 @@ struct {{interfaceName}}IPCAdapter::Impl { {{interfaceName}}IPCAdapter::{{interfaceName}}IPCAdapter(QObject* parent) : BaseType(facelift::InterfaceManager::instance(), parent) { +#ifdef DBUS_IPC_ENABLED + {% for type in interface.referencedTypes %} + {% if (not type.is_primitive) %} + {% if (not type.is_model) %} + {% if (not type.is_interface) %} + qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + {% if type.is_struct %} + {{type.fullyQualifiedCppType}}::registerDBusTypes(); + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +#endif } {{interfaceName}}IPCAdapter::~{{interfaceName}}IPCAdapter() { diff --git a/codegen/facelift/templates/IPCCommon.template.h b/codegen/facelift/templates/IPCCommon.template.h index 345988c0..cfb8db42 100644 --- a/codegen/facelift/templates/IPCCommon.template.h +++ b/codegen/facelift/templates/IPCCommon.template.h @@ -47,25 +47,12 @@ class {{classExport}} {{interfaceName}}IPCCommon {{operation.name}}, {% endfor %} {% for property in interface.properties %} - {% if (not property.readonly) %} - set{{property.name}}, - {% endif %} {% if (property.type.is_model) %} {{property.name}}, // model {% endif %} {% endfor %} }; - enum class SignalID { - invalid = static_cast(facelift::CommonSignalID::firstSpecific), - {% for signal in interface.signals %} - {{signal.name}}, - {% endfor %} - {% for property in interface.properties %} - {{property.name}}, - {% endfor %} - }; - }; {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index 8441e5c6..0fdcec71 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -67,7 +67,6 @@ class {{classExport}} {{className}}: public {{baseClass}} using ServiceType = {{interfaceName}}; using BaseType = {{baseClass}}; using ThisType = {{className}}; - using SignalID = {{interface}}IPCCommon::SignalID; using MethodID = {{interface}}IPCCommon::MethodID; {{className}}(QObject* parent = nullptr) : @@ -87,7 +86,11 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - void serializePropertyValues(OutputIPCMessage& msg, bool isCompleteSnapshot) override; + void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + + void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + + void setProperty(const QList& arguments) override; {% for event in interface.signals %} void {{event}}( @@ -96,7 +99,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{ comma() }}{{parameter.interfaceCppType}} {{parameter.name}} {%- endfor -%} ) { - sendSignal(SignalID::{{event}} + sendSignal("{{event}}" {%- for parameter in event.parameters -%} , {{parameter.name}} {%- endfor -%} ); diff --git a/codegen/facelift/templates/IPCProxy.template.cpp b/codegen/facelift/templates/IPCProxy.template.cpp index 5d100338..bf98e9ba 100644 --- a/codegen/facelift/templates/IPCProxy.template.cpp +++ b/codegen/facelift/templates/IPCProxy.template.cpp @@ -39,6 +39,15 @@ #ifdef DBUS_IPC_ENABLED #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusProxy.h" +{% for type in interface.referencedTypes %} +{% if (not type.is_primitive) %} +{% if (not type.is_model) %} +{% if (not type.is_interface) %} +{{type.requiredInclude}} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} #endif {% set className = interfaceName + "IPCProxy" %} @@ -81,6 +90,20 @@ struct {{className}}::Impl { {{className}}::{{className}}(QObject *parent) : BaseType(facelift::InterfaceManager::instance(), parent), m_impl(std::make_unique()) { +#ifdef DBUS_IPC_ENABLED + {% for type in interface.referencedTypes %} + {% if (not type.is_primitive) %} + {% if (not type.is_model) %} + {% if (not type.is_interface) %} + qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +#endif + ipc()->setObjectPath(SINGLETON_OBJECT_PATH); {% if generateAsyncProxy %} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index e7d50b71..45f89b51 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -36,6 +36,8 @@ {% set className = interfaceName + proxyTypeNameSuffix %} #include "{{className}}.h" +#include "FaceliftEnum.h" +#include "DBusIPCCommon.h" {{module.namespaceCppOpen}} @@ -55,76 +57,135 @@ {% endif %} } -void {{className}}::deserializePropertyValues(InputIPCMessage &msg, bool isCompleteSnapshot) +void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) { - {% for property in interface.properties %} - {% if property.type.is_interface %} - bool emit_{{property.name}}ChangeSignal = false; - QString {{property.name}}_objectPath; - if (deserializeOptionalValue(msg, {{property.name}}_objectPath, isCompleteSnapshot)) - { - m_{{property.name}}Proxy.update({{property.name}}_objectPath); - m_{{property.name}} = m_{{property.name}}Proxy.getValue(); - emit_{{property.name}}ChangeSignal = true; - } - {% elif property.type.is_model %} - bool emit_{{property.name}}ChangeSignal = false; - if (isCompleteSnapshot) { - int {{property.name}}Size; - deserializeValue(msg, {{property.name}}Size); - m_{{property.name}}.beginResetModel(); - m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); - m_{{property.name}}.endResetModel(); - emit_{{property.name}}ChangeSignal = true; + QListIterator argumentsIterator(msg.arguments()); + if (argumentsIterator.hasNext()) { + QMap values = castArgument>(argumentsIterator.next()); + for (const QString &propertyName: values.keys()) { + {% for property in interface.properties %} + {% if property.type.is_interface %} + if (propertyName == QStringLiteral("{{property.name}}")) { + bool emit_{{property.name}}ChangeSignal = false; + QString {{property.name}}_objectPath = castDBusVariantArgument(values[propertyName]); + m_{{property.name}}Proxy.update({{property.name}}_objectPath); + m_{{property.name}} = m_{{property.name}}Proxy.getValue(); + emit_{{property.name}}ChangeSignal = true; + if (emit_{{property.name}}ChangeSignal) + emit {{property.name}}Changed(); + } + {% elif property.type.is_model %} + if (propertyName == QStringLiteral("{{property.name}}")) { + bool emit_{{property.name}}ChangeSignal = false; + int {{property.name}}Size = castDBusVariantArgument(values[propertyName]); + m_{{property.name}}.beginResetModel(); + m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); + m_{{property.name}}.endResetModel(); + emit_{{property.name}}ChangeSignal = true; + if (emit_{{property.name}}ChangeSignal) + emit {{property.name}}Changed(); + } + {% else %} + if (propertyName == QStringLiteral("{{property.name}}")) { + const auto previous_{{property.name}}_Value = m_{{property.name}}; + {% if (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} + m_{{property.name}} = castDBusVariantArgument(values[propertyName]); + {% else %} + m_{{property.name}} = castDBusVariantArgument<{{property.interfaceCppType}}>(values[propertyName]); + {% endif %} + bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); + if (emit_{{property.name}}ChangeSignal) + emit {{property.name}}Changed(); + } + {% endif %} + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + bool previousIsReady = this->ready(); + m_serviceReady = castDBusVariantArgument(values[propertyName]); + bool emit_ReadyChangeSignal = (previousIsReady != m_serviceReady); + if (emit_ReadyChangeSignal) + emit readyChanged(); + } + } } - {% else %} - const auto previous_{{property.name}}_Value = m_{{property.name}}; - deserializeOptionalValue(msg, m_{{property.name}}, isCompleteSnapshot); - bool emit_{{property.name}}ChangeSignal = isCompleteSnapshot && ((previous_{{property.name}}_Value != m_{{property.name}})); - {% endif %} - {% endfor %} - - bool emit_ReadyChangeSignal = deserializeReadyValue(msg, isCompleteSnapshot) && isCompleteSnapshot; - - {% for property in interface.properties %} - if (emit_{{property.name}}ChangeSignal) - emit {{property.name}}Changed(); - {% endfor %} - - if (emit_ReadyChangeSignal) - emit readyChanged(); - } -void {{className}}::deserializeSignal(InputIPCMessage &msg) +void {{className}}::handleSignals(InputIPCMessage& msg) { - SignalID member; - deserializeValue(msg, member); - {% for event in interface.signals %} - if (member == SignalID::{{event}}) - { + if (msg.member() == QStringLiteral("{{event}}")) { + QListIterator argumentsIterator(msg.arguments()); {% for parameter in event.parameters %} {{parameter.interfaceCppType}} param_{{parameter.name}}; - deserializeValue(msg, param_{{parameter.name}}); + param_{{parameter.name}} = (argumentsIterator.hasNext() ? castArgument<{{parameter.interfaceCppType}}>(argumentsIterator.next()): {{parameter.interfaceCppType}}()); {% endfor %} emit {{event}}( {%- set comma = joiner(", ") -%} {%- for parameter in event.parameters -%} {{ comma() }}param_{{parameter.name}} {%- endfor -%} ); - } else + } + {% endfor %} + + {% if interface.hasModelProperty %} + this->onModelUpdateEvent(msg); + {% endif %} +} + +const QList& {{className}}::getSignals() const +{ + static QList allSignals{ + {% for event in interface.signals %} + "{{event}}", {% endfor %} + {% if interface.hasModelProperty %} + "ModelUpdateEventDataChanged", + "ModelUpdateEventInsert", + "ModelUpdateEventRemove", + "ModelUpdateEventMove", + "ModelUpdateEventReset" + {% endif %} + }; + + return allSignals; +} + +{% if interface.hasModelProperty %} +void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) +{ + QListIterator argumentsIterator(msg.arguments()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); {% for property in interface.properties %} - if (member == SignalID::{{property.name}}) { {% if property.type.is_model %} + if (modelPropertyName == QStringLiteral("{{property.name}}")) { m_{{property.name}}.handleSignal(msg); - {% else %} - emit {{property.name}}Changed(); + } {% endif %} - } else {% endfor %} - BaseType::deserializeCommonSignal(static_cast(member), this); +} +{% endif %} + +void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) +{ + QListIterator argumentsIterator(msg.arguments()); + QString interfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + QVariantMap changedProperties = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QVariantMap()); + for (const QString &propertyName: changedProperties.keys()) { + {% for property in interface.properties %} + {% if property.type.is_interface %} + {% elif property.type.is_model %} + {% else %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} + m_{{property.name}} = castArgument(changedProperties[propertyName]); + {% else %} + m_{{property.name}} = castArgument<{{property.cppType}}>(changedProperties[propertyName]); + {% endif %} + emit {{property.name}}Changed(); // trust the propertiesChanged signal and emit without checking + } + {% endif %} + {% endfor %} + } } {% for property in interface.properties %} @@ -134,7 +195,7 @@ void {{className}}::deserializeSignal(InputIPCMessage &msg) void {{className}}::set{{property}}({{property.cppMethodArgumentType}} newValue) { {% if (not property.type.is_interface) %} - ipc()->sendSetterCall(memberID(MethodID::set{{property.name}}, "set{{property.name}}"), newValue); + ipc()->sendSetterCall("{{property.name}}", newValue); {% else %} Q_ASSERT(false); // Writable interface properties are unsupported {% endif %} @@ -168,12 +229,11 @@ void {{className}}::{{operation.name}}( {%- endfor -%} ){% if operation.is_const %} const{% endif %} { {% if (operation.hasReturnValue) %} - {{operation.interfaceCppType}} returnValue; - ipc()->sendMethodCallWithReturn(memberID(MethodID::{{operation.name}}, "{{operation.name}}"), returnValue + QList args = ipc()->sendMethodCallWithReturn(memberID(MethodID::{{operation.name}}, "{{operation.name}}") {%- for parameter in operation.parameters -%} , {{parameter.name}} {%- endfor -%} ); - return returnValue; + return (!args.isEmpty() ? castArgument<{{operation.interfaceCppType}}>(args[0]): {{operation.interfaceCppType}}()); {% else %} ipc()->sendMethodCall(memberID(MethodID::{{operation.name}}, "{{operation.name}}") {%- for parameter in operation.parameters -%} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index 8731a5b3..96651a87 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -60,7 +60,6 @@ class {{classExport}} {{className}} : public {{baseClass}} using ThisType = {{className}}; using BaseType = {{baseClass}}; - using SignalID = {{interface}}IPCCommon::SignalID; using MethodID = {{interface}}IPCCommon::MethodID; // override the default QMLAdapter type to add the IPC related properties @@ -68,7 +67,7 @@ class {{classExport}} {{className}} : public {{baseClass}} {{className}}(QObject *parent = nullptr); - void deserializePropertyValues(InputIPCMessage &msg, bool isCompleteSnapshot) override; + void unmarshalPropertyValues(InputIPCMessage &msg) override; {% if interface.hasModelProperty %} void setServiceRegistered(bool isRegistered) override @@ -85,7 +84,10 @@ class {{classExport}} {{className}} : public {{baseClass}} {% endif %} - void deserializeSignal(InputIPCMessage &msg) override; + void handleSignals(InputIPCMessage& msg) override; + const QList& getSignals() const override; + + void unmarshalPropertiesChanged(InputIPCMessage &msg) override; {% for operation in interface.operations %} @@ -122,7 +124,6 @@ class {{classExport}} {{className}} : public {{baseClass}} } {% elif property.type.is_list %} - const {{property.interfaceCppType}}& {{property}}() const override { return m_{{property.name}}; @@ -150,6 +151,15 @@ class {{classExport}} {{className}} : public {{baseClass}} {% endif %} {% endfor %} + {% if interface.hasModelProperty %} + void onModelUpdateEvent(const InputIPCMessage& msg); + + Q_SIGNAL void ModelUpdateEventDataChanged(const InputIPCMessage& msg); + Q_SIGNAL void ModelUpdateEventInsert(const InputIPCMessage& msg); + Q_SIGNAL void ModelUpdateEventRemove(const InputIPCMessage& msg); + Q_SIGNAL void ModelUpdateEventMove(const InputIPCMessage& msg); + Q_SIGNAL void ModelUpdateEventReset(const InputIPCMessage& msg); + {% endif %} private: {% for property in interface.properties %} {% if property.type.is_interface %} @@ -159,6 +169,7 @@ class {{classExport}} {{className}} : public {{baseClass}} facelift::IPCProxyModelProperty m_{{property.name}}; {% endif %} {% endfor %} + }; diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 068ed434..d2f9486b 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -35,9 +35,10 @@ {% set className = interfaceName + proxyTypeNameSuffix %} +#include +#include "DBusIPCCommon.h" #include "{{className}}.h" - {{module.namespaceCppOpen}} facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessage &requestMessage, @@ -45,7 +46,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa { Q_UNUSED(replyMessage); // Since we do not always have return values Q_UNUSED(requestMessage); - + QListIterator argumentsIterator(requestMessage.arguments()); const auto &member = requestMessage.member(); Q_UNUSED(member); // In case there are no methods auto theService = service(); @@ -56,8 +57,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for operation in interface.operations %} if (member == memberID(MethodID::{{operation.name}}, "{{operation.name}}")) { {% for parameter in operation.parameters %} - {{parameter.cppType}} param_{{parameter.name}}; - deserializeValue(requestMessage, param_{{parameter.name}}); + {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castArgument<{{parameter.cppType}}>(argumentsIterator.next()): {{parameter.cppType}}()); {% endfor %} {% if operation.isAsync %} theService->{{operation.name}}({% for parameter in operation.parameters %} param_{{parameter.name}}, {%- endfor -%} @@ -75,7 +75,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {{ comma() }}param_{{parameter.name}} {%- endfor -%}); {% if operation.hasReturnValue %} - serializeValue(replyMessage, returnValue); + replyMessage << QVariant::fromValue(returnValue); {% endif %} {% endif %} } else @@ -86,17 +86,6 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa m_{{property.name}}Handler.handleModelRequest(requestMessage, replyMessage); } else {% endif %} - {% if (not property.readonly) %} - if (member == memberID(MethodID::set{{property.name}}, "set{{property.name}}")) { - {% if (not property.type.is_interface) %} - {{property.cppType}} value; - deserializeValue(requestMessage, value); - theService->set{{property.name}}(value); - {% else %} - Q_ASSERT(false); // Writable interface properties are unsupported - {% endif %} - } else - {% endif %} {% endfor %} { return facelift::IPCHandlingResult::INVALID; @@ -109,42 +98,49 @@ void {{className}}::appendDBUSIntrospectionData(QTextStream &s) const { Q_UNUSED(s); // For empty interfaces {% for property in interface.properties %} - ::facelift::DBusSignatureHelper::addPropertySignature(s, "{{property.name}}", {{ property.readonly | cppBool }}); + {% if not property.type.is_model %} + s << QStringLiteral("").arg(typeToSignature<{{property.type.interfaceCppType}}>(), + {{ property.readonly | cppBool }} ? QStringLiteral("read"): QStringLiteral("readwrite")); + {% endif %} {% endfor %} - {% for operation in interface.operations %} + s << QStringLiteral(""); - { - std::array argumentNames = { { - {%- for parameter in operation.parameters -%} - "{{parameter}}", - {%- endfor -%} - } }; - ::facelift::DBusSignatureHelper::addMethodSignature< - {%- set comma = joiner(", ") -%} - {%- for parameter in operation.parameters -%} - {{ comma() }}{{parameter.cppType}} - {%- endfor -%} - >(s, "{{operation.name}}", argumentNames); - } + {% for operation in interface.operations %} + s << ""; + {%- for parameter in operation.parameters -%} + s << "(); + s << "\" direction=\"in\"/>"; + {%- endfor -%} + + {% if operation.hasReturnValue %} + s << "(); + s << "\" direction=\"out\"/>"; + {% endif %}; + s << ""; {% endfor %} // signals {% for signal in interface.signals %} { - std::array argumentNames = { { - {%- for parameter in signal.parameters -%} - "{{parameter}}", - {%- endfor -%} - }}; - ::facelift::DBusSignatureHelper::addSignalSignature< - {%- set comma = joiner(", ") -%} + s << ""; {%- for parameter in signal.parameters -%} - {{ comma() }}{{parameter.interfaceCppType}} + s << "(); + s << "\" direction=\"out\"/>"; {%- endfor -%} - >(s, "{{signal.name}}", argumentNames); + s << ""; } - {% endfor %} + + {% if interface.hasModelProperty %} + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + {% endif %} } void {{className}}::connectSignals() @@ -154,10 +150,8 @@ void {{className}}::connectSignals() {% for property in interface.properties %} {% if property.type.is_model %} - m_{{property.name}}Handler.connectModel(SignalID::{{property.name}}, theService->{{property.name}}()); + m_{{property.name}}Handler.connectModel(QStringLiteral("{{property.name}}"), theService->{{property.name}}()); {% elif property.type.is_interface %} - {% else %} - m_previous{{property.name}} = theService->{{property.name}}(); {% endif %} {% endfor %} @@ -169,39 +163,93 @@ void {{className}}::connectSignals() m_{{property.name}}.update(this, theService->{{property.name}}()); }); {% endif %} - QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this] () { - this->sendSignal(SignalID::{{property.name}}); + {% if (not property.type.is_model) %} + QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this, theService] () { + this->sendPropertiesChanged("{{property.name}}", theService->{{property.name}}()); }); + {% endif %} {% endfor %} + QObject::connect(theService, &ServiceType::readyChanged, this, [this, theService] () { + this->sendPropertiesChanged("ready", theService->ready()); + }); + // Signals {% for signal in interface.signals %} QObject::connect(theService, &ServiceType::{{signal}}, this, &ThisType::{{signal}}); {% endfor %} } -void {{className}}::serializePropertyValues(OutputIPCMessage& msg, bool isCompleteSnapshot) +void {{className}}::marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) { - auto theService = service(); - {#% if (not interface.properties) %#} - Q_UNUSED(theService); - {#% endif %#} + QListIterator argumentsIterator(arguments); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto theService = service(); + QMap ret; + {#% if (not interface.properties) %#} + Q_UNUSED(theService); + {#% endif %#} + + {% for property in interface.properties %} + {% if property.type.is_interface %} + ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(m_{{property.name}}.objectPath())); + {% elif property.type.is_model %} + ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(theService->{{property.name}}().size())); + {% elif (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} + ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(QStringList(theService->{{property.name}}()))); + {% else %} + ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(theService->{{property.name}}())); + {% endif %} + {% endfor %} + ret["ready"] = QDBusVariant(QVariant::fromValue(theService->ready())); + msg << QVariant::fromValue(ret); + } +} - {% for property in interface.properties %} - {% if property.type.is_interface %} +void {{className}}::marshalProperty(const QList& arguments, OutputIPCMessage& msg) +{ + QListIterator argumentsIterator(arguments); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + {% for property in interface.properties %} + {% if property.type.is_interface %} - serializeOptionalValue(msg, m_{{property.name}}.objectPath(), m_previous{{property.name}}ObjectPath, isCompleteSnapshot); + {% elif property.type.is_model %} - {% elif property.type.is_model %} - if (isCompleteSnapshot) { - serializeValue(msg, theService->{{property.name}}().size()); + {% else %} + if (propertyName == QStringLiteral("{{property.name}}")) { + msg << QVariant::fromValue(service()->{{property.name}}()); + } + {% endif %} + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + msg << QVariant::fromValue(service()->ready()); + } } - {% else %} - serializeOptionalValue(msg, theService->{{property.name}}(), m_previous{{property.name}}, isCompleteSnapshot); - {% endif %} - {% endfor %} +} - BaseType::serializePropertyValues(msg, isCompleteSnapshot); +void {{className}}::setProperty(const QList& arguments) +{ + QListIterator argumentsIterator(arguments); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + if (argumentsIterator.hasNext()) { + {% for property in interface.properties %} + {% if property.type.is_interface %} + + {% elif property.type.is_model %} + + {% elif (not property.readonly) %} + if (propertyName == QStringLiteral("{{property.name}}")) { + service()->set{{property.name}}(castDBusVariantArgument<{{property.cppType}}>(argumentsIterator.next())); + } + {% endif %} + {% endfor %} + } + } } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index 4551f550..10cd513c 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -64,7 +64,6 @@ class {{classExport}} {{className}}: public {{baseClass}} using ServiceType = {{interfaceName}}; using BaseType = {{baseClass}}; using ThisType = {{className}}; - using SignalID = {{interface}}IPCCommon::SignalID; using MethodID = {{interface}}IPCCommon::MethodID; {{className}}(QObject* parent = nullptr) : BaseType(parent) @@ -83,7 +82,11 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - void serializePropertyValues(OutputIPCMessage& msg, bool isCompleteSnapshot) override; + void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + + void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + + void setProperty(const QList& arguments) override; {% for event in interface.signals %} void {{event}}( @@ -92,7 +95,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{ comma() }}{{parameter.interfaceCppType}} {{parameter.name}} {%- endfor -%} ) { - sendSignal(SignalID::{{event}} + sendSignal("{{event}}" {%- for parameter in event.parameters -%} , {{parameter.name}} {%- endfor -%} ); diff --git a/codegen/facelift/templates/ImplementationBase.template.h b/codegen/facelift/templates/ImplementationBase.template.h index 6f9a23e5..9ee36edb 100644 --- a/codegen/facelift/templates/ImplementationBase.template.h +++ b/codegen/facelift/templates/ImplementationBase.template.h @@ -91,6 +91,7 @@ class {{classExport}} {{interfaceName}}ImplementationBase : public {{interfaceNa {% endif %} {% endfor %} + Q_PROPERTY(bool ready READ ready) bool ready() const override { return m_ready.value(); diff --git a/codegen/facelift/templates/Module.template.cpp b/codegen/facelift/templates/Module.template.cpp index 6dea4e1c..d0474ac9 100644 --- a/codegen/facelift/templates/Module.template.cpp +++ b/codegen/facelift/templates/Module.template.cpp @@ -76,13 +76,6 @@ void Module::registerTypes() if (!alreadyRegistered) { alreadyRegistered = true; - {% for enum in module.enums %} - facelift::qRegisterMetaType<{{enum.fullyQualifiedCppType}}>(); - {% endfor %} - {% for struct in module.structs %} - qRegisterMetaType<{{struct.fullyQualifiedCppType}}>(); - {% endfor %} - #ifdef ENABLE_DESKTOP_TOOLS ModuleMonitor::registerTypes(); #endif diff --git a/codegen/facelift/templates/Service.template.cpp b/codegen/facelift/templates/Service.template.cpp index 23b1a86b..82728d66 100644 --- a/codegen/facelift/templates/Service.template.cpp +++ b/codegen/facelift/templates/Service.template.cpp @@ -58,6 +58,7 @@ constexpr const char* {{interfaceName}}::FULLY_QUALIFIED_INTERFACE_NAME; }); } #endif + registerTypes(""); } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Service.template.h b/codegen/facelift/templates/Service.template.h index 8f87f979..3d15564a 100644 --- a/codegen/facelift/templates/Service.template.h +++ b/codegen/facelift/templates/Service.template.h @@ -40,6 +40,7 @@ {{classExportDefines}} #include "FaceliftModel.h" +#include // Dependencies {% for type in interface.referencedTypes %} @@ -122,9 +123,6 @@ class {{classExport}} {{interfaceName}} : public facelift::InterfaceBase { return facelift::ServicePropertyInterface(this, &ThisType::{{property}}, &ThisType::{{property}}Changed); } - {% if (not property.readonly) %} - virtual void set{{property}}( {{property.cppMethodArgumentType}} newValue) = 0; - {% endif %} {% else %} using PropertyType_{{property}} = {{property.interfaceCppType}}; virtual const {{property.interfaceCppType}}& {{property}}() const = 0; diff --git a/codegen/facelift/templates/Struct.template.h b/codegen/facelift/templates/Struct.template.h index b50bae7e..3db17c53 100644 --- a/codegen/facelift/templates/Struct.template.h +++ b/codegen/facelift/templates/Struct.template.h @@ -39,6 +39,8 @@ {{classExportDefines}} +#include +#include #include "Structure.h" #include "FaceliftQMLUtils.h" @@ -84,6 +86,27 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {{struct.name}}& operator=(const {{struct.name}} &right); + friend QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}); + + static void registerDBusTypes() + { + {% for field in struct.fields %} + {% if field.type.is_struct %} + {{field.type.cppType}}::registerDBusTypes(); + {% endif %} + {% if (not field.type.is_primitive and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} + qDBusRegisterMetaType<{{field.cppType}}>(); + {% endif %} + {% if (field.type.is_list or field.type.is_map) %} + {% if (not field.type.nested.is_primitive) %} + qDBusRegisterMetaType<{{field.cppType}}>(); + qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); + {% endif %} + {% endif %} + {% endfor %} + } + Q_INVOKABLE {{struct.fullyQualifiedCppType}} clone() const; {% if struct.isSerializable %} @@ -126,6 +149,26 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {% endfor -%} }; +inline QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}) +{ + argument.beginStructure(); + {% for field in struct.fields %} + argument << {{struct.name|lower}}.m_{{field}}; + {% endfor -%} + argument.endStructure(); + return argument; +} + +inline const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}) +{ + argument.beginStructure(); + {% for field in struct.fields %} + argument >> {{struct.name|lower}}.m_{{field}}; + {% endfor -%} + argument.endStructure(); + + return argument; +} {{module.namespaceCppClose}} @@ -144,8 +187,10 @@ inline QDebug operator<< (QDebug d, const {{struct.fullyQualifiedCppType}} &f) return d; } +typedef QMap QMapOf{{struct.fullyQualifiedCppType|replace("::","")}}; + Q_DECLARE_METATYPE(QList<{{struct.fullyQualifiedCppType}}>) // Needed for list properties -//Q_DECLARE_METATYPE(QMap) // TODO: Needed for map properties? +Q_DECLARE_METATYPE(QMapOf{{struct.fullyQualifiedCppType|replace("::","")}}) Q_DECLARE_METATYPE({{struct.fullyQualifiedCppType}}) diff --git a/src/ipc/dbus/CMakeLists.txt b/src/ipc/dbus/CMakeLists.txt index 39d2d97f..e865445a 100644 --- a/src/ipc/dbus/CMakeLists.txt +++ b/src/ipc/dbus/CMakeLists.txt @@ -21,6 +21,7 @@ if(Qt5DBus_FOUND) DBusIPCProxyBinder.cpp DBusManager.cpp HEADERS + DBusIPCCommon.h DBusManager.h DBusManagerInterface.h DBusIPCProxy.h diff --git a/src/ipc/dbus/DBusIPCCommon.h b/src/ipc/dbus/DBusIPCCommon.h index 9f3280aa..710ee5ee 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -36,15 +36,29 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif +#include + +template +const char* typeToSignature() +{ + return QDBusMetaType::typeToSignature(qMetaTypeId()); +} + +template<> +inline const char* typeToSignature>() +{ + return QDBusMetaType::typeToSignature(qMetaTypeId()); +} + namespace facelift { namespace dbus { using namespace facelift; struct FaceliftIPCLibDBus_EXPORT DBusIPCCommon { - static constexpr const char *GET_PROPERTIES_MESSAGE_NAME = "GetAllProperties"; + static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; + static constexpr const char *GET_PROPERTY = "Get"; + static constexpr const char *SET_PROPERTY = "Set"; static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *SIGNAL_TRIGGERED_SIGNAL_NAME = "SignalTriggered"; - static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "SetProperty"; static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; static constexpr const char *DEFAULT_SERVICE_NAME = "facelift.registry"; diff --git a/src/ipc/dbus/DBusIPCMessage.cpp b/src/ipc/dbus/DBusIPCMessage.cpp index cd7b6056..77bc35f8 100644 --- a/src/ipc/dbus/DBusIPCMessage.cpp +++ b/src/ipc/dbus/DBusIPCMessage.cpp @@ -67,6 +67,24 @@ DBusIPCMessage::DBusIPCMessage(const QString &path, const QString &interface, co m_message = QDBusMessage::createSignal(path, interface, signal); } +QList DBusIPCMessage::arguments() const +{ + return m_message.arguments(); +} + +DBusIPCMessage &DBusIPCMessage::operator<<(const QVariant &arg) +{ + static int qListStringTypeId = qMetaTypeId>(); + if (arg.userType() != qListStringTypeId) { // workaround to use QList since its signature matches the QStringList + m_message << arg; + } + else { + QStringList stringList(arg.value>()); + m_message << stringList; + } + return *this; +} + QString DBusIPCMessage::member() const { return m_message.member(); @@ -119,28 +137,7 @@ bool DBusIPCMessage::isErrorMessage() const return (m_message.type() == QDBusMessage::ErrorMessage); } -OutputPayLoad &DBusIPCMessage::outputPayLoad() -{ - if (m_outputPayload == nullptr) { - m_outputPayload = std::make_unique(m_payload); - } - return *m_outputPayload; -} - -InputPayLoad &DBusIPCMessage::inputPayLoad() -{ - if (m_inputPayload == nullptr) { - m_payload = m_message.arguments()[0].value(); - m_inputPayload = std::make_unique(m_payload); - } - return *m_inputPayload; -} - QDBusMessage& DBusIPCMessage::outputMessage() { - if (m_outputPayload) { - m_message << m_outputPayload->getContent(); - m_outputPayload.reset(); - } return m_message; } diff --git a/src/ipc/dbus/DBusIPCMessage.h b/src/ipc/dbus/DBusIPCMessage.h index 0198bd36..e517d322 100644 --- a/src/ipc/dbus/DBusIPCMessage.h +++ b/src/ipc/dbus/DBusIPCMessage.h @@ -60,20 +60,17 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCMessage QString member() const; QString toString() const; + QList arguments() const; + DBusIPCMessage &operator<<(const QVariant &arg); DBusIPCMessage createReply(); DBusIPCMessage createErrorReply(const QString &msg, const QString &member); QString signature() const; bool isReplyMessage() const; bool isErrorMessage() const; - OutputPayLoad &outputPayLoad(); - InputPayLoad &inputPayLoad(); QDBusMessage& outputMessage(); private: QDBusMessage m_message; - QByteArray m_payload; - std::unique_ptr m_outputPayload; - std::unique_ptr m_inputPayload; }; } // end namespace dbus diff --git a/src/ipc/dbus/DBusIPCProxy.h b/src/ipc/dbus/DBusIPCProxy.h index 8111ad4d..6f19d579 100644 --- a/src/ipc/dbus/DBusIPCProxy.h +++ b/src/ipc/dbus/DBusIPCProxy.h @@ -56,6 +56,8 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa using InputIPCMessage = ::facelift::dbus::DBusIPCMessage; using OutputIPCMessage = ::facelift::dbus::DBusIPCMessage; + template struct type { }; + template using IPCProxyType = typename Type::IPCDBusProxyType; @@ -78,42 +80,6 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa return memberName; } - template - void serializeValue(DBusIPCMessage &msg, const Type &v) - { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg, IPCTypeRegisterHandler::convertToSerializedType(v, *this)); - } - - template - void deserializeValue(DBusIPCMessage &msg, Type &v) - { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); - } - - template - bool deserializeOptionalValue(DBusIPCMessage &msg, Type &value, bool isCompleteSnapshot) - { - bool b = true; - if (!isCompleteSnapshot) { - msg.inputPayLoad().readNextParameter(b); - } - if (b) { - this->deserializeValue(msg, value); - } - return b; - } - - bool deserializeReadyValue(DBusIPCMessage &msg, bool isCompleteSnapshot) - { - bool previousIsReady = this->ready(); - deserializeOptionalValue(msg, this->m_serviceReady, isCompleteSnapshot); - return (this->ready() != previousIsReady); - } - void setServiceRegistered(bool isRegistered) override { bool oldReady = this->ready(); @@ -141,11 +107,30 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa m_ipcBinder.connectToServer(); } + template + T castArgument(const QVariant& value) { + return castArgumentPrivate(type(), value); + } + + template + T castDBusVariantArgument(const QVariant& value) { + return qdbus_cast(value); + } + protected: bool m_serviceRegistered = false; private: DBusIPCProxyBinder m_ipcBinder; + template + T castArgumentPrivate(type, const QVariant& value) { + return qdbus_cast(value); + } + + QList castArgumentPrivate(type>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + }; } // end namespace dbus diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 636fbb0b..8b2d6bac 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -60,25 +60,18 @@ void DBusIPCProxyBinder::setInterfaceName(const QString &name) checkInit(); } -void DBusIPCProxyBinder::onServerNotAvailableError(const char *methodName) const +void DBusIPCProxyBinder::onServerNotAvailableError(const QString &propertyName) const { qCCritical(LogIpc, "Error message received when calling method '%s' on service at path '%s'. " "This likely indicates that the server you are trying to access is not available yet", - qPrintable(methodName), qPrintable(objectPath())); + qPrintable(propertyName), qPrintable(objectPath())); } void DBusIPCProxyBinder::onPropertiesChanged(const QDBusMessage &dbusMessage) { DBusIPCMessage msg(dbusMessage); - m_serviceObject->deserializePropertyValues(msg, false); -} - -void DBusIPCProxyBinder::onSignalTriggered(const QDBusMessage &dbusMessage) -{ - DBusIPCMessage msg(dbusMessage); - m_serviceObject->deserializePropertyValues(msg, false); - m_serviceObject->deserializeSignal(msg); + m_serviceObject->unmarshalPropertiesChanged(msg); } void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) @@ -90,11 +83,11 @@ void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) void DBusIPCProxyBinder::requestPropertyValues() { - DBusIPCMessage msg(serviceName(), objectPath(), interfaceName(), DBusIPCCommon::GET_PROPERTIES_MESSAGE_NAME); - + DBusIPCMessage msg(serviceName(), objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::GET_ALL_PROPERTIES); + msg << QVariant::fromValue(interfaceName()); auto replyHandler = [this](DBusIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->deserializePropertyValues(replyMessage, true); + m_serviceObject->unmarshalPropertyValues(replyMessage); m_serviceObject->setServiceRegistered(true); } else { qCDebug(LogIpc) << "Service not yet available : " << objectPath(); @@ -115,16 +108,16 @@ void DBusIPCProxyBinder::onServiceNameKnown() auto& connection = m_dbusManager.connection(); auto successPropertyChangeSignal = connection.connect(m_serviceName, - objectPath(), m_interfaceName, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, + objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); Q_UNUSED(successPropertyChangeSignal); // TODO: check - auto successSignalTriggeredSignal = connection.connect(m_serviceName, - objectPath(), m_interfaceName, DBusIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME, this, - SLOT(onSignalTriggered(const QDBusMessage&))); - - Q_UNUSED(successSignalTriggeredSignal); // TODO: check + for (const QString& signalEntry: m_serviceObject->getSignals()) { + auto signalConnected = connection.connect(m_serviceName, + objectPath(), m_interfaceName, signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); + Q_UNUSED(successPropertyChangeSignal); // TODO: check + } m_busWatcher.addWatchedService(m_serviceName); m_busWatcher.setConnection(connection); @@ -155,12 +148,13 @@ void DBusIPCProxyBinder::checkRegistry() auto& connection = m_dbusManager.connection(); connection.disconnect(m_serviceName, - objectPath(), m_interfaceName, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, + objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); - connection.disconnect(m_serviceName, - objectPath(), m_interfaceName, DBusIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME, this, - SLOT(onSignalTriggered(const QDBusMessage&))); + for (const QString& signalEntry: m_serviceObject->getSignals()) { + connection.disconnect(m_serviceName, + objectPath(), interfaceName(), signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); + } setServiceAvailable(false); m_serviceName.clear(); @@ -168,6 +162,12 @@ void DBusIPCProxyBinder::checkRegistry() } } +void DBusIPCProxyBinder::handleGenericSignals(const QDBusMessage& msg) +{ + DBusIPCMessage dbusMsg(msg); + m_serviceObject->handleSignals(dbusMsg); +} + void DBusIPCProxyBinder::asyncCall(DBusIPCMessage &message, const QObject *context, std::function callback) { auto& connection = m_dbusManager.connection(); diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index ddbe67ef..9514595c 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -36,10 +36,12 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif +#include #include #include "IPCProxyBinderBase.h" #include "DBusIPCMessage.h" -#include "ipc-serialization.h" +#include "FaceliftUtils.h" +#include "DBusIPCCommon.h" #include "DBusManagerInterface.h" class QDBusMessage; @@ -72,7 +74,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase Q_SLOT void onPropertiesChanged(const QDBusMessage &dbusMessage); - Q_SLOT void onSignalTriggered(const QDBusMessage &dbusMessage); + Q_SLOT void handleGenericSignals(const QDBusMessage &msg); void bindToIPC() override; @@ -91,16 +93,10 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void asyncCall(DBusIPCMessage &message, const QObject *context, std::function callback); - template - void serializeValue(DBusIPCMessage &msg, const Type &v); - - template - void deserializeValue(DBusIPCMessage &msg, Type &v); - - void onServerNotAvailableError(const char *methodName) const; + void onServerNotAvailableError(const QString &propertyName) const; template - void sendSetterCall(const char *methodName, const PropertyType &value); + void sendSetterCall(const QString& property, const PropertyType &value); template DBusIPCMessage sendMethodCall(const char *methodName, const Args & ... args) const; @@ -111,8 +107,8 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase template void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args); - template - void sendMethodCallWithReturn(const char *methodName, ReturnType &returnValue, const Args & ... args) const; + template + QList sendMethodCallWithReturn(const char *methodName, const Args & ... args) const; void setHandler(DBusRequestHandler *handler); @@ -127,29 +123,12 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase }; -template -inline void DBusIPCProxyBinder::serializeValue(DBusIPCMessage &msg, const Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg.outputPayLoad(), IPCTypeRegisterHandler::convertToSerializedType(v, *this)); -} - -template -inline void DBusIPCProxyBinder::deserializeValue(DBusIPCMessage &msg, Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); -} - - template inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, const Args & ... args) const { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); auto replyMessage = this->call(msg); if (replyMessage.isErrorMessage()) { onServerNotAvailableError(methodName); @@ -162,11 +141,11 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { - deserializeValue(msg, returnValue); + returnValue = (!msg.arguments().isEmpty() ? qdbus_cast(msg.arguments()[0]): ReturnType()); answer(returnValue); } else { qCWarning(LogIpc) << "Error received" << msg.toString(); @@ -179,39 +158,40 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); asyncCall(msg, this, [answer](DBusIPCMessage &msg) { Q_UNUSED(msg); answer(); }); } -template -inline void DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, ReturnType &returnValue, const Args & ... args) const +template +inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, const Args & ... args) const { DBusIPCMessage msg = sendMethodCall(methodName, args ...); + QList ret; if (msg.isReplyMessage()) { - const_cast(this)->deserializeValue(msg, returnValue); - } else { - assignDefaultValue(returnValue); + ret = msg.arguments(); } + return ret; } - template -inline void DBusIPCProxyBinder::sendSetterCall(const char *methodName, const PropertyType &value) +inline void DBusIPCProxyBinder::sendSetterCall(const QString &property, const PropertyType &value) { - DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); - serializeValue(msg, value); + DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY); + msg << QVariant::fromValue(m_interfaceName); + msg << QVariant::fromValue(property); + msg << QVariant::fromValue(QDBusVariant(QVariant::fromValue(value))); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { - onServerNotAvailableError(methodName); + onServerNotAvailableError(property); } } else { - asyncCall(msg, this, [this, methodName](const DBusIPCMessage &replyMessage) { + asyncCall(msg, this, [this, property](const DBusIPCMessage &replyMessage) { if (replyMessage.isErrorMessage()) { - onServerNotAvailableError(methodName); + onServerNotAvailableError(property); } }); } diff --git a/src/ipc/dbus/DBusManager.cpp b/src/ipc/dbus/DBusManager.cpp index 2a8189a1..2f6dcb77 100644 --- a/src/ipc/dbus/DBusManager.cpp +++ b/src/ipc/dbus/DBusManager.cpp @@ -44,6 +44,14 @@ DBusManager::DBusManager() : m_busConnection(QDBusConnection::sessionBus()) DBusManager &DBusManager::instance() { + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + qDBusRegisterMetaType>(); + static auto i = new DBusManager(); // TODO solve memory leak return *i; } diff --git a/src/ipc/dbus/DBusObjectRegistry.cpp b/src/ipc/dbus/DBusObjectRegistry.cpp index d91a4ccc..d07c490f 100644 --- a/src/ipc/dbus/DBusObjectRegistry.cpp +++ b/src/ipc/dbus/DBusObjectRegistry.cpp @@ -122,7 +122,7 @@ void DBusObjectRegistry::syncObjects() ObjectRegistryIPCDBusProxy objectRegistryProxy; objectRegistryProxy.ipc()->setServiceName(m_serviceName); objectRegistryProxy.connectToServer(); - Q_ASSERT(objectRegistryProxy.ready()); + // Q_ASSERT(objectRegistryProxy.ready()); updateObjects(objectRegistryProxy.getObjects()); } diff --git a/src/ipc/dbus/DBusRequestHandler.h b/src/ipc/dbus/DBusRequestHandler.h index 8a57f669..c37eebd4 100644 --- a/src/ipc/dbus/DBusRequestHandler.h +++ b/src/ipc/dbus/DBusRequestHandler.h @@ -45,8 +45,10 @@ class FaceliftIPCLibDBus_EXPORT DBusRequestHandler { public: - virtual void deserializePropertyValues(DBusIPCMessage &msg, bool isCompleteSnapshot) = 0; - virtual void deserializeSignal(DBusIPCMessage &msg) = 0; + virtual void unmarshalPropertyValues(DBusIPCMessage &msg) = 0; + virtual void unmarshalPropertiesChanged(DBusIPCMessage &msg) = 0; + virtual void handleSignals(DBusIPCMessage& msg) = 0; + virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; }; diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index 9d6eaf7f..c74bc6e4 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -58,6 +58,7 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase typedef ServiceType TheServiceType; using InputIPCMessage = ::facelift::dbus::DBusIPCMessage; using OutputIPCMessage = ::facelift::dbus::DBusIPCMessage; + template struct type { }; IPCDBusServiceAdapter(DBusManagerInterface& dbusManager, QObject *parent) : IPCDBusServiceAdapterBase(dbusManager, parent) @@ -91,8 +92,36 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase registerService(objectPath, static_cast(serverObject)); } + template + T castArgument(const QVariant& value) { + return castArgumentPrivate(type(), value); + } + + template + T castDBusVariantArgument(const QVariant& value) { + return castDBusVariantArgumentPrivate(type(), value); + } + protected: QPointer m_service; + + template + T castArgumentPrivate(type, const QVariant& value) { + return qdbus_cast(value); + } + + QList castArgumentPrivate(type>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + + template + T castDBusVariantArgumentPrivate(type, const QVariant& value) { + return qvariant_cast(qdbus_cast(value).variant()); + } + + QList castDBusVariantArgumentPrivate(type>, const QVariant& value) { + return qvariant_cast(qdbus_cast(value).variant()); + } }; } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp index bd3e21ed..616dffb5 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp @@ -57,29 +57,6 @@ namespace facelift { namespace dbus { -constexpr const char *DBusIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME; - -void IPCDBusServiceAdapterBase::initOutgoingSignalMessage() { - m_pendingOutgoingMessage = std::make_unique(objectPath(), interfaceName(), DBusIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME); - - // Send property value updates before the signal itself so that they are set before the signal is triggered on the client side. - this->serializePropertyValues(*m_pendingOutgoingMessage, false); -} - -void IPCDBusServiceAdapterBase::serializePropertyValues(DBusIPCMessage &msg, bool isCompleteSnapshot) -{ - Q_ASSERT(service()); - serializeOptionalValue(msg, service()->ready(), m_previousReadyState, isCompleteSnapshot); -} - -void IPCDBusServiceAdapterBase::flush() -{ - if (m_pendingOutgoingMessage) { - this->send(*m_pendingOutgoingMessage); - m_pendingOutgoingMessage.reset(); - } -} - bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) { DBusIPCMessage requestMessage(dbusMsg); @@ -89,29 +66,33 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) qCDebug(LogIpc) << "Handling incoming message: " << requestMessage.toString(); if (dbusMsg.interface() == DBusIPCCommon::INTROSPECTABLE_INTERFACE_NAME) { - // TODO + // is handled via the QDBusVirtualObject } else if (dbusMsg.interface() == DBusIPCCommon::PROPERTIES_INTERFACE_NAME) { - // TODO - } else { + if (!m_signalsConnected) { + m_signalsConnected = true; + qCDebug(LogIpc) << "Enabling IPCDBusServiceAdapter for" << this->service(); + connectSignals(); + } + if (dbusMsg.member() == DBusIPCCommon::GET_ALL_PROPERTIES) { + marshalPropertyValues(dbusMsg.arguments(), replyMessage); + send(replyMessage); + } + else if (dbusMsg.member() == DBusIPCCommon::GET_PROPERTY) { + marshalProperty(dbusMsg.arguments(), replyMessage); + send(replyMessage); + } + else if (dbusMsg.member() == DBusIPCCommon::SET_PROPERTY) { + setProperty(dbusMsg.arguments()); + send(replyMessage); + } + } else if (dbusMsg.interface() == interfaceName()) { if (service()) { bool sendReply = true; - if (requestMessage.member() == DBusIPCCommon::GET_PROPERTIES_MESSAGE_NAME) { - if (!m_signalsConnected) { - m_signalsConnected = true; - QObject::connect(service(), &InterfaceBase::readyChanged, this, [this]() { - this->sendSignal(CommonSignalID::readyChanged); - }); - qCDebug(LogIpc) << "Enabling IPCDBusServiceAdapter for" << this->service(); - connectSignals(); - } - serializePropertyValues(replyMessage, true); - } else { - auto handlingResult = handleMethodCallMessage(requestMessage, replyMessage); - if (handlingResult == IPCHandlingResult::INVALID) { - replyMessage = requestMessage.createErrorReply("Invalid arguments", "TODO"); - } else if (handlingResult == IPCHandlingResult::OK_ASYNC) { - sendReply = false; - } + auto handlingResult = handleMethodCallMessage(requestMessage, replyMessage); + if (handlingResult == IPCHandlingResult::INVALID) { + replyMessage = requestMessage.createErrorReply("Invalid arguments", "TODO"); + } else if (handlingResult == IPCHandlingResult::OK_ASYNC) { + sendReply = false; } if (sendReply) { send(replyMessage); diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index f6d2f988..d9d7be69 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -39,8 +39,9 @@ #include #include "IPCServiceAdapterBase.h" #include "DBusIPCMessage.h" +#include "DBusIPCCommon.h" #include "ipc-common.h" -#include "ipc-serialization.h" +#include "FaceliftUtils.h" #include "DBusManagerInterface.h" namespace facelift { @@ -87,18 +88,12 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool handleMessage(const QDBusMessage &dbusMsg); - void flush(); - template - void serializeValue(DBusIPCMessage &msg, const Type &v); - - template - void deserializeValue(DBusIPCMessage &msg, Type &v); + template + inline void sendPropertiesChanged(const QString& property , const Value & value); - void initOutgoingSignalMessage(); - - template - void sendSignal(MemberID signalID, const Args & ... args); + template + void sendSignal(const QString& signalName, const Args & ... args); template void sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue); @@ -109,17 +104,15 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda virtual IPCHandlingResult handleMethodCallMessage(DBusIPCMessage &requestMessage, DBusIPCMessage &replyMessage) = 0; - virtual void serializePropertyValues(DBusIPCMessage &msg, bool isCompleteSnapshot); + virtual void marshalPropertyValues(const QList& arguments, DBusIPCMessage &msg) = 0; - void registerService() override; + virtual void marshalProperty(const QList& arguments, DBusIPCMessage &msg) = 0; - void unregisterService() override; + virtual void setProperty(const QList& arguments) = 0; - template - void serializeOptionalValue(DBusIPCMessage &msg, const Type ¤tValue, Type &previousValue, bool isCompleteSnapshot); + void registerService() override; - template - void serializeOptionalValue(DBusIPCMessage &msg, const Type ¤tValue, bool isCompleteSnapshot); + void unregisterService() override; virtual void appendDBUSIntrospectionData(QTextStream &s) const = 0; @@ -134,7 +127,6 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } protected: - std::unique_ptr m_pendingOutgoingMessage; DBusVirtualObject m_dbusVirtualObject; QString m_introspectionData; @@ -147,64 +139,39 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda DBusManagerInterface& m_dbusManager; }; -template -inline void IPCDBusServiceAdapterBase::serializeValue(DBusIPCMessage &msg, const Type &v) +template +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& property, const Value &value) { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg.outputPayLoad(), IPCTypeRegisterHandler::convertToSerializedType(v, *this)); + DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); + reply << interfaceName(); + reply << QVariantMap{{property, QVariant::fromValue(value)}}; + this->send(reply); } -template -inline void IPCDBusServiceAdapterBase::deserializeValue(DBusIPCMessage &msg, Type &v) +template<> +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& property, const QList &value) { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); + DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); + reply << interfaceName(); + reply << QVariantMap{{property, QVariant::fromValue(QStringList(value))}}; + this->send(reply); } -template -inline void IPCDBusServiceAdapterBase::sendSignal(MemberID signalID, const Args & ... args) +template +inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, const Args & ... args) { - if (m_pendingOutgoingMessage == nullptr) { - initOutgoingSignalMessage(); - auto argTuple = std::make_tuple(signalID, args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(m_pendingOutgoingMessage->outputPayLoad(), *this)); - flush(); - } + DBusIPCMessage signal(objectPath(), interfaceName(), signalName); + auto argTuple = std::make_tuple(args ...); + for_each_in_tuple(argTuple, [this, &signal](const auto &v){signal << QVariant::fromValue(v);}); + this->send(signal); } template inline void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue) { - serializeValue(replyMessage, returnValue); + replyMessage << QVariant::fromValue(returnValue); send(replyMessage); } -template -inline void IPCDBusServiceAdapterBase::serializeOptionalValue(DBusIPCMessage &msg, const Type ¤tValue, Type &previousValue, bool isCompleteSnapshot) -{ - if (isCompleteSnapshot) { - serializeValue(msg, currentValue); - } else { - if (previousValue == currentValue) { - msg.outputPayLoad().writeSimple(false); - } else { - msg.outputPayLoad().writeSimple(true); - serializeValue(msg, currentValue); - previousValue = currentValue; - } - } -} - -template -inline void IPCDBusServiceAdapterBase::serializeOptionalValue(DBusIPCMessage &msg, const Type ¤tValue, bool isCompleteSnapshot) -{ - msg.outputPayLoad().writeSimple(isCompleteSnapshot); - if (isCompleteSnapshot) { - serializeValue(msg, currentValue); - } -} - } // end namespace dbus } // end namespace facelift diff --git a/src/ipc/ipc-common/AppendDBUSSignatureFunction.h b/src/ipc/ipc-common/AppendDBUSSignatureFunction.h deleted file mode 100644 index c24408df..00000000 --- a/src/ipc/ipc-common/AppendDBUSSignatureFunction.h +++ /dev/null @@ -1,68 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - - -#include - -#include - -#include "FaceliftUtils.h" - -namespace facelift { - -struct FaceliftIPCCommonLib_EXPORT AppendDBUSSignatureFunction -{ - AppendDBUSSignatureFunction(QTextStream &s) : - s(s) - { - } - - QTextStream &s; - - template - void operator()(T &&t) - { - Q_UNUSED(t); - typedef typename std::decay::type TupleType; - std::tuple dummyTuple; - appendDBUSTypeSignature(s, dummyTuple); - } -}; - - -} diff --git a/src/ipc/ipc-common/CMakeLists.txt b/src/ipc/ipc-common/CMakeLists.txt index e85b58a6..0a8287e7 100644 --- a/src/ipc/ipc-common/CMakeLists.txt +++ b/src/ipc/ipc-common/CMakeLists.txt @@ -2,9 +2,7 @@ facelift_add_library(FaceliftIPCCommonLib SOURCES ipc-common.cpp - IPCProxyBaseBase.cpp ModuleIPCBase.cpp - ipc-serialization.cpp IPCServiceAdapterBase.cpp NotAvailableImplBase.cpp IPCAdapterFactoryManager.cpp @@ -13,8 +11,6 @@ facelift_add_library(FaceliftIPCCommonLib InterfaceManager.cpp IPCProxyNewBase.cpp NewIPCServiceAdapterBase.cpp - OutputPayLoad.cpp - InputPayLoad.cpp LocalProviderBinderBase.cpp HEADERS ipc-common.h @@ -24,10 +20,8 @@ facelift_add_library(FaceliftIPCCommonLib LocalProviderBinder.h LocalProviderBinderBase.h StaticArrayReference.h - IPCProxyBaseBase.h IPCProxyBase.h IPCProxy.h - IPCTypeHandler.h InterfaceManager.h InterfaceManagerInterface.h IPCProxyModelProperty.h @@ -36,17 +30,10 @@ facelift_add_library(FaceliftIPCCommonLib IPCServiceAdapterBase.h NewIPCServiceAdapterBase.h ModuleIPCBase.h - ipc-serialization.h IPCAdapterFactoryManager.h IPCAttachedPropertyFactory.h IPCServiceAdapter.h Registry.h - InputPayLoad.h - OutputPayLoad.h - DBusSignatureHelper.h - IPCTypeRegisterHandler.h - AppendDBUSSignatureFunction.h - SerializeParameterFunction.h LINK_LIBRARIES FaceliftModelLib FaceliftCommonLib MONOLITHIC_SUPPORTED ) diff --git a/src/ipc/ipc-common/DBusSignatureHelper.h b/src/ipc/ipc-common/DBusSignatureHelper.h deleted file mode 100644 index 7fa042dc..00000000 --- a/src/ipc/ipc-common/DBusSignatureHelper.h +++ /dev/null @@ -1,141 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include "IPCTypeHandler.h" -#include - -namespace facelift { - -class FaceliftIPCCommonLib_EXPORT DBusSignatureHelper { - - public: - - template - typename std::enable_if::type - static appendDBUSMethodArgumentsSignature(QTextStream &s, std::tuple &t, const std::array &argNames) - { - Q_UNUSED(s); - Q_UNUSED(t); - Q_UNUSED(argNames); - } - - template - typename std::enable_if < I::type - static appendDBUSMethodArgumentsSignature(QTextStream &s, std::tuple &t, const std::array &argNames) - { - using Type = decltype(std::get(t)); - s << "::writeDBUSSignature(s); - s << "\" direction=\"in\"/>"; - appendDBUSMethodArgumentsSignature(s, t, argNames); - } - - - template - typename std::enable_if::type - static appendDBUSSignalArgumentsSignature(QTextStream &s, std::tuple &t, const std::array &argNames) - { - Q_UNUSED(s); - Q_UNUSED(t); - Q_UNUSED(argNames); - } - - template - typename std::enable_if < I::type - static appendDBUSSignalArgumentsSignature(QTextStream &s, std::tuple &t, const std::array &argNames) - { - using Type = decltype(std::get(t)); - s << "::writeDBUSSignature(s); - s << "\"/>"; - appendDBUSSignalArgumentsSignature(s, t, argNames); - } - - template - typename std::enable_if::type - static appendDBUSTypeSignature(QTextStream &s, std::tuple &t) - { - Q_UNUSED(s); - Q_UNUSED(t); - } - - template - typename std::enable_if < I::type - static appendDBUSTypeSignature(QTextStream &s, std::tuple &t) - { - using Type = decltype(std::get(t)); - IPCTypeHandler::writeDBUSSignature(s); - appendDBUSTypeSignature(s, t); - } - - template - static void addPropertySignature(QTextStream &s, const char *propertyName, bool isReadonly) - { - s << " dummyTuple; - appendDBUSTypeSignature(s, dummyTuple); - s << "\" access=\"" << (isReadonly ? "read" : "readwrite") << "\"/>"; - } - - template - static void addMethodSignature(QTextStream &s, const char *methodName, - const std::array &argNames) - { - s << ""; - std::tuple t; // TODO : get rid of the tuple - appendDBUSMethodArgumentsSignature(s, t, argNames); - s << ""; - } - - template - static void addSignalSignature(QTextStream &s, const char *methodName, - const std::array &argNames) - { - s << ""; - std::tuple t; // TODO : get rid of the tuple - appendDBUSSignalArgumentsSignature(s, t, argNames); - s << ""; - } - -}; - -} diff --git a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h index 72481e98..bae9eca0 100644 --- a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h +++ b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h @@ -30,6 +30,7 @@ #pragma once #include +#include #include "ipc-common.h" #if defined(FaceliftIPCCommonLib_LIBRARY) @@ -50,26 +51,25 @@ class IPCAdapterModelPropertyHandler { } - template - void connectModel(SignalID signalID, facelift::Model &model) + void connectModel(const QString& modelPropertyName, facelift::Model &model) { m_model = &model; QObject::connect(m_model, static_cast - (&facelift::ModelBase::dataChanged), &m_adapter, [this, signalID] (int first, int last) { + (&facelift::ModelBase::dataChanged), &m_adapter, [this, modelPropertyName] (int first, int last) { QList changedItems; for (int i = first ; i <= last ; i++) { changedItems.append(m_model->elementAt(i)); } - m_adapter.sendSignal(signalID, ModelUpdateEvent::DataChanged, first, changedItems); + m_adapter.sendSignal("ModelUpdateEventDataChanged", modelPropertyName, first, changedItems); }); QObject::connect(m_model, &facelift::ModelBase::beginRemoveElements, &m_adapter, [this] (int first, int last) { m_removeFirst = first; m_removeLast = last; }); - QObject::connect(m_model, &facelift::ModelBase::endRemoveElements, &m_adapter, [this, signalID] () { + QObject::connect(m_model, &facelift::ModelBase::endRemoveElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_removeFirst != UNDEFINED); Q_ASSERT(m_removeLast != UNDEFINED); - m_adapter.sendSignal(signalID, ModelUpdateEvent::Remove, m_removeFirst, m_removeLast); + m_adapter.sendSignal("ModelUpdateEventRemove", modelPropertyName, m_removeFirst, m_removeLast); m_removeFirst = UNDEFINED; m_removeLast = UNDEFINED; }); @@ -78,44 +78,42 @@ class IPCAdapterModelPropertyHandler m_moveSourceLastIndex = sourceLastIndex; m_moveDestinationIndex = destinationIndex; }); - QObject::connect(m_model, &facelift::ModelBase::endMoveElements, &m_adapter, [this, signalID] () { + QObject::connect(m_model, &facelift::ModelBase::endMoveElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_moveSourceFirstIndex != UNDEFINED); Q_ASSERT(m_moveSourceLastIndex != UNDEFINED); Q_ASSERT(m_moveDestinationIndex != UNDEFINED); - m_adapter.sendSignal(signalID, ModelUpdateEvent::Move, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); + m_adapter.sendSignal("ModelUpdateEventMove", modelPropertyName, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); m_moveSourceFirstIndex = UNDEFINED; m_moveSourceLastIndex = UNDEFINED; m_moveDestinationIndex = UNDEFINED; }); - QObject::connect(m_model, &facelift::ModelBase::beginInsertElements, &m_adapter, [this] (int first, int last) { + QObject::connect(m_model, &facelift::ModelBase::beginInsertElements, &m_adapter, [this, modelPropertyName] (int first, int last) { m_insertFirst = first; m_insertLast = last; }); - QObject::connect(m_model, &facelift::ModelBase::endInsertElements, &m_adapter, [this, signalID] () { + QObject::connect(m_model, &facelift::ModelBase::endInsertElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_insertFirst != UNDEFINED); Q_ASSERT(m_insertLast != UNDEFINED); - m_adapter.sendSignal(signalID, ModelUpdateEvent::Insert, m_insertFirst, m_insertLast); + m_adapter.sendSignal("ModelUpdateEventInsert", modelPropertyName, m_insertFirst, m_insertLast); m_insertFirst = UNDEFINED; m_insertLast = UNDEFINED; }); - QObject::connect(m_model, &facelift::ModelBase::beginResetModel, &m_adapter, [this] () { + QObject::connect(m_model, &facelift::ModelBase::beginResetModel, &m_adapter, [this, modelPropertyName] () { m_resettingModel = true; }); - QObject::connect(m_model, &facelift::ModelBase::endResetModel, &m_adapter, [this, signalID] () { + QObject::connect(m_model, &facelift::ModelBase::endResetModel, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_resettingModel); - m_adapter.sendSignal(signalID, ModelUpdateEvent::Reset, m_model->size()); + m_adapter.sendSignal("ModelUpdateEventReset", modelPropertyName, m_model->size()); m_resettingModel = false; }); } void handleModelRequest(typename IPCAdapterType::InputIPCMessage &requestMessage, typename IPCAdapterType::OutputIPCMessage &replyMessage) { - std::tuple> requestResult; - int & first = std::get<0>(requestResult); - auto & list = std::get<1>(requestResult); - int last; - m_adapter.deserializeValue(requestMessage, first); - m_adapter.deserializeValue(requestMessage, last); + QListIterator argumentsIterator(requestMessage.arguments()); + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + QList list; // Make sure we do not request items which are out of range first = qMax(first, 0); @@ -125,7 +123,8 @@ class IPCAdapterModelPropertyHandler list.append(m_model->elementAt(i)); } - m_adapter.serializeValue(replyMessage, requestResult); + replyMessage << QVariant::fromValue(first); + replyMessage << QVariant::fromValue(list); } private: diff --git a/src/ipc/ipc-common/IPCProxyBase.h b/src/ipc/ipc-common/IPCProxyBase.h index 25701b8d..1903a109 100644 --- a/src/ipc/ipc-common/IPCProxyBase.h +++ b/src/ipc/ipc-common/IPCProxyBase.h @@ -31,7 +31,6 @@ #pragma once #include "ipc-common.h" -#include "IPCProxyBaseBase.h" #include "IPCProxyBinderBase.h" @@ -44,7 +43,7 @@ namespace facelift { template -class IPCProxyBase : public AdapterType, protected IPCProxyBaseBase +class IPCProxyBase : public AdapterType { public: diff --git a/src/ipc/ipc-common/IPCProxyBaseBase.cpp b/src/ipc/ipc-common/IPCProxyBaseBase.cpp deleted file mode 100644 index b2dbbc9d..00000000 --- a/src/ipc/ipc-common/IPCProxyBaseBase.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, freIPCServiceAdapterBasee of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#include "IPCProxyBase.h" -#include "FaceliftModel.h" - -namespace facelift { - -void IPCProxyBaseBase::deserializeCommonSignal(facelift::CommonSignalID signalID, InterfaceBase* i) -{ - switch (signalID) { - case facelift::CommonSignalID::readyChanged: - emit i->readyChanged(); - break; - default: - qFatal("Unknown signal ID"); - } -} - -} diff --git a/src/ipc/ipc-common/IPCProxyBaseBase.h b/src/ipc/ipc-common/IPCProxyBaseBase.h deleted file mode 100644 index d2f63ab3..00000000 --- a/src/ipc/ipc-common/IPCProxyBaseBase.h +++ /dev/null @@ -1,51 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, freIPCServiceAdapterBasee of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#include "ipc-common.h" - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -namespace facelift { - -class FaceliftIPCCommonLib_EXPORT IPCProxyBaseBase { - -public: - - void deserializeCommonSignal(facelift::CommonSignalID signalID, InterfaceBase* i); - -}; - -} diff --git a/src/ipc/ipc-common/IPCProxyModelProperty.h b/src/ipc/ipc-common/IPCProxyModelProperty.h index 28aa5807..b51ec153 100644 --- a/src/ipc/ipc-common/IPCProxyModelProperty.h +++ b/src/ipc/ipc-common/IPCProxyModelProperty.h @@ -30,6 +30,9 @@ #pragma once #include +#include +#include "FaceliftUtils.h" +#include "ModelProperty.h" #if defined(FaceliftIPCCommonLib_LIBRARY) # define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT @@ -50,66 +53,58 @@ class IPCProxyModelProperty : public facelift::ModelProperty { } - void handleSignal(typename IPCProxyType::InputIPCMessage &msg) + void handleSignal(const typename IPCProxyType::InputIPCMessage &msg) { - ModelUpdateEvent event; - m_proxy.deserializeValue(msg, event); - switch (event) { - - case ModelUpdateEvent::DataChanged: - { - int first; - QList list; - m_proxy.deserializeValue(msg, first); - m_proxy.deserializeValue(msg, list); - int last = first + list.size() - 1; - for (int i = first; i <= last; ++i) { - m_cache.insert(i, list.at(i - first)); - } - emit this->dataChanged(first, last); - } break; - - case ModelUpdateEvent::Insert: - { - int first, last; - m_proxy.deserializeValue(msg, first); - m_proxy.deserializeValue(msg, last); - emit this->beginInsertElements(first, last); - clear(); // TODO: insert elements in cache without clear() - emit this->endInsertElements(); - } break; - - case ModelUpdateEvent::Remove: - { - int first, last; - m_proxy.deserializeValue(msg, first); - m_proxy.deserializeValue(msg, last); - emit this->beginRemoveElements(first, last); - m_cache.clear(); // TODO: remove elements from cache without clear() - emit this->endRemoveElements(); - } break; - - case ModelUpdateEvent::Move: - { - int sourceFirstIndex, sourceLastIndex, destinationIndex; - m_proxy.deserializeValue(msg, sourceFirstIndex); - m_proxy.deserializeValue(msg, sourceLastIndex); - m_proxy.deserializeValue(msg, destinationIndex); - emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); - m_cache.clear(); // TODO: move elements in cache without clear() - emit this->endMoveElements(); - } break; - - case ModelUpdateEvent::Reset: - { - emit this->beginResetModel(); - int size; - m_proxy.deserializeValue(msg, size); - this->setSize(size); - clear(); - emit this->endResetModel(); - } break; + QListIterator argumentsIterator(msg.arguments()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + + if (!modelPropertyName.isEmpty()) { + const QString& eventName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + if (eventName == QStringLiteral("ModelUpdateEventDataChanged")) + { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + + int last = first + list.size() - 1; + for (int i = first; i <= last; ++i) { + m_cache.insert(i, list.at(i - first)); + } + emit this->dataChanged(first, last); + } + else if (eventName == QStringLiteral("ModelUpdateEventInsert")) { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginInsertElements(first, last); + clear(); // TODO: insert elements in cache without clear() + emit this->endInsertElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventRemove")) + { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginRemoveElements(first, last); + m_cache.clear(); // TODO: remove elements from cache without clear() + emit this->endRemoveElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventMove")) { + int sourceFirstIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int sourceLastIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int destinationIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); + m_cache.clear(); // TODO: move elements in cache without clear() + emit this->endMoveElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventReset")) { + emit this->beginResetModel(); + int size = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + this->setSize(size); + clear(); + emit this->endResetModel(); + } + else { + qCWarning(LogIpc) << "Unhandled event for model property" << eventName; + } } } @@ -135,11 +130,10 @@ class IPCProxyModelProperty : public facelift::ModelProperty --last; } - std::tuple> requestResult; - m_proxy.ipc()->sendMethodCallWithReturn(requestMemberID, requestResult, first, last); - - first = std::get<0>(requestResult); - auto &list = std::get<1>(requestResult); + QList args = m_proxy.ipc()->sendMethodCallWithReturn(requestMemberID, first, last); + QListIterator argumentsIterator(args); + first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); last = first + list.size() - 1; for (int i = first; i <= last; ++i) { @@ -187,10 +181,11 @@ class IPCProxyModelProperty : public facelift::ModelProperty } if (first <= last) { - m_proxy.ipc()->sendAsyncMethodCall(requestMemberID, facelift::AsyncAnswer>>(&m_proxy, [this](std::tuple> result) { + m_proxy.ipc()->sendAsyncMethodCall(requestMemberID, facelift::AsyncAnswer>(&m_proxy, [this](QList arguments) { // qCDebug(LogIpc) << "Received model items " << first << "-" << last; - auto & first = std::get<0>(result); - auto & list = std::get<1>(result); + QListIterator argumentsIterator(arguments); + auto first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + auto list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); auto last = first + list.size() - 1; for (int i = first; i <= last; ++i) { auto &newItem = list[i - first]; diff --git a/src/ipc/ipc-common/IPCTypeHandler.h b/src/ipc/ipc-common/IPCTypeHandler.h deleted file mode 100644 index ac1d1169..00000000 --- a/src/ipc/ipc-common/IPCTypeHandler.h +++ /dev/null @@ -1,262 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include "ipc-common.h" -#include "ModelProperty.h" -#include "OutputPayLoad.h" -#include "InputPayLoad.h" -#include "AppendDBUSSignatureFunction.h" - -namespace facelift { - -template -struct IPCTypeHandler -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "i"; - } - - static void write(OutputPayLoad &msg, const Type &v) - { - msg.writeSimple(v); - } - - static void read(InputPayLoad &msg, Type &v) - { - msg.readNextParameter(v); - } - -}; - - -template<> -struct IPCTypeHandler -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "d"; - } - - static void write(OutputPayLoad &msg, const double &v) - { - msg.writeSimple(v); - } - - static void read(InputPayLoad &msg, double &v) - { - double d; - msg.readNextParameter(d); - v = d; - } - -}; - - -template<> -struct IPCTypeHandler -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "b"; - } - - static void write(OutputPayLoad &msg, const bool &v) - { - msg.writeSimple(v); - } - - static void read(InputPayLoad &msg, bool &v) - { - msg.readNextParameter(v); - } - -}; - - -template<> -struct IPCTypeHandler -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "s"; - } - - static void write(OutputPayLoad &msg, const QString &v) - { - msg.writeSimple(v); - } - - static void read(InputPayLoad &msg, QString &v) - { - msg.readNextParameter(v); - } - -}; - -template -struct IPCTypeHandler::value>::type> -{ - - static void writeDBUSSignature(QTextStream &s) - { - typename Type::FieldTupleTypes t; // TODO : get rid of that tuple - s << "("; - for_each_in_tuple(t, AppendDBUSSignatureFunction(s)); - s << ")"; - } - - static void write(OutputPayLoad &msg, const Type ¶m) - { - IPCTypeHandler::write(msg, param.asTuple()); - } - - static void read(InputPayLoad &msg, Type ¶m) - { - IPCTypeHandler::read(msg, param.asTuple()); - } - -}; - - -template -struct IPCTypeHandler> -{ - static void write(OutputPayLoad &msg, const std::tuple ¶m) - { - for_each_in_tuple_const(param, StreamWriteFunction(msg)); - } - - static void read(InputPayLoad &msg, std::tuple ¶m) - { - for_each_in_tuple(param, StreamReadFunction(msg)); - } - -}; - - -template -struct IPCTypeHandler::value>::type> -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "i"; - } - - static void write(OutputPayLoad &msg, const Type ¶m) - { - msg.writeSimple(static_cast(param)); - } - - static void read(InputPayLoad &msg, Type ¶m) - { - int i; - msg.readNextParameter(i); - param = static_cast(i); - } -}; - - -template -struct IPCTypeHandler> -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "a"; - IPCTypeHandler::writeDBUSSignature(s); - } - - static void write(OutputPayLoad &msg, const QList &list) - { - int count = list.size(); - msg.writeSimple(count); - for (const auto &e : list) { - IPCTypeHandler::write(msg, e); - } - } - - static void read(InputPayLoad &msg, QList &list) - { - list.clear(); - int count; - msg.readNextParameter(count); - for (int i = 0; i < count; i++) { - ElementType e; - IPCTypeHandler::read(msg, e); - list.append(e); - } - } - -}; - - -template -struct IPCTypeHandler> -{ - static void writeDBUSSignature(QTextStream &s) - { - s << "a{sv}"; // TODO: is it so? - IPCTypeHandler::writeDBUSSignature(s); - } - - static void write(OutputPayLoad &msg, const QMap &map) - { - int count = map.size(); - msg.writeSimple(count); - for (auto i = map.constBegin(); i != map.constEnd(); ++i) { - IPCTypeHandler::write(msg, i.key()); - IPCTypeHandler::write(msg, i.value()); - } - } - - static void read(InputPayLoad &msg, QMap &map) - { - map.clear(); - int count; - msg.readNextParameter(count); - for (int i = 0; i < count; i++) { - QString key; - ElementType value; - IPCTypeHandler::read(msg, key); - IPCTypeHandler::read(msg, value); - map.insert(key, value); - } - } -}; - -} diff --git a/src/ipc/ipc-common/IPCTypeRegisterHandler.h b/src/ipc/ipc-common/IPCTypeRegisterHandler.h deleted file mode 100644 index 7e5c3162..00000000 --- a/src/ipc/ipc-common/IPCTypeRegisterHandler.h +++ /dev/null @@ -1,149 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include - -#include "FaceliftModel.h" - -namespace facelift { - -template -struct IPCTypeRegisterHandler -{ - typedef Type SerializedType; - - template - static const Type &convertToSerializedType(const Type &v, OwnerType &adapter) - { - Q_UNUSED(adapter); - return v; - } - - template - static void convertToDeserializedType(Type &v, const SerializedType &serializedValue, OwnerType &adapter) - { - Q_UNUSED(adapter); - v = serializedValue; - } - -}; - - -template -struct IPCTypeRegisterHandler > -{ - typedef QList::SerializedType> SerializedType; - - template - static SerializedType convertToSerializedType(const QList &v, OwnerType &adapter) - { - Q_UNUSED(v); - Q_UNUSED(adapter); - SerializedType convertedValue; - for (const auto &e : v) { - convertedValue.append(IPCTypeRegisterHandler::convertToSerializedType(e, adapter)); - } - return convertedValue; - } - - template - static void convertToDeserializedType(QList &v, const SerializedType &serializedValue, OwnerType &adapter) - { - v.clear(); - for (const auto &e : serializedValue) { - Type c; - IPCTypeRegisterHandler::convertToDeserializedType(c, e, adapter); - v.append(c); - } - } - -}; - - -template -struct IPCTypeRegisterHandler > -{ - typedef QMap::SerializedType> SerializedType; - - template - static SerializedType convertToSerializedType(const QMap &v, OwnerType &adapter) - { - SerializedType convertedValue; - for (const auto &key : v.keys()) { - convertedValue.insert(key, IPCTypeRegisterHandler::convertToSerializedType(v[key], adapter)); - } - return convertedValue; - } - - template - static void convertToDeserializedType(QMap &v, const SerializedType &serializedValue, OwnerType &adapter) - { - v.clear(); - for (const auto &key : serializedValue.keys()) { - Type c; - IPCTypeRegisterHandler::convertToDeserializedType(c, serializedValue[key], adapter); - v.insert(key, c); - } - } - -}; - - -template -struct IPCTypeRegisterHandler::value>::type> -{ - typedef QString SerializedType; - - template - static SerializedType convertToSerializedType(Type *const &v, OwnerType &adapter) - { - using IPCAdapterType = typename OwnerType::template IPCAdapterType; - return adapter.template getOrCreateAdapter< IPCAdapterType >(v)->objectPath(); - } - - template - static void convertToDeserializedType(Type * &v, const SerializedType &serializedValue, OwnerType &owner) - { - using IPCProxyType = typename OwnerType::template IPCProxyType; - v = owner.template getOrCreateSubProxy(serializedValue); - } - -}; - -} - diff --git a/src/ipc/ipc-common/InputPayLoad.cpp b/src/ipc/ipc-common/InputPayLoad.cpp deleted file mode 100644 index eb13413c..00000000 --- a/src/ipc/ipc-common/InputPayLoad.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ -#include "InputPayLoad.h" - -namespace facelift { - -InputPayLoad::InputPayLoad(const QByteArray &payloadArray) : - m_payloadArray(payloadArray), - m_dataStream(m_payloadArray) -{ -} - -InputPayLoad::~InputPayLoad() = default; - - -} diff --git a/src/ipc/ipc-common/InputPayLoad.h b/src/ipc/ipc-common/InputPayLoad.h deleted file mode 100644 index 56c637ce..00000000 --- a/src/ipc/ipc-common/InputPayLoad.h +++ /dev/null @@ -1,69 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include -#include - -namespace facelift { - -class FaceliftIPCCommonLib_EXPORT InputPayLoad -{ - -public: - InputPayLoad(const QByteArray &payloadArray); - - ~InputPayLoad(); - - template - void readNextParameter(Type &v) - { - m_dataStream >> v; - // qCDebug(LogIpc) << "Read from message : " << v; - } - - const QByteArray &getContent() const - { - return m_payloadArray; - } - -private: - const QByteArray& m_payloadArray; - QDataStream m_dataStream; -}; - -} - diff --git a/src/ipc/ipc-common/OutputPayLoad.cpp b/src/ipc/ipc-common/OutputPayLoad.cpp deleted file mode 100644 index f9930d71..00000000 --- a/src/ipc/ipc-common/OutputPayLoad.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ -#include "OutputPayLoad.h" - -namespace facelift { - -OutputPayLoad::OutputPayLoad(QByteArray &payloadArray) : m_payloadArray(payloadArray), m_dataStream(&m_payloadArray, QIODevice::WriteOnly) -{ -} - - -} diff --git a/src/ipc/ipc-common/OutputPayLoad.h b/src/ipc/ipc-common/OutputPayLoad.h deleted file mode 100644 index 436aca87..00000000 --- a/src/ipc/ipc-common/OutputPayLoad.h +++ /dev/null @@ -1,69 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ -#pragma once - -#include -#include - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -namespace facelift { - -class FaceliftIPCCommonLib_EXPORT OutputPayLoad -{ - -public: - OutputPayLoad(QByteArray &payloadArray); - - template - void writeSimple(const Type &v) - { - // qCDebug(LogIpc) << "Writing to message : " << v; - m_dataStream << v; - } - - const QByteArray &getContent() const - { - return m_payloadArray; - } - - -private: - QByteArray& m_payloadArray; - QDataStream m_dataStream; -}; - -} - - diff --git a/src/ipc/ipc-common/SerializeParameterFunction.h b/src/ipc/ipc-common/SerializeParameterFunction.h deleted file mode 100644 index 89a9c757..00000000 --- a/src/ipc/ipc-common/SerializeParameterFunction.h +++ /dev/null @@ -1,67 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include - -#include "OutputPayLoad.h" -#include "IPCTypeHandler.h" -#include "IPCTypeRegisterHandler.h" - -namespace facelift { - -template -struct SerializeParameterFunction -{ - SerializeParameterFunction(OutputPayLoad &msg, const ParentType &parent) : - m_msg(msg), - m_parent(parent) - { - } - - OutputPayLoad &m_msg; - const ParentType &m_parent; - - template - void operator()(const Type &v) - { - IPCTypeHandler::SerializedType>::write(m_msg, - IPCTypeRegisterHandler::convertToSerializedType(v, m_parent)); - } -}; - -} diff --git a/src/ipc/ipc-common/ipc-common.h b/src/ipc/ipc-common/ipc-common.h index 81878ff4..809fed4e 100644 --- a/src/ipc/ipc-common/ipc-common.h +++ b/src/ipc/ipc-common/ipc-common.h @@ -39,20 +39,11 @@ #include #include "FaceliftModel.h" -#include "InputPayLoad.h" -#include "OutputPayLoad.h" -#include "DBusSignatureHelper.h" -#include "IPCTypeRegisterHandler.h" namespace facelift { FaceliftIPCCommonLib_EXPORT Q_DECLARE_LOGGING_CATEGORY(LogIpc) -enum class CommonSignalID { - readyChanged, - firstSpecific -}; - typedef int ASyncRequestID; enum class IPCHandlingResult { @@ -61,20 +52,5 @@ enum class IPCHandlingResult { INVALID, // Message is invalid and could not be handled }; -enum class ModelUpdateEvent { - DataChanged, - Insert, - Remove, - Move, - Reset -}; - -template -inline void assignDefaultValue(Type &v) -{ - v = Type {}; -} - - } diff --git a/src/ipc/ipc-common/ipc-serialization.cpp b/src/ipc/ipc-common/ipc-serialization.cpp deleted file mode 100644 index 8a42c4c4..00000000 --- a/src/ipc/ipc-common/ipc-serialization.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2019 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#include "ipc-serialization.h" diff --git a/src/ipc/ipc-common/ipc-serialization.h b/src/ipc/ipc-common/ipc-serialization.h deleted file mode 100644 index 62c269e2..00000000 --- a/src/ipc/ipc-common/ipc-serialization.h +++ /dev/null @@ -1,78 +0,0 @@ -/********************************************************************** -** -** Copyright (C) 2020 Luxoft Sweden AB -** -** This file is part of the FaceLift project -** -** Permission is hereby granted, free of charge, to any person -** obtaining a copy of this software and associated documentation files -** (the "Software"), to deal in the Software without restriction, -** including without limitation the rights to use, copy, modify, merge, -** publish, distribute, sublicense, and/or sell copies of the Software, -** and to permit persons to whom the Software is furnished to do so, -** subject to the following conditions: -** -** The above copyright notice and this permission notice shall be -** included in all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -** SOFTWARE. -** -** SPDX-License-Identifier: MIT -** -**********************************************************************/ - -#pragma once - -#if defined(FaceliftIPCCommonLib_LIBRARY) -# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT -#else -# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT -#endif - -#include - -#include "ipc-common.h" -#include "InputPayLoad.h" -#include "OutputPayLoad.h" -#include "Structure.h" -#include "FaceliftUtils.h" -#include "ModelProperty.h" -#include "IPCTypeHandler.h" -#include "SerializeParameterFunction.h" - -namespace facelift { - -template -OutputPayLoad &operator<<(OutputPayLoad &msg, const Type &v) -{ - IPCTypeHandler::write(msg, v); - return msg; -} - - -template -InputPayLoad &operator>>(InputPayLoad &msg, Type &v) -{ - IPCTypeHandler::read(msg, v); - return msg; -} - - -template -InputPayLoad &operator>>(InputPayLoad &msg, Property &property) -{ - Type v; - IPCTypeHandler::read(msg, v); - property.setValue(v); - return msg; -} - - -} diff --git a/src/ipc/local/FaceliftIPCCommon.h b/src/ipc/local/FaceliftIPCCommon.h index 8942adc1..9c121c28 100644 --- a/src/ipc/local/FaceliftIPCCommon.h +++ b/src/ipc/local/FaceliftIPCCommon.h @@ -42,14 +42,13 @@ namespace local { struct FaceliftIPCLocalLib_EXPORT FaceliftIPCCommon { - static constexpr const char *GET_PROPERTIES_MESSAGE_NAME = "GetAllProperties"; + static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; + static constexpr const char *GET_PROPERTY = "Get"; + static constexpr const char *SET_PROPERTY = "Set"; static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *SIGNAL_TRIGGERED_SIGNAL_NAME = "SignalTriggered"; - static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "SetProperty"; + static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; }; -constexpr const char *FaceliftIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME; - } } diff --git a/src/ipc/local/LocalIPC-serialization.h b/src/ipc/local/LocalIPC-serialization.h index fdd626d7..c28a3b85 100644 --- a/src/ipc/local/LocalIPC-serialization.h +++ b/src/ipc/local/LocalIPC-serialization.h @@ -36,56 +36,22 @@ # define FaceliftIPCLocalLib_EXPORT Q_DECL_IMPORT #endif +#include #include "LocalIPCMessage.h" -#include "ipc-serialization.h" #include "LocalIPCProxy.h" #include "LocalIPCServiceAdapter.h" +#include "FaceliftIPCCommon.h" namespace facelift { namespace local { - -template -inline void LocalIPCServiceAdapterBase::serializeValue(LocalIPCMessage &msg, const Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg.outputPayLoad(), IPCTypeRegisterHandler::convertToSerializedType(v, *this)); -} - -template -inline void LocalIPCServiceAdapterBase::deserializeValue(LocalIPCMessage &msg, Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); -} - - -template -inline void LocalIPCProxyBinder::serializeValue(LocalIPCMessage &msg, const Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg.outputPayLoad(), IPCTypeRegisterHandler::convertToSerializedType(v, *this)); -} - -template -inline void LocalIPCProxyBinder::deserializeValue(LocalIPCMessage &msg, Type &v) -{ - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); -} - - template inline LocalIPCMessage LocalIPCProxyBinder::sendMethodCall(const char *methodName, const Args & ... args) const { LocalIPCMessage msg(methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { onServerNotAvailableError(methodName); @@ -98,11 +64,11 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac { LocalIPCMessage msg(methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); asyncCall(msg, this, [this, answer](LocalIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { - deserializeValue(msg, returnValue); + returnValue = (!msg.arguments().isEmpty() ? qvariant_cast(msg.arguments()[0]): ReturnType()); answer(returnValue); } else { qCWarning(LogIpc) << "Error received" << msg.toString(); @@ -115,88 +81,51 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac { LocalIPCMessage msg(methodName); auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(msg.outputPayLoad(), *this)); + for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); asyncCall(msg, this, [answer](LocalIPCMessage &msg) { Q_UNUSED(msg); answer(); }); } -template -inline void LocalIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, ReturnType &returnValue, const Args & ... args) const -{ - LocalIPCMessage msg = sendMethodCall(methodName, args ...); - if (msg.isReplyMessage()) { - const_cast(this)->deserializeValue(msg, returnValue); - } else { - assignDefaultValue(returnValue); - } -} - - template -inline void LocalIPCProxyBinder::sendSetterCall(const char *methodName, const PropertyType &value) +inline void LocalIPCProxyBinder::sendSetterCall(const QString& property, const PropertyType &value) { - LocalIPCMessage msg(methodName); - serializeValue(msg, value); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::SET_PROPERTY); + msg << QVariant::fromValue(m_interfaceName); + msg << QVariant::fromValue(property); + msg << QVariant::fromValue(QDBusVariant(QVariant::fromValue(value))); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { - onServerNotAvailableError(methodName); + onServerNotAvailableError(property); } } else { - asyncCall(msg, this, [this, methodName](const LocalIPCMessage &replyMessage) { + asyncCall(msg, this, [this, property](const LocalIPCMessage &replyMessage) { if (replyMessage.isErrorMessage()) { - onServerNotAvailableError(methodName); + onServerNotAvailableError(property); } }); } } -template -inline void LocalIPCServiceAdapterBase::sendSignal(MemberID signalID, const Args & ... args) +template +inline void LocalIPCServiceAdapterBase::sendSignal(const QString& signalName, const Args & ... args) { - if (m_pendingOutgoingMessage == nullptr) { - initOutgoingSignalMessage(); - auto argTuple = std::make_tuple(signalID, args ...); - for_each_in_tuple(argTuple, SerializeParameterFunction(m_pendingOutgoingMessage->outputPayLoad(), *this)); - flush(); - } + LocalIPCMessage signal(signalName); + auto argTuple = std::make_tuple(args ...); + for_each_in_tuple(argTuple, [this, &signal](const auto &v){signal << QVariant::fromValue(v);}); + this->send(signal); } template inline void LocalIPCServiceAdapterBase::sendAsyncCallAnswer(LocalIPCMessage &replyMessage, const ReturnType returnValue) { - serializeValue(replyMessage, returnValue); + replyMessage << QVariant::fromValue(returnValue); sendReply(replyMessage); } -template -inline void LocalIPCServiceAdapterBase::serializeOptionalValue(LocalIPCMessage &msg, const Type ¤tValue, Type &previousValue, - bool isCompleteSnapshot) -{ - if (isCompleteSnapshot) { - serializeValue(msg, currentValue); - } else { - if (previousValue == currentValue) { - msg.outputPayLoad().writeSimple(false); - } else { - msg.outputPayLoad().writeSimple(true); - serializeValue(msg, currentValue); - previousValue = currentValue; - } - } -} - -template -inline void LocalIPCServiceAdapterBase::serializeOptionalValue(LocalIPCMessage &msg, const Type ¤tValue, bool isCompleteSnapshot) -{ - msg.outputPayLoad().writeSimple(isCompleteSnapshot); - if (isCompleteSnapshot) { - serializeValue(msg, currentValue); - } -} } } diff --git a/src/ipc/local/LocalIPCMessage.cpp b/src/ipc/local/LocalIPCMessage.cpp index 411ed953..c36d2740 100644 --- a/src/ipc/local/LocalIPCMessage.cpp +++ b/src/ipc/local/LocalIPCMessage.cpp @@ -45,32 +45,22 @@ QString LocalIPCMessage::toString() const s << "Local IPC message "; s << " member:" << m_data.m_member; - s << m_data.m_payload; + s << m_data.m_arguments; return str; } -OutputPayLoad &LocalIPCMessage::outputPayLoad() -{ - if (m_outputPayload == nullptr) { - m_outputPayload = std::make_unique(m_data.m_payload); - } - return *m_outputPayload; -} - -InputPayLoad &LocalIPCMessage::inputPayLoad() +LocalIPCMessage::LocalIPCMessage() { - if (m_inputPayload == nullptr) { - m_inputPayload = std::make_unique(m_data.m_payload); - } - return *m_inputPayload; } -LocalIPCMessage::LocalIPCMessage() +LocalIPCMessage::LocalIPCMessage(const QString &methodName) { + m_data.m_member = methodName; } -LocalIPCMessage::LocalIPCMessage(const char *methodName) +LocalIPCMessage::LocalIPCMessage(const QString &interface, const char *methodName) { + m_data.m_interface = interface; m_data.m_member = methodName; } @@ -96,6 +86,17 @@ void LocalIPCMessage::copyRequestMessage(const LocalIPCMessage &other) } } +QList LocalIPCMessage::arguments() const +{ + return m_data.m_arguments; +} + +LocalIPCMessage &LocalIPCMessage::operator<<(const QVariant &arg) +{ + m_data.m_arguments.append(arg); + return *this; +} + LocalIPCMessage LocalIPCMessage::createReply() const { LocalIPCMessage reply; diff --git a/src/ipc/local/LocalIPCMessage.h b/src/ipc/local/LocalIPCMessage.h index 7d2a68d1..a5e0d7b8 100644 --- a/src/ipc/local/LocalIPCMessage.h +++ b/src/ipc/local/LocalIPCMessage.h @@ -71,7 +71,9 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCMessage LocalIPCMessage(); - LocalIPCMessage(const char *methodName); + LocalIPCMessage(const QString& methodName); + + LocalIPCMessage(const QString &interface, const char *methodName); LocalIPCMessage(const LocalIPCMessage &other); @@ -84,6 +86,14 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCMessage return m_data.m_member; } + QString interface() const + { + return m_data.m_interface; + } + + QList arguments() const; + + LocalIPCMessage &operator<<(const QVariant &arg); LocalIPCMessage createReply() const; @@ -101,10 +111,6 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCMessage return (m_data.m_messageType == MessageType::Error); } - OutputPayLoad &outputPayLoad(); - - InputPayLoad &inputPayLoad(); - void addListener(const QObject *context, ReplyFunction function); void notifyListener(); @@ -112,15 +118,14 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCMessage private: struct { + QString m_interface; QString m_member; - QByteArray m_payload; MessageType m_messageType = MessageType::Request; ReplyFunction m_listener; QPointer m_listenerContext; + QList m_arguments; } m_data; - std::unique_ptr m_outputPayload; - std::unique_ptr m_inputPayload; std::unique_ptr m_requestMessage; }; diff --git a/src/ipc/local/LocalIPCProxy.h b/src/ipc/local/LocalIPCProxy.h index 947f7a3a..94ad87ef 100644 --- a/src/ipc/local/LocalIPCProxy.h +++ b/src/ipc/local/LocalIPCProxy.h @@ -75,35 +75,6 @@ class LocalIPCProxy : public IPCProxyBase, protected LocalIPCProx return memberName; } - template - void serializeValue(LocalIPCMessage &msg, const Type &v) - { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - IPCTypeHandler::write(msg, IPCTypeRegisterHandler::convertToSerializedType(v, *this)); - } - - template - void deserializeValue(LocalIPCMessage &msg, Type &v) - { - typedef typename IPCTypeRegisterHandler::SerializedType SerializedType; - SerializedType serializedValue; - IPCTypeHandler::read(msg.inputPayLoad(), serializedValue); - IPCTypeRegisterHandler::convertToDeserializedType(v, serializedValue, *this); - } - - template - bool deserializeOptionalValue(LocalIPCMessage &msg, Type &value, bool isCompleteSnapshot) - { - bool b = true; - if (!isCompleteSnapshot) { - msg.inputPayLoad().readNextParameter(b); - } - if (b) { - this->deserializeValue(msg, value); - } - return b; - } - void setServiceRegistered(bool isRegistered) override { bool oldReady = this->ready(); @@ -115,13 +86,6 @@ class LocalIPCProxy : public IPCProxyBase, protected LocalIPCProx m_ipcBinder.setServiceAvailable(isRegistered); } - bool deserializeReadyValue(LocalIPCMessage &msg, bool isCompleteSnapshot) - { - bool previousIsReady = this->ready(); - deserializeOptionalValue(msg, this->m_serviceReady, isCompleteSnapshot); - return (this->ready() != previousIsReady); - } - LocalIPCProxyBinder *ipc() { return &m_ipcBinder; diff --git a/src/ipc/local/LocalIPCProxyBase.h b/src/ipc/local/LocalIPCProxyBase.h index d8476c6d..9771a2f4 100644 --- a/src/ipc/local/LocalIPCProxyBase.h +++ b/src/ipc/local/LocalIPCProxyBase.h @@ -34,6 +34,7 @@ #include "IPCProxyBase.h" #include "LocalIPCRequestHandler.h" #include "LocalIPCProxyBinder.h" +#include #if defined(FaceliftIPCLocalLib_LIBRARY) # define FaceliftIPCLocalLib_EXPORT Q_DECL_EXPORT @@ -50,6 +51,16 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCProxyBase : protected LocalIPCRequestHa public: LocalIPCProxyBase(LocalIPCProxyBinder &ipcBinder); + template + T castArgument(const QVariant& value) { + return qvariant_cast(value); + } + + template + T castDBusVariantArgument(const QVariant& value) { + return qvariant_cast(qvariant_cast(value).variant()); + } + protected: LocalIPCProxyBinder &m_ipcBinder; bool m_serviceRegistered = false; diff --git a/src/ipc/local/LocalIPCProxyBinder.cpp b/src/ipc/local/LocalIPCProxyBinder.cpp index eaff415f..87e4db32 100644 --- a/src/ipc/local/LocalIPCProxyBinder.cpp +++ b/src/ipc/local/LocalIPCProxyBinder.cpp @@ -60,9 +60,16 @@ void LocalIPCProxyBinder::checkServiceAvailability() } if (!isServiceAvailable()) { m_serviceAdapter = adapter; - m_signalConnection = QObject::connect(adapter, &LocalIPCServiceAdapterBase::messageSent, this, [this] (LocalIPCMessage &message) { - this->onSignalTriggered(message); - }); + m_signalConnection = QObject::connect(adapter, &LocalIPCServiceAdapterBase::messageSent, this, [this](LocalIPCMessage &msg){ + if ((msg.interface() == FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME) && + msg.member() == FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME) { + onPropertiesChanged(msg); + } + else if (!msg.member().isEmpty()) { + m_serviceObject->handleSignals(msg); + } + }); + requestPropertyValues(); } } @@ -110,7 +117,7 @@ void LocalIPCProxyBinder::setInterfaceName(const QString &name) checkInit(); } -void LocalIPCProxyBinder::onServerNotAvailableError(const char *methodName) const +void LocalIPCProxyBinder::onServerNotAvailableError(const QString& methodName) const { qCCritical(LogIpc, "Error message received when calling method '%s' on service at path '%s'. " @@ -120,13 +127,7 @@ void LocalIPCProxyBinder::onServerNotAvailableError(const char *methodName) cons void LocalIPCProxyBinder::onPropertiesChanged(LocalIPCMessage &msg) { - m_serviceObject->deserializePropertyValues(msg, false); -} - -void LocalIPCProxyBinder::onSignalTriggered(LocalIPCMessage &msg) -{ - m_serviceObject->deserializePropertyValues(msg, false); - m_serviceObject->deserializeSignal(msg); + m_serviceObject->unmarshalPropertiesChanged(msg); } LocalIPCMessage LocalIPCProxyBinder::call(LocalIPCMessage &message) const @@ -150,11 +151,12 @@ void LocalIPCProxyBinder::asyncCall(LocalIPCMessage &requestMessage, QObject *co void LocalIPCProxyBinder::requestPropertyValues() { - LocalIPCMessage msg(FaceliftIPCCommon::GET_PROPERTIES_MESSAGE_NAME); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::GET_ALL_PROPERTIES); + msg << interfaceName(); auto replyHandler = [this](LocalIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->deserializePropertyValues(replyMessage, true); + m_serviceObject->unmarshalPropertyValues(replyMessage); m_serviceObject->setServiceRegistered(true); emit serviceAvailableChanged(); } else { diff --git a/src/ipc/local/LocalIPCProxyBinder.h b/src/ipc/local/LocalIPCProxyBinder.h index 3818b260..39704733 100644 --- a/src/ipc/local/LocalIPCProxyBinder.h +++ b/src/ipc/local/LocalIPCProxyBinder.h @@ -67,8 +67,6 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCProxyBinder : public IPCProxyBinderBase void onPropertiesChanged(LocalIPCMessage &message); - void onSignalTriggered(LocalIPCMessage &message); - void bindToIPC() override; void setServiceAvailable(bool isRegistered); @@ -81,16 +79,10 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCProxyBinder : public IPCProxyBinderBase void requestPropertyValues(); - template - void serializeValue(LocalIPCMessage &msg, const Type &v); - - template - void deserializeValue(LocalIPCMessage &msg, Type &v); - - void onServerNotAvailableError(const char *methodName) const; + void onServerNotAvailableError(const QString &methodName) const; template - void sendSetterCall(const char *methodName, const PropertyType &value); + void sendSetterCall(const QString &property, const PropertyType &value); template LocalIPCMessage sendMethodCall(const char *methodName, const Args & ... args) const; diff --git a/src/ipc/local/LocalIPCRequestHandler.h b/src/ipc/local/LocalIPCRequestHandler.h index 8296467d..3bed1008 100644 --- a/src/ipc/local/LocalIPCRequestHandler.h +++ b/src/ipc/local/LocalIPCRequestHandler.h @@ -43,7 +43,6 @@ #include "FaceliftModel.h" #include "FaceliftUtils.h" #include "ModelProperty.h" - #include "ipc-common.h" namespace facelift { @@ -61,8 +60,10 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCRequestHandler { public: - virtual void deserializePropertyValues(LocalIPCMessage &msg, bool isCompleteSnapshot) = 0; - virtual void deserializeSignal(LocalIPCMessage &msg) = 0; + virtual void unmarshalPropertyValues(LocalIPCMessage &msg) = 0; + virtual void unmarshalPropertiesChanged(LocalIPCMessage &msg) = 0; + virtual void handleSignals(LocalIPCMessage& msg) = 0; + virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; }; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index 004439d8..fe764318 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -30,6 +30,7 @@ #pragma once +#include #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" #include "LocalIPCServiceAdapterBase.h" @@ -91,6 +92,16 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } + template + T castArgument(const QVariant& value) { + return qvariant_cast(value); + } + + template + T castDBusVariantArgument(const QVariant& value) { + return qvariant_cast(qvariant_cast(value).variant()); + } + protected: QPointer m_service; }; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.cpp b/src/ipc/local/LocalIPCServiceAdapterBase.cpp index 60f8bdc5..3b5987a8 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.cpp +++ b/src/ipc/local/LocalIPCServiceAdapterBase.cpp @@ -40,28 +40,6 @@ namespace facelift { namespace local { -void LocalIPCServiceAdapterBase::initOutgoingSignalMessage() -{ - m_pendingOutgoingMessage = std::make_unique(FaceliftIPCCommon::SIGNAL_TRIGGERED_SIGNAL_NAME); - - // Send property value updates before the signal itself so that they are set before the signal is triggered on the client side. - this->serializePropertyValues(*m_pendingOutgoingMessage, false); -} - -void LocalIPCServiceAdapterBase::serializePropertyValues(LocalIPCMessage &msg, bool isCompleteSnapshot) -{ - Q_ASSERT(service()); - serializeOptionalValue(msg, service()->ready(), m_previousReadyState, isCompleteSnapshot); -} - -void LocalIPCServiceAdapterBase::flush() -{ - if (m_pendingOutgoingMessage) { - this->send(*m_pendingOutgoingMessage); - m_pendingOutgoingMessage.reset(); - } -} - IPCHandlingResult LocalIPCServiceAdapterBase::handleMessage(LocalIPCMessage &requestMessage) { LocalIPCMessage replyMessage = requestMessage.createReply(); @@ -71,9 +49,18 @@ IPCHandlingResult LocalIPCServiceAdapterBase::handleMessage(LocalIPCMessage &req auto handlingResult = IPCHandlingResult::OK; bool sendReply = true; - if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTIES_MESSAGE_NAME) { - serializePropertyValues(replyMessage, true); - } else { + if (requestMessage.interface() == FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME) { + if (requestMessage.member() == FaceliftIPCCommon::GET_ALL_PROPERTIES) { + marshalPropertyValues(requestMessage.arguments(), replyMessage); + } + else if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTY) { + marshalProperty(requestMessage.arguments(), replyMessage); + } + else if (requestMessage.member() == FaceliftIPCCommon::SET_PROPERTY) { + setProperty(requestMessage.arguments()); + } + } + else { handlingResult = handleMethodCallMessage(requestMessage, replyMessage); if (handlingResult == IPCHandlingResult::INVALID) { replyMessage = requestMessage.createErrorReply(); @@ -126,9 +113,6 @@ void LocalIPCServiceAdapterBase::registerService() m_alreadyInitialized = true; qCDebug(LogIpc) << "Registering local IPC object at " << objectPath(); if (m_alreadyInitialized) { - QObject::connect(service(), &InterfaceBase::readyChanged, this, [this]() { - this->sendSignal(CommonSignalID::readyChanged); - }); connectSignals(); } else { qFatal("Could not register service at object path '%s'", qPrintable(objectPath())); diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 4911cec6..e1dd3828 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -32,6 +32,7 @@ #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" +#include "FaceliftIPCCommon.h" #if defined(FaceliftIPCLocalLib_LIBRARY) # define FaceliftIPCLocalLib_EXPORT Q_DECL_EXPORT @@ -61,18 +62,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA IPCHandlingResult handleMessage(LocalIPCMessage &message); - void flush(); + template + inline void sendPropertiesChanged(const QString& property , const Value & value); - template - void serializeValue(LocalIPCMessage &msg, const Type &v); - - template - void deserializeValue(LocalIPCMessage &msg, Type &v); - - void initOutgoingSignalMessage(); - - template - void sendSignal(MemberID signalID, const Args & ... args); + template + void sendSignal(const QString& signalName, const Args & ... args); template void sendAsyncCallAnswer(LocalIPCMessage &replyMessage, const ReturnType returnValue); @@ -81,7 +75,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA virtual IPCHandlingResult handleMethodCallMessage(LocalIPCMessage &requestMessage, LocalIPCMessage &replyMessage) = 0; - virtual void serializePropertyValues(LocalIPCMessage &msg, bool isCompleteSnapshot); + virtual void marshalPropertyValues(const QList& arguments, LocalIPCMessage &msg) = 0; + + virtual void marshalProperty(const QList& arguments, LocalIPCMessage &msg) = 0; + + virtual void setProperty(const QList& arguments) = 0; void registerService() override; @@ -93,12 +91,6 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA void sendReply(LocalIPCMessage &message); - template - void serializeOptionalValue(LocalIPCMessage &msg, const Type ¤tValue, Type &previousValue, bool isCompleteSnapshot); - - template - void serializeOptionalValue(LocalIPCMessage &msg, const Type ¤tValue, bool isCompleteSnapshot); - virtual void appendDBUSIntrospectionData(QTextStream &s) const = 0; QString introspect(const QString &path) const; @@ -122,6 +114,14 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA bool m_alreadyInitialized = false; }; +template +inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QString& property , const Value & value) +{ + LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); + reply << interfaceName(); + reply << QVariantMap{{property, QVariant::fromValue(value)}}; + this->send(reply); +} } diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index 83131aeb..d14ff1aa 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -81,6 +81,7 @@ facelift_add_library(FaceliftModelLib LINK_LIBRARIES Qt5::Qml Qt5::Quick + Qt5::DBus FaceliftCommonLib MONOLITHIC_SUPPORTED ) diff --git a/src/model/FaceliftEnum.h b/src/model/FaceliftEnum.h index df45946d..2d46dff6 100644 --- a/src/model/FaceliftEnum.h +++ b/src/model/FaceliftEnum.h @@ -39,6 +39,47 @@ #include "FaceliftCommon.h" #include #include +#include + +template +class QDBusEnumMarshal; + +template +class QDBusEnumMarshal::value>::type> +{ +public: + static QDBusArgument& marshal(QDBusArgument &argument, const T& source) + { + argument.beginStructure(); + argument << static_cast(source); + argument.endStructure(); + return argument; + } + + static const QDBusArgument& unmarshal(const QDBusArgument &argument, T &source) + { + int a; + argument.beginStructure(); + argument >> a; + argument.endStructure(); + + source = static_cast(a); + + return argument; + } +}; + +template +QDBusArgument& operator<<(QDBusArgument &argument, const T& source) +{ + return QDBusEnumMarshal::marshal(argument, source); +} + +template +const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) +{ + return QDBusEnumMarshal::unmarshal(argument, source); +} namespace facelift { From 47b4a42a4118b39f11aedec90981a9844c6a6e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Sun, 13 Sep 2020 16:33:30 +0200 Subject: [PATCH 02/12] standardize facelift dbus communication Fix service type --- .../IPCDBusServiceAdapter.template.h | 7 -- .../templates/IPCProxyAdapter.template.cpp | 58 ++++--------- .../templates/IPCProxyAdapter.template.h | 3 - .../templates/IPCServiceAdapter.template.cpp | 54 +++++------- .../templates/IPCServiceAdapter.template.h | 7 -- src/ipc/dbus/DBusIPCCommon.h | 13 +-- src/ipc/dbus/DBusIPCProxy.h | 19 +--- src/ipc/dbus/DBusIPCProxyBinder.h | 61 ++++++++++++- src/ipc/dbus/IPCDBusServiceAdapter.h | 29 ------- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 86 ++++++++++++++++--- src/ipc/ipc-common/IPCProxyBase.h | 29 ------- src/ipc/ipc-common/IPCServiceAdapterBase.h | 51 +++++++---- src/ipc/local/LocalIPCProxy.h | 47 ++++++++++ src/ipc/local/LocalIPCProxyBase.h | 10 --- src/ipc/local/LocalIPCServiceAdapter.h | 11 --- src/ipc/local/LocalIPCServiceAdapterBase.h | 58 ++++++++++++- 16 files changed, 316 insertions(+), 227 deletions(-) diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index 0fdcec71..8ab9b6f6 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -110,13 +110,6 @@ class {{classExport}} {{className}}: public {{baseClass}} {% for property in interface.properties %} {% if property.type.is_model %} ::facelift::IPCAdapterModelPropertyHandler m_{{property.name}}Handler; - {% elif property.type.is_interface %} - QString m_previous{{property.name}}ObjectPath; - {% else %} - {{property.interfaceCppType}} m_previous{{property.name}} {}; - {% endif %} - {% if property.type.is_interface %} - InterfacePropertyIPCAdapterHandler<{{property.cppType}}, {{property.cppType}}{{proxyTypeNameSuffix}}> m_{{property.name}}; {% endif %} {% endfor %} }; diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 45f89b51..9666c80a 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -43,9 +43,6 @@ {{className}}::{{className}}(QObject *parent) : BaseType(parent) {% for property in interface.properties %} - {% if property.type.is_interface %} - , m_{{property.name}}Proxy(*this) - {% endif %} {% if property.type.is_model %} , m_{{property.name}}(*this) {% endif %} @@ -61,47 +58,33 @@ void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) { QListIterator argumentsIterator(msg.arguments()); if (argumentsIterator.hasNext()) { - QMap values = castArgument>(argumentsIterator.next()); + QMap values = castFromVariant>(argumentsIterator.next()); for (const QString &propertyName: values.keys()) { {% for property in interface.properties %} - {% if property.type.is_interface %} if (propertyName == QStringLiteral("{{property.name}}")) { - bool emit_{{property.name}}ChangeSignal = false; - QString {{property.name}}_objectPath = castDBusVariantArgument(values[propertyName]); - m_{{property.name}}Proxy.update({{property.name}}_objectPath); - m_{{property.name}} = m_{{property.name}}Proxy.getValue(); - emit_{{property.name}}ChangeSignal = true; - if (emit_{{property.name}}ChangeSignal) - emit {{property.name}}Changed(); - } + {% if property.type.is_interface %} + const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); + bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); {% elif property.type.is_model %} - if (propertyName == QStringLiteral("{{property.name}}")) { bool emit_{{property.name}}ChangeSignal = false; - int {{property.name}}Size = castDBusVariantArgument(values[propertyName]); + int {{property.name}}Size = castFromDBusVariant(values[propertyName]); m_{{property.name}}.beginResetModel(); m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); m_{{property.name}}.endResetModel(); emit_{{property.name}}ChangeSignal = true; - if (emit_{{property.name}}ChangeSignal) - emit {{property.name}}Changed(); - } {% else %} - if (propertyName == QStringLiteral("{{property.name}}")) { const auto previous_{{property.name}}_Value = m_{{property.name}}; - {% if (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} - m_{{property.name}} = castDBusVariantArgument(values[propertyName]); - {% else %} - m_{{property.name}} = castDBusVariantArgument<{{property.interfaceCppType}}>(values[propertyName]); - {% endif %} + m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% endif %} if (emit_{{property.name}}ChangeSignal) emit {{property.name}}Changed(); } - {% endif %} {% endfor %} if (propertyName == QStringLiteral("ready")) { bool previousIsReady = this->ready(); - m_serviceReady = castDBusVariantArgument(values[propertyName]); + m_serviceReady = castFromDBusVariant(values[propertyName]); bool emit_ReadyChangeSignal = (previousIsReady != m_serviceReady); if (emit_ReadyChangeSignal) emit readyChanged(); @@ -117,7 +100,7 @@ void {{className}}::handleSignals(InputIPCMessage& msg) QListIterator argumentsIterator(msg.arguments()); {% for parameter in event.parameters %} {{parameter.interfaceCppType}} param_{{parameter.name}}; - param_{{parameter.name}} = (argumentsIterator.hasNext() ? castArgument<{{parameter.interfaceCppType}}>(argumentsIterator.next()): {{parameter.interfaceCppType}}()); + param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); {% endfor %} emit {{event}}( {%- set comma = joiner(", ") -%} @@ -154,7 +137,7 @@ const QList& {{className}}::getSignals() const void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) { QListIterator argumentsIterator(msg.arguments()); - const QString& modelPropertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); {% for property in interface.properties %} {% if property.type.is_model %} if (modelPropertyName == QStringLiteral("{{property.name}}")) { @@ -168,22 +151,17 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) { QListIterator argumentsIterator(msg.arguments()); - QString interfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); - QVariantMap changedProperties = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QVariantMap()); + QString interfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); + QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QVariantMap()); for (const QString &propertyName: changedProperties.keys()) { {% for property in interface.properties %} - {% if property.type.is_interface %} - {% elif property.type.is_model %} - {% else %} if (propertyName == QStringLiteral("{{property.name}}")) { - {% if (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} - m_{{property.name}} = castArgument(changedProperties[propertyName]); - {% else %} - m_{{property.name}} = castArgument<{{property.cppType}}>(changedProperties[propertyName]); - {% endif %} + {% if property.type.is_model %} + {% else %} + m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); emit {{property.name}}Changed(); // trust the propertiesChanged signal and emit without checking - } {% endif %} + } {% endfor %} } } @@ -233,7 +211,7 @@ void {{className}}::{{operation.name}}( {%- for parameter in operation.parameters -%} , {{parameter.name}} {%- endfor -%} ); - return (!args.isEmpty() ? castArgument<{{operation.interfaceCppType}}>(args[0]): {{operation.interfaceCppType}}()); + return (!args.isEmpty() ? castFromVariant<{{operation.interfaceCppType}}>(args[0]):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); {% else %} ipc()->sendMethodCall(memberID(MethodID::{{operation.name}}, "{{operation.name}}") {%- for parameter in operation.parameters -%} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index 96651a87..b3d321fc 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -162,9 +162,6 @@ class {{classExport}} {{className}} : public {{baseClass}} {% endif %} private: {% for property in interface.properties %} - {% if property.type.is_interface %} - InterfacePropertyIPCProxyHandler<{{property.cppType}}{{proxyTypeNameSuffix}}> m_{{property.name}}Proxy; - {% endif %} {% if property.type.is_model %} facelift::IPCProxyModelProperty m_{{property.name}}; {% endif %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index d2f9486b..37cf5743 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -57,7 +57,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for operation in interface.operations %} if (member == memberID(MethodID::{{operation.name}}, "{{operation.name}}")) { {% for parameter in operation.parameters %} - {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castArgument<{{parameter.cppType}}>(argumentsIterator.next()): {{parameter.cppType}}()); + {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.cppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.cppType}}(){% else %}nullptr{% endif %}); {% endfor %} {% if operation.isAsync %} theService->{{operation.name}}({% for parameter in operation.parameters %} param_{{parameter.name}}, {%- endfor -%} @@ -75,7 +75,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {{ comma() }}param_{{parameter.name}} {%- endfor -%}); {% if operation.hasReturnValue %} - replyMessage << QVariant::fromValue(returnValue); + replyMessage << castToVariant(returnValue); {% endif %} {% endif %} } else @@ -157,12 +157,6 @@ void {{className}}::connectSignals() // Properties {% for property in interface.properties %} - {% if property.type.is_interface %} - m_{{property.name}}.update(this, theService->{{property.name}}()); - QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this, theService] () { - m_{{property.name}}.update(this, theService->{{property.name}}()); - }); - {% endif %} {% if (not property.type.is_model) %} QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this, theService] () { this->sendPropertiesChanged("{{property.name}}", theService->{{property.name}}()); @@ -183,7 +177,7 @@ void {{className}}::connectSignals() void {{className}}::marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) { QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); if (msgInterfaceName == interfaceName()) { auto theService = service(); QMap ret; @@ -192,40 +186,34 @@ void {{className}}::marshalPropertyValues(const QList& arguments, Outp {#% endif %#} {% for property in interface.properties %} - {% if property.type.is_interface %} - ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(m_{{property.name}}.objectPath())); - {% elif property.type.is_model %} - ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(theService->{{property.name}}().size())); - {% elif (property.type.is_list and property.nestedType.interfaceCppType == 'QString') %} - ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(QStringList(theService->{{property.name}}()))); + {% if property.type.is_model %} + ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}().size()); {% else %} - ret["{{property.name}}"] = QDBusVariant(QVariant::fromValue(theService->{{property.name}}())); + ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}()); {% endif %} {% endfor %} - ret["ready"] = QDBusVariant(QVariant::fromValue(theService->ready())); - msg << QVariant::fromValue(ret); + ret["ready"] = castToDBusVariant(theService->ready()); + msg << castToVariant(ret); } } void {{className}}::marshalProperty(const QList& arguments, OutputIPCMessage& msg) { QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); {% for property in interface.properties %} - {% if property.type.is_interface %} - - {% elif property.type.is_model %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_model %} {% else %} - if (propertyName == QStringLiteral("{{property.name}}")) { - msg << QVariant::fromValue(service()->{{property.name}}()); - } + msg << castToVariant(service()->{{property.name}}()); {% endif %} + } {% endfor %} if (propertyName == QStringLiteral("ready")) { - msg << QVariant::fromValue(service()->ready()); + msg << castToVariant(service()->ready()); } } } @@ -233,20 +221,20 @@ void {{className}}::marshalProperty(const QList& arguments, OutputIPCM void {{className}}::setProperty(const QList& arguments) { QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castArgument(argumentsIterator.next()): QString()); + auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); if (argumentsIterator.hasNext()) { {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { {% if property.type.is_interface %} - + Q_ASSERT(false); // Writable interface properties are unsupported {% elif property.type.is_model %} {% elif (not property.readonly) %} - if (propertyName == QStringLiteral("{{property.name}}")) { - service()->set{{property.name}}(castDBusVariantArgument<{{property.cppType}}>(argumentsIterator.next())); - } + service()->set{{property.name}}(castFromDBusVariant<{{property.cppType}}>(argumentsIterator.next())); {% endif %} + } {% endfor %} } } diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index 10cd513c..b15404a2 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -106,13 +106,6 @@ class {{classExport}} {{className}}: public {{baseClass}} {% for property in interface.properties %} {% if property.type.is_model %} ::facelift::IPCAdapterModelPropertyHandler m_{{property.name}}Handler; - {% elif property.type.is_interface %} - QString m_previous{{property.name}}ObjectPath; - {% else %} - {{property.interfaceCppType}} m_previous{{property.name}} {}; - {% endif %} - {% if property.type.is_interface %} - InterfacePropertyIPCAdapterHandler<{{property.cppType}}, {{property.cppType}}{{proxyTypeNameSuffix}}> m_{{property.name}}; {% endif %} {% endfor %} }; diff --git a/src/ipc/dbus/DBusIPCCommon.h b/src/ipc/dbus/DBusIPCCommon.h index 710ee5ee..44302f28 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -38,22 +38,11 @@ #include -template -const char* typeToSignature() -{ - return QDBusMetaType::typeToSignature(qMetaTypeId()); -} - -template<> -inline const char* typeToSignature>() -{ - return QDBusMetaType::typeToSignature(qMetaTypeId()); -} - namespace facelift { namespace dbus { using namespace facelift; + struct FaceliftIPCLibDBus_EXPORT DBusIPCCommon { static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; static constexpr const char *GET_PROPERTY = "Get"; diff --git a/src/ipc/dbus/DBusIPCProxy.h b/src/ipc/dbus/DBusIPCProxy.h index 6f19d579..1d29e475 100644 --- a/src/ipc/dbus/DBusIPCProxy.h +++ b/src/ipc/dbus/DBusIPCProxy.h @@ -56,8 +56,6 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa using InputIPCMessage = ::facelift::dbus::DBusIPCMessage; using OutputIPCMessage = ::facelift::dbus::DBusIPCMessage; - template struct type { }; - template using IPCProxyType = typename Type::IPCDBusProxyType; @@ -108,13 +106,13 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa } template - T castArgument(const QVariant& value) { - return castArgumentPrivate(type(), value); + T castFromVariant(const QVariant& value) { + return m_ipcBinder.castFromVariant(value); } template - T castDBusVariantArgument(const QVariant& value) { - return qdbus_cast(value); + T castFromDBusVariant(const QVariant& value) { + return m_ipcBinder.castFromDBusVariant(value); } protected: @@ -122,15 +120,6 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa private: DBusIPCProxyBinder m_ipcBinder; - template - T castArgumentPrivate(type, const QVariant& value) { - return qdbus_cast(value); - } - - QList castArgumentPrivate(type>, const QVariant& value) { - return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList - } - }; } // end namespace dbus diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index 9514595c..ee6bab98 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -43,6 +43,7 @@ #include "FaceliftUtils.h" #include "DBusIPCCommon.h" #include "DBusManagerInterface.h" +#include "IPCServiceAdapterBase.h" class QDBusMessage; @@ -112,9 +113,63 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void setHandler(DBusRequestHandler *handler); + template + T castFromVariant(const QVariant& value) { + return castFromVariantSpecialized(HelperType(), value); + } + + template + T castFromDBusVariant(const QVariant& value) { + return castFromVariantSpecialized(HelperType(), value); + } + + template + QDBusVariant castToDBusVariant(const T& value) { + return QDBusVariant(QVariant::fromValue(value)); + } + + QDBusVariant castToDBusVariant(const QList& value) { + return QDBusVariant(QVariant::fromValue(QStringList(value))); // workaround to use QList since its signature matches the QStringList + } private: void checkRegistry(); + template struct HelperType { }; + + template::value, int> = 0> + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return qdbus_cast(value); + } + + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + + template::value, int> = 0> + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCDBusProxyType>(qdbus_cast(value)); + } + + template + QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qdbus_cast>(value); + for (const QString& key: objectPaths.keys()) { + ret[key] = getOrCreateSubProxy(objectPaths[key]); + } + return ret; + } + + template + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qdbus_cast*/>(value); + for (const DBusObjectPath& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy(objectPath)); + } + return ret; + } + QString m_interfaceName; QDBusServiceWatcher m_busWatcher; DBusRequestHandler *m_serviceObject = nullptr; @@ -145,7 +200,9 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { - returnValue = (!msg.arguments().isEmpty() ? qdbus_cast(msg.arguments()[0]): ReturnType()); + if (!msg.arguments().isEmpty()) { + returnValue = castFromVariant(msg.arguments()[0]); + } answer(returnValue); } else { qCWarning(LogIpc) << "Error received" << msg.toString(); @@ -182,7 +239,7 @@ inline void DBusIPCProxyBinder::sendSetterCall(const QString &property, const Pr DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY); msg << QVariant::fromValue(m_interfaceName); msg << QVariant::fromValue(property); - msg << QVariant::fromValue(QDBusVariant(QVariant::fromValue(value))); + msg << QVariant::fromValue(castToDBusVariant(value)); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index c74bc6e4..4a65cb27 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -58,7 +58,6 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase typedef ServiceType TheServiceType; using InputIPCMessage = ::facelift::dbus::DBusIPCMessage; using OutputIPCMessage = ::facelift::dbus::DBusIPCMessage; - template struct type { }; IPCDBusServiceAdapter(DBusManagerInterface& dbusManager, QObject *parent) : IPCDBusServiceAdapterBase(dbusManager, parent) @@ -91,37 +90,9 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase Q_ASSERT(qobject_cast(serverObject) != nullptr); registerService(objectPath, static_cast(serverObject)); } - - template - T castArgument(const QVariant& value) { - return castArgumentPrivate(type(), value); - } - - template - T castDBusVariantArgument(const QVariant& value) { - return castDBusVariantArgumentPrivate(type(), value); - } - protected: QPointer m_service; - template - T castArgumentPrivate(type, const QVariant& value) { - return qdbus_cast(value); - } - - QList castArgumentPrivate(type>, const QVariant& value) { - return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList - } - - template - T castDBusVariantArgumentPrivate(type, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); - } - - QList castDBusVariantArgumentPrivate(type>, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); - } }; } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index d9d7be69..c71bde01 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -126,6 +126,26 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda return memberName; } + template + T castFromVariant(const QVariant& value) { + return castFromVariantSpecialized(HelperType(), value); + } + + template + T castFromDBusVariant(const QVariant& value) { + return castFromDBusVariantSpecialized(HelperType(), value); + } + + template + QVariant castToVariant(const T& value) { + return castToVariantSpecialized(HelperType(), value); + } + + template + QDBusVariant castToDBusVariant(const T& value) { + return QDBusVariant(castToVariant(value)); + } + protected: DBusVirtualObject m_dbusVirtualObject; @@ -137,6 +157,61 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool m_alreadyInitialized = false; DBusManagerInterface& m_dbusManager; +private: + template struct HelperType { }; + template + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return qdbus_cast(value); + } + + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + + template + T castFromDBusVariantSpecialized(HelperType, const QVariant& value) { + return qvariant_cast(qdbus_cast(value).variant()); + } + + QList castFromDBusVariantSpecialized(HelperType>, const QVariant& value) { + return qvariant_cast(qdbus_cast(value).variant()); + } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType, const T& value) { + return QVariant::fromValue(value); + } + + QVariant castToVariantSpecialized(HelperType>, const QList& value) { + return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList + } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType, const T& value) { + DBusObjectPath dbusObjectPath; + if (value != nullptr) { + dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCDBusAdapterType>(value)->objectPath()); + } + return QVariant::fromValue(dbusObjectPath); + } + + template + QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QStringList /*QList*/ objectPathes; + for (T* service: value) { + objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + } + return QVariant::fromValue(objectPathes); + } + + template + QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QMap objectPathesMap; + for (const QString& key: value.keys()) { + objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + } + return QVariant::fromValue(objectPathesMap); + } }; template @@ -144,16 +219,7 @@ inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& prop { DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariantMap{{property, QVariant::fromValue(value)}}; - this->send(reply); -} - -template<> -inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& property, const QList &value) -{ - DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); - reply << interfaceName(); - reply << QVariantMap{{property, QVariant::fromValue(QStringList(value))}}; + reply << QVariant::fromValue(QMap{{property, castToDBusVariant(value)}}); this->send(reply); } diff --git a/src/ipc/ipc-common/IPCProxyBase.h b/src/ipc/ipc-common/IPCProxyBase.h index 1903a109..362f18ec 100644 --- a/src/ipc/ipc-common/IPCProxyBase.h +++ b/src/ipc/ipc-common/IPCProxyBase.h @@ -72,35 +72,6 @@ class IPCProxyBase : public AdapterType return r; } - template - class InterfacePropertyIPCProxyHandler - { - - public: - InterfacePropertyIPCProxyHandler(IPCProxyBase &owner) : m_owner(owner) - { - } - - void update(const QString &objectPath) - { - if (m_proxy && (m_proxy->ipc()->objectPath() != objectPath)) { - m_proxy = nullptr; - } - if (!m_proxy) { - m_proxy = m_owner.m_ipcBinder->template getOrCreateSubProxy(objectPath); - } - } - - ProxyType *getValue() const - { - return m_proxy; - } - - private: - QPointer m_proxy; - IPCProxyBase &m_owner; - }; - protected: bool m_serviceReady = false; IPCProxyBinderBase *m_ipcBinder = nullptr; diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index 10fc8012..c8b95ca5 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -30,6 +30,7 @@ #pragma once #include +#include #include "FaceliftModel.h" @@ -41,6 +42,7 @@ namespace facelift { +typedef QString DBusObjectPath; // potentially could be QDBusObjectPath but no empty QDBusObjectPath is allowed class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject { @@ -109,29 +111,42 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject return serviceAdapter; } - template - class InterfacePropertyIPCAdapterHandler + template + const char* typeToSignature() const { + return typeToSignatureSpecialized(HelperType()); + } +private: + template struct HelperType { }; + template::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } - public: - void update(IPCServiceAdapterBase *parent, InterfaceType *service) - { - if (m_service != service) { - m_service = service; - m_serviceAdapter = parent->getOrCreateAdapter(service); - } - } + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } - QString objectPath() const - { - return (m_serviceAdapter ? m_serviceAdapter->objectPath() : ""); - } + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } - QPointer m_service; - QPointer m_serviceAdapter; - }; + template + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } -private: QList > m_subAdapters; QString m_objectPath; QString m_interfaceName; diff --git a/src/ipc/local/LocalIPCProxy.h b/src/ipc/local/LocalIPCProxy.h index 94ad87ef..9ecd9353 100644 --- a/src/ipc/local/LocalIPCProxy.h +++ b/src/ipc/local/LocalIPCProxy.h @@ -42,6 +42,8 @@ namespace facelift { +typedef QString DBusObjectPath; + namespace local { using namespace facelift; @@ -102,7 +104,52 @@ class LocalIPCProxy : public IPCProxyBase, protected LocalIPCProx m_ipcBinder.connectToServer(); } + template + T castFromVariant(const QVariant& value) { + return castFromVariantSpecialized(HelperType(), value); + } + + template + T castFromDBusVariant(const QVariant& value) { + return castFromVariantSpecialized(HelperType(), qvariant_cast(value).variant()); + } + private: + template struct HelperType { }; + template::value, int> = 0> + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return qvariant_cast(value); + } + + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + return qvariant_cast(value); // workaround to use QList since its signature matches the QStringList + } + + template::value, int> = 0> + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCLocalProxyType>(qvariant_cast(value)); + } + + template + QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qvariant_cast>(value); + for (const QString& key: objectPaths.keys()) { + ret[key] = getOrCreateSubProxy(objectPaths[key]); + } + return ret; + } + + template + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qvariant_cast*/>(value); + for (const DBusObjectPath& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy(objectPath)); + } + return ret; + } + LocalIPCProxyBinder m_ipcBinder; }; diff --git a/src/ipc/local/LocalIPCProxyBase.h b/src/ipc/local/LocalIPCProxyBase.h index 9771a2f4..a0e0f426 100644 --- a/src/ipc/local/LocalIPCProxyBase.h +++ b/src/ipc/local/LocalIPCProxyBase.h @@ -51,16 +51,6 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCProxyBase : protected LocalIPCRequestHa public: LocalIPCProxyBase(LocalIPCProxyBinder &ipcBinder); - template - T castArgument(const QVariant& value) { - return qvariant_cast(value); - } - - template - T castDBusVariantArgument(const QVariant& value) { - return qvariant_cast(qvariant_cast(value).variant()); - } - protected: LocalIPCProxyBinder &m_ipcBinder; bool m_serviceRegistered = false; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index fe764318..004439d8 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -30,7 +30,6 @@ #pragma once -#include #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" #include "LocalIPCServiceAdapterBase.h" @@ -92,16 +91,6 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } - template - T castArgument(const QVariant& value) { - return qvariant_cast(value); - } - - template - T castDBusVariantArgument(const QVariant& value) { - return qvariant_cast(qvariant_cast(value).variant()); - } - protected: QPointer m_service; }; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index e1dd3828..0cb0b176 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -30,6 +30,7 @@ #pragma once +#include #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" #include "FaceliftIPCCommon.h" @@ -103,6 +104,61 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA return memberName; } + template + T castFromVariant(const QVariant& value) { + return qvariant_cast(value); + } + + template + T castFromDBusVariant(const QVariant& value) { + return qvariant_cast(qvariant_cast(value).variant()); + } + + template::value, int> = 0> + QVariant castToVariant(const T& value) { + return QVariant::fromValue(value); + } + + QVariant castToVariant(const QList& value) { + return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList + } + + template::value, int> = 0> + QVariant castToVariant(const T& value) { + DBusObjectPath dbusObjectPath; + if (value != nullptr) { + dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCLocalAdapterType>(value)->objectPath()); + } + return QVariant::fromValue(dbusObjectPath); + } + + template + QVariant castToVariant(const QList& value) { + QStringList /*QList*/ objectPathes; + for (T* service: value) { + objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + } + return QVariant::fromValue(objectPathes); + } + + template + QVariant castToVariant(const QMap& value) { + QMap objectPathesMap; + for (const QString& key: value.keys()) { + objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + } + return QVariant::fromValue(objectPathesMap); + } + + template + QDBusVariant castToDBusVariant(const T& value) { + return QDBusVariant(castToVariant(value)); + } + + QDBusVariant castToDBusVariant(const QList& value) { + return QDBusVariant(castToVariant(value)); + } + protected: std::unique_ptr m_pendingOutgoingMessage; @@ -119,7 +175,7 @@ inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QString& pro { LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariantMap{{property, QVariant::fromValue(value)}}; + reply << QVariant::fromValue(QMap{{property, castToDBusVariant(value)}}); this->send(reply); } From 7fb1d9cd45810ba1e68e3f915c339508e1d56d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Mon, 14 Sep 2020 17:48:44 +0200 Subject: [PATCH 03/12] Standardize facelift dbus communication Fix removed enum/struct qt-registeration --- .../templates/IPCProxyAdapter.template.cpp | 9 +- .../facelift/templates/Module.template.cpp | 7 ++ codegen/facelift/templates/Service.template.h | 1 - src/ipc/dbus/DBusIPCCommon.h | 1 - src/ipc/dbus/DBusIPCProxyBinder.cpp | 2 +- src/ipc/ipc-common/IPCProxyModelProperty.h | 88 +++++++++---------- 6 files changed, 57 insertions(+), 51 deletions(-) diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 9666c80a..7f916eda 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -67,12 +67,11 @@ void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); {% elif property.type.is_model %} - bool emit_{{property.name}}ChangeSignal = false; + bool emit_{{property.name}}ChangeSignal = true; int {{property.name}}Size = castFromDBusVariant(values[propertyName]); m_{{property.name}}.beginResetModel(); m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); m_{{property.name}}.endResetModel(); - emit_{{property.name}}ChangeSignal = true; {% else %} const auto previous_{{property.name}}_Value = m_{{property.name}}; m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); @@ -157,10 +156,14 @@ void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) {% for property in interface.properties %} if (propertyName == QStringLiteral("{{property.name}}")) { {% if property.type.is_model %} + int {{property.name}}Size = castFromDBusVariant(changedProperties[propertyName]); + m_{{property.name}}.beginResetModel(); + m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); + m_{{property.name}}.endResetModel(); {% else %} m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); - emit {{property.name}}Changed(); // trust the propertiesChanged signal and emit without checking {% endif %} + emit {{property.name}}Changed(); // trust the propertiesChanged signal and emit without checking } {% endfor %} } diff --git a/codegen/facelift/templates/Module.template.cpp b/codegen/facelift/templates/Module.template.cpp index d0474ac9..6dea4e1c 100644 --- a/codegen/facelift/templates/Module.template.cpp +++ b/codegen/facelift/templates/Module.template.cpp @@ -76,6 +76,13 @@ void Module::registerTypes() if (!alreadyRegistered) { alreadyRegistered = true; + {% for enum in module.enums %} + facelift::qRegisterMetaType<{{enum.fullyQualifiedCppType}}>(); + {% endfor %} + {% for struct in module.structs %} + qRegisterMetaType<{{struct.fullyQualifiedCppType}}>(); + {% endfor %} + #ifdef ENABLE_DESKTOP_TOOLS ModuleMonitor::registerTypes(); #endif diff --git a/codegen/facelift/templates/Service.template.h b/codegen/facelift/templates/Service.template.h index 3d15564a..21bd3e21 100644 --- a/codegen/facelift/templates/Service.template.h +++ b/codegen/facelift/templates/Service.template.h @@ -40,7 +40,6 @@ {{classExportDefines}} #include "FaceliftModel.h" -#include // Dependencies {% for type in interface.referencedTypes %} diff --git a/src/ipc/dbus/DBusIPCCommon.h b/src/ipc/dbus/DBusIPCCommon.h index 44302f28..676a0bdc 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -36,7 +36,6 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif -#include namespace facelift { namespace dbus { diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 8b2d6bac..97355801 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -116,7 +116,7 @@ void DBusIPCProxyBinder::onServiceNameKnown() for (const QString& signalEntry: m_serviceObject->getSignals()) { auto signalConnected = connection.connect(m_serviceName, objectPath(), m_interfaceName, signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); - Q_UNUSED(successPropertyChangeSignal); // TODO: check + Q_UNUSED(signalConnected) // TODO: check } m_busWatcher.addWatchedService(m_serviceName); diff --git a/src/ipc/ipc-common/IPCProxyModelProperty.h b/src/ipc/ipc-common/IPCProxyModelProperty.h index b51ec153..c0457ac1 100644 --- a/src/ipc/ipc-common/IPCProxyModelProperty.h +++ b/src/ipc/ipc-common/IPCProxyModelProperty.h @@ -57,54 +57,52 @@ class IPCProxyModelProperty : public facelift::ModelProperty { QListIterator argumentsIterator(msg.arguments()); const QString& modelPropertyName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + Q_ASSERT(!modelPropertyName.isEmpty()); + const QString& eventName = msg.member(); - if (!modelPropertyName.isEmpty()) { - const QString& eventName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + if (eventName == QStringLiteral("ModelUpdateEventDataChanged")) + { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); - if (eventName == QStringLiteral("ModelUpdateEventDataChanged")) - { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); - - int last = first + list.size() - 1; - for (int i = first; i <= last; ++i) { - m_cache.insert(i, list.at(i - first)); - } - emit this->dataChanged(first, last); - } - else if (eventName == QStringLiteral("ModelUpdateEventInsert")) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - emit this->beginInsertElements(first, last); - clear(); // TODO: insert elements in cache without clear() - emit this->endInsertElements(); - } - else if (eventName == QStringLiteral("ModelUpdateEventRemove")) - { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - emit this->beginRemoveElements(first, last); - m_cache.clear(); // TODO: remove elements from cache without clear() - emit this->endRemoveElements(); - } - else if (eventName == QStringLiteral("ModelUpdateEventMove")) { - int sourceFirstIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int sourceLastIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int destinationIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); - m_cache.clear(); // TODO: move elements in cache without clear() - emit this->endMoveElements(); - } - else if (eventName == QStringLiteral("ModelUpdateEventReset")) { - emit this->beginResetModel(); - int size = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - this->setSize(size); - clear(); - emit this->endResetModel(); - } - else { - qCWarning(LogIpc) << "Unhandled event for model property" << eventName; + int last = first + list.size() - 1; + for (int i = first; i <= last; ++i) { + m_cache.insert(i, list.at(i - first)); } + emit this->dataChanged(first, last); + } + else if (eventName == QStringLiteral("ModelUpdateEventInsert")) { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginInsertElements(first, last); + clear(); // TODO: insert elements in cache without clear() + emit this->endInsertElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventRemove")) + { + int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginRemoveElements(first, last); + m_cache.clear(); // TODO: remove elements from cache without clear() + emit this->endRemoveElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventMove")) { + int sourceFirstIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int sourceLastIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int destinationIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); + m_cache.clear(); // TODO: move elements in cache without clear() + emit this->endMoveElements(); + } + else if (eventName == QStringLiteral("ModelUpdateEventReset")) { + emit this->beginResetModel(); + int size = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + this->setSize(size); + clear(); + emit this->endResetModel(); + } + else { + qCWarning(LogIpc) << "Unhandled event for model property" << eventName; } } From 698e225a282054e8d74bfd04988998529b36f846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Wed, 16 Sep 2020 07:43:10 +0200 Subject: [PATCH 04/12] Standardize facelift dbus communication - Eliminate possible struct signature overflow by asserting the size and utilizing @serializable: true - Make the struct not directly dependent on QtDBus --- codegen/facelift/facelift-codegen.py | 4 + .../templates/IPCAdapter.template.cpp | 9 +++ .../templates/IPCProxyAdapter.template.cpp | 6 +- .../templates/IPCServiceAdapter.template.cpp | 1 - .../facelift/templates/Struct.template.cpp | 77 +++++++++++++++++++ codegen/facelift/templates/Struct.template.h | 46 ++--------- doc/page-annotations.h | 1 + src/ipc/dbus/DBusIPCProxyBinder.h | 36 +++++---- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 10 ++- src/ipc/ipc-common/CMakeLists.txt | 6 +- src/ipc/local/LocalIPC-serialization.h | 33 +++++--- src/ipc/local/LocalIPCProxyBinder.h | 8 +- src/ipc/local/LocalIPCServiceAdapterBase.h | 2 +- src/model/CMakeLists.txt | 8 +- src/model/FaceliftEnum.h | 37 +++++++++ tests/models/check_models.js | 1 + .../cpp/ModelInterfaceCppImplementation.h | 33 ++++++++ tests/models/interface/models.qface | 40 ++++++++++ 18 files changed, 278 insertions(+), 80 deletions(-) diff --git a/codegen/facelift/facelift-codegen.py b/codegen/facelift/facelift-codegen.py index ba7bc6bf..e35890a4 100755 --- a/codegen/facelift/facelift-codegen.py +++ b/codegen/facelift/facelift-codegen.py @@ -211,6 +211,9 @@ def isQMLImplementationEnabled(self): def isSerializable(self): return True if self.tags.get('serializable') else generateAll +def serializeOverIPC(self): + return True if self.tags.get('serializeOverIPC') else generateAll + def isQObjectWrapperEnabled(self): return True if self.tags.get('qml-component') else False @@ -309,6 +312,7 @@ def cppMethodArgumentType(self): setattr(qface.idl.domain.Struct, 'verifyStruct', property(verifyStruct)) setattr(qface.idl.domain.Struct, 'isSerializable', property(isSerializable)) +setattr(qface.idl.domain.Struct, 'serializeOverIPC', property(serializeOverIPC)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperEnabled', property(isQObjectWrapperEnabled)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperDeprecated', property(isQObjectWrapperDeprecated)) diff --git a/codegen/facelift/templates/IPCAdapter.template.cpp b/codegen/facelift/templates/IPCAdapter.template.cpp index 7a67e9f6..f94389cb 100644 --- a/codegen/facelift/templates/IPCAdapter.template.cpp +++ b/codegen/facelift/templates/IPCAdapter.template.cpp @@ -53,6 +53,8 @@ #include "{{property.fullyQualifiedPath}}{% if generateAsyncProxy %}Async{% endif %}IPCDBusAdapter.h" {% endfor %} +#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255 + {% for type in interface.referencedTypes %} {% if (not type.is_primitive) %} {% if (not type.is_model) %} @@ -109,6 +111,13 @@ struct {{interfaceName}}IPCAdapter::Impl { qDBusRegisterMetaType>(); {% if type.is_struct %} {{type.fullyQualifiedCppType}}::registerDBusTypes(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to byte array stream of the struct over dbus, but yet better rethink your structure!"); + {% endif %} + {% if type.nested.is_struct %} + {{type.nested.fullyQualifiedCppType}}::registerDBusTypes(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to binary array stream of the struct over dbus, but yet better rethink your structure!"); {% endif %} {% endif %} {% endif %} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 7f916eda..75be4c8f 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -37,7 +37,6 @@ #include "{{className}}.h" #include "FaceliftEnum.h" -#include "DBusIPCCommon.h" {{module.namespaceCppOpen}} @@ -94,6 +93,7 @@ void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) void {{className}}::handleSignals(InputIPCMessage& msg) { + Q_UNUSED(msg); {% for event in interface.signals %} if (msg.member() == QStringLiteral("{{event}}")) { QListIterator argumentsIterator(msg.arguments()); @@ -149,6 +149,7 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) { + {% if interface.properties %} QListIterator argumentsIterator(msg.arguments()); QString interfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QVariantMap()); @@ -167,6 +168,9 @@ void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) } {% endfor %} } + {% else %} + Q_UNUSED(msg); + {% endif %} } {% for property in interface.properties %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 37cf5743..41dee83a 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -36,7 +36,6 @@ {% set className = interfaceName + proxyTypeNameSuffix %} #include -#include "DBusIPCCommon.h" #include "{{className}}.h" {{module.namespaceCppOpen}} diff --git a/codegen/facelift/templates/Struct.template.cpp b/codegen/facelift/templates/Struct.template.cpp index 7fc2dbd2..15407b2c 100644 --- a/codegen/facelift/templates/Struct.template.cpp +++ b/codegen/facelift/templates/Struct.template.cpp @@ -36,7 +36,12 @@ ****************************************************************************/ #include "{{struct}}.h" +#ifdef DBUS_IPC_ENABLED +#include +#include +#endif #include "FaceliftConversion.h" +#include "FaceliftEnum.h" {{module.namespaceCppOpen}} @@ -126,5 +131,77 @@ QString {{struct.name}}::toString() const return toStringWithFields(CLASS_ID, FIELD_NAMES); } +#ifdef DBUS_IPC_ENABLED +void {{struct.name}}::registerDBusTypes() +{ + {% for field in struct.fields %} + {% if field.type.is_struct %} + {{field.type.cppType}}::registerDBusTypes(); + {% endif %} + {% if field.type.nested.is_struct %} + {{field.type.nested.cppType}}::registerDBusTypes(); + {% endif %} + {% if (not field.type.is_primitive and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} + qDBusRegisterMetaType<{{field.cppType}}>(); + {% endif %} + {% if (field.type.is_list or field.type.is_map) %} + {% if (not field.type.nested.is_primitive) %} + qDBusRegisterMetaType<{{field.cppType}}>(); + qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); + {% endif %} + {% endif %} + {% endfor %} +} +QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}) +{ + argument.beginStructure(); + {% if not struct.serializeOverIPC %} + {% for field in struct.fields %} + argument << {{struct.name|lower}}.m_{{field}}; + {% endfor -%} + {% else %} + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::WriteOnly); + dataStream << {{struct.name|lower}}; + argument << byteArray; + {% endif %} + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}) +{ + argument.beginStructure(); + {% if not struct.serializeOverIPC %} + {% for field in struct.fields %} + argument >> {{struct.name|lower}}.m_{{field}}; + {% endfor -%} + {% else %} + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::ReadOnly); + argument >> byteArray; + dataStream >> {{struct.name|lower}}; + {% endif %} + argument.endStructure(); + + return argument; +} + +QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ) +{ + {% for field in struct.fields %} + dataStream << {{struct.name|lower}}.m_{{field}}; + {% endfor %} + return dataStream; +} + +QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ) +{ + {% for field in struct.fields %} + dataStream >> {{struct.name|lower}}.m_{{field}}; + {% endfor %} + return dataStream; +} +#endif {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Struct.template.h b/codegen/facelift/templates/Struct.template.h index 3db17c53..4f0439e4 100644 --- a/codegen/facelift/templates/Struct.template.h +++ b/codegen/facelift/templates/Struct.template.h @@ -39,8 +39,6 @@ {{classExportDefines}} -#include -#include #include "Structure.h" #include "FaceliftQMLUtils.h" @@ -49,6 +47,7 @@ {{field.type.requiredInclude}} {% endfor %} +class QDBusArgument; {{module.namespaceCppOpen}} {% if struct.isQObjectWrapperEnabled %} @@ -89,23 +88,11 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< friend QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}); friend const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}); - static void registerDBusTypes() - { - {% for field in struct.fields %} - {% if field.type.is_struct %} - {{field.type.cppType}}::registerDBusTypes(); - {% endif %} - {% if (not field.type.is_primitive and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - {% endif %} - {% if (field.type.is_list or field.type.is_map) %} - {% if (not field.type.nested.is_primitive) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); - {% endif %} - {% endif %} - {% endfor %} - } + + friend QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ); + friend QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ); + + static void registerDBusTypes(); Q_INVOKABLE {{struct.fullyQualifiedCppType}} clone() const; @@ -149,27 +136,6 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {% endfor -%} }; -inline QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% for field in struct.fields %} - argument << {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - argument.endStructure(); - return argument; -} - -inline const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% for field in struct.fields %} - argument >> {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - argument.endStructure(); - - return argument; -} - {{module.namespaceCppClose}} inline QTextStream &operator <<(QTextStream &outStream, const {{struct.fullyQualifiedCppType}} &f) diff --git a/doc/page-annotations.h b/doc/page-annotations.h index 34f50d2c..334a8f3c 100644 --- a/doc/page-annotations.h +++ b/doc/page-annotations.h @@ -39,6 +39,7 @@ The following annotations can be used in structure definitions: |Annotation | Description | Supported over IPC | |-------------------------------|-------------------------------------------------------------|--------------------| +|\@serializeOverIPC: true | Treat the whole structure as byte array over IPC reducing structure signature only to DBUS Type BYTE | Yes | |\@serializable: true | Adds serialization/deserialization capability to the structure | Yes | |\@qml-component: true | Enables the creation and registration of a creatable QML component for the corresponding structure | Yes | diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index ee6bab98..85ca2554 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -100,16 +100,16 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendSetterCall(const QString& property, const PropertyType &value); template - DBusIPCMessage sendMethodCall(const char *methodName, const Args & ... args) const; + DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args) const; template - void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args); + void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args); + void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - QList sendMethodCallWithReturn(const char *methodName, const Args & ... args) const; + QList sendMethodCallWithReturn(const char *methodName, Args && ... args) const; void setHandler(DBusRequestHandler *handler); @@ -179,11 +179,13 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase template -inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, const Args & ... args) const +inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) const { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; auto replyMessage = this->call(msg); if (replyMessage.isErrorMessage()) { onServerNotAvailableError(methodName); @@ -192,11 +194,13 @@ inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, } template -inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args) +inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args) { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { @@ -211,19 +215,21 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face } template -inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args) +inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args) { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; asyncCall(msg, this, [answer](DBusIPCMessage &msg) { - Q_UNUSED(msg); + Q_UNUSED(msg) answer(); }); } template -inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, const Args & ... args) const +inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) const { DBusIPCMessage msg = sendMethodCall(methodName, args ...); QList ret; diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index c71bde01..f23f7059 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -93,7 +93,7 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda inline void sendPropertiesChanged(const QString& property , const Value & value); template - void sendSignal(const QString& signalName, const Args & ... args); + void sendSignal(const QString& signalName, Args && ... args); template void sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue); @@ -224,11 +224,13 @@ inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& prop } template -inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, const Args & ... args) +inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Args && ... args) { DBusIPCMessage signal(objectPath(), interfaceName(), signalName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [this, &signal](const auto &v){signal << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(signal << QVariant::fromValue(std::forward(args))), 0)... + }; this->send(signal); } diff --git a/src/ipc/ipc-common/CMakeLists.txt b/src/ipc/ipc-common/CMakeLists.txt index 0a8287e7..3b59cfbc 100644 --- a/src/ipc/ipc-common/CMakeLists.txt +++ b/src/ipc/ipc-common/CMakeLists.txt @@ -1,3 +1,4 @@ +find_package(Qt5DBus REQUIRED) facelift_add_library(FaceliftIPCCommonLib SOURCES @@ -34,6 +35,9 @@ facelift_add_library(FaceliftIPCCommonLib IPCAttachedPropertyFactory.h IPCServiceAdapter.h Registry.h - LINK_LIBRARIES FaceliftModelLib FaceliftCommonLib + LINK_LIBRARIES + FaceliftModelLib + FaceliftCommonLib + Qt5::DBus MONOLITHIC_SUPPORTED ) diff --git a/src/ipc/local/LocalIPC-serialization.h b/src/ipc/local/LocalIPC-serialization.h index c28a3b85..3a3c7d28 100644 --- a/src/ipc/local/LocalIPC-serialization.h +++ b/src/ipc/local/LocalIPC-serialization.h @@ -47,11 +47,13 @@ namespace facelift { namespace local { template -inline LocalIPCMessage LocalIPCProxyBinder::sendMethodCall(const char *methodName, const Args & ... args) const +inline LocalIPCMessage LocalIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) const { LocalIPCMessage msg(methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { onServerNotAvailableError(methodName); @@ -60,11 +62,13 @@ inline LocalIPCMessage LocalIPCProxyBinder::sendMethodCall(const char *methodNam } template -inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args) +inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args) { LocalIPCMessage msg(methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; asyncCall(msg, this, [this, answer](LocalIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { @@ -77,11 +81,13 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac } template -inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args) +inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args) { LocalIPCMessage msg(methodName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [&msg](const auto &v){msg << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(msg << QVariant::fromValue(std::forward(args))), 0)... + }; asyncCall(msg, this, [answer](LocalIPCMessage &msg) { Q_UNUSED(msg); answer(); @@ -111,11 +117,14 @@ inline void LocalIPCProxyBinder::sendSetterCall(const QString& property, const P template -inline void LocalIPCServiceAdapterBase::sendSignal(const QString& signalName, const Args & ... args) +inline void LocalIPCServiceAdapterBase::sendSignal(const QString& signalName, Args && ... args) { LocalIPCMessage signal(signalName); - auto argTuple = std::make_tuple(args ...); - for_each_in_tuple(argTuple, [this, &signal](const auto &v){signal << QVariant::fromValue(v);}); + using expander = int[]; + (void)expander{0, + (void(signal << QVariant::fromValue(std::forward(args))), 0)... + }; + this->send(signal); } diff --git a/src/ipc/local/LocalIPCProxyBinder.h b/src/ipc/local/LocalIPCProxyBinder.h index 39704733..603dcb34 100644 --- a/src/ipc/local/LocalIPCProxyBinder.h +++ b/src/ipc/local/LocalIPCProxyBinder.h @@ -85,16 +85,16 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCProxyBinder : public IPCProxyBinderBase void sendSetterCall(const QString &property, const PropertyType &value); template - LocalIPCMessage sendMethodCall(const char *methodName, const Args & ... args) const; + LocalIPCMessage sendMethodCall(const char *methodName, Args && ... args) const; template - void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args); + void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, const Args & ... args); + void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - void sendMethodCallWithReturn(const char *methodName, ReturnType &returnValue, const Args & ... args) const; + void sendMethodCallWithReturn(const char *methodName, ReturnType &returnValue, Args && ... args) const; LocalIPCMessage call(LocalIPCMessage &message) const; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 0cb0b176..8ec9e19a 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -67,7 +67,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA inline void sendPropertiesChanged(const QString& property , const Value & value); template - void sendSignal(const QString& signalName, const Args & ... args); + void sendSignal(const QString& signalName, Args && ... args); template void sendAsyncCallAnswer(LocalIPCMessage &replyMessage, const ReturnType returnValue); diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index d14ff1aa..65325977 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -1,4 +1,10 @@ +set(QtDBusDependency "") +if(FACELIFT_DBUS_IPC_ENABLED) +find_package(Qt5DBus REQUIRED) +set(QtDBusDependency "Qt5::DBus") +endif() + facelift_add_library(FaceliftModelLib SOURCES StructureBase.cpp @@ -81,7 +87,7 @@ facelift_add_library(FaceliftModelLib LINK_LIBRARIES Qt5::Qml Qt5::Quick - Qt5::DBus + ${QtDBusDependency} FaceliftCommonLib MONOLITHIC_SUPPORTED ) diff --git a/src/model/FaceliftEnum.h b/src/model/FaceliftEnum.h index 2d46dff6..61d584e0 100644 --- a/src/model/FaceliftEnum.h +++ b/src/model/FaceliftEnum.h @@ -39,6 +39,8 @@ #include "FaceliftCommon.h" #include #include +#include +#ifdef DBUS_IPC_ENABLED #include template @@ -80,6 +82,41 @@ const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) { return QDBusEnumMarshal::unmarshal(argument, source); } +#endif + +template +class QDataStreamMarshal; + +template +class QDataStreamMarshal::value>::type> +{ +public: + static QDataStream& marshal(QDataStream &dataStream, const T& source) + { + dataStream << static_cast(source); + return dataStream; + } + + static const QDataStream& unmarshal(QDataStream &dataStream, T &source) + { + int value; + dataStream >> value; + source = static_cast(value); + return dataStream; + } +}; + +template +inline QDataStream& operator<<(QDataStream &dataStream, const T& source) +{ + return QDataStreamMarshal::marshal(dataStream, source); +} + +template +inline const QDataStream& operator>>(QDataStream &dataStream, T &source) +{ + return QDataStreamMarshal::unmarshal(dataStream, source); +} namespace facelift { diff --git a/tests/models/check_models.js b/tests/models/check_models.js index 901db31a..c8dce67a 100644 --- a/tests/models/check_models.js +++ b/tests/models/check_models.js @@ -43,6 +43,7 @@ function checkInit() tryVerify(function() { return api.ready; }); verify(api.theModel); compare(api.theModel.rowCount(), 100); + compare(api.oversizedStruct.theKiller.anotherSecondLevel.firstLevel.someOtherString, "someOtherString"); for(var i = 0; i < api.theModel.rowCount(); ++i) { compare(getData(i).name, "entry " + i); compare(getData(i).enabled, !(i%2)); diff --git a/tests/models/impl/cpp/ModelInterfaceCppImplementation.h b/tests/models/impl/cpp/ModelInterfaceCppImplementation.h index 0a153441..b916a36d 100644 --- a/tests/models/impl/cpp/ModelInterfaceCppImplementation.h +++ b/tests/models/impl/cpp/ModelInterfaceCppImplementation.h @@ -48,6 +48,34 @@ class ModelInterfaceImplementation : public ModelInterfaceImplementationBase m_items.append(i); m_nextAvailableID = i; + FirstLevel firstLevel; + firstLevel.setsomeString("someString"); + firstLevel.setsomeInt(10); + firstLevel.setsomeBool(true); + firstLevel.setsomeOtherString("someOtherString"); + firstLevel.setsomeOtherInt(20); + firstLevel.setsomeOtherBool(true); + SecondLevel secondLevel; + secondLevel.setfirstLevel(firstLevel); + secondLevel.setanotherfirstLevel(firstLevel); + secondLevel.setyetAnotherFirstLevel(firstLevel); + ThirdLevel thirdLevel; + thirdLevel.setsecondLevel(secondLevel); + thirdLevel.setanotherSecondLevel(secondLevel); + thirdLevel.setyetAnotherSecondLevel(secondLevel); + + HugeStruct hugeStruct; + hugeStruct.setthirdLevel(thirdLevel); + hugeStruct.setanotherThirdLevel(thirdLevel); + hugeStruct.setyetAnotherThirdLevel(thirdLevel); + m_hugeStruct.setValue(hugeStruct); + + OversizedStruct oversizedStruct; + oversizedStruct.setthirdLevel(thirdLevel); + oversizedStruct.setanotherThirdLevel(thirdLevel); + oversizedStruct.setyetAnotherThirdLevel(thirdLevel); + oversizedStruct.settheKiller(thirdLevel); + m_oversizedStruct.setValue(oversizedStruct); m_theModel.reset(m_items.size(), std::bind(&ModelInterfaceImplementation::getItem, this, std::placeholders::_1)); @@ -93,6 +121,11 @@ class ModelInterfaceImplementation : public ModelInterfaceImplementationBase emit m_theModel.dataChanged(first, last); } + HugeStruct hungryBeast(const tests::models::HugeStruct& hugeStruct) override + { + return hugeStruct; + } + private: QVector m_items; int m_nextAvailableID = 0; diff --git a/tests/models/interface/models.qface b/tests/models/interface/models.qface index e4ffddd6..c183c520 100644 --- a/tests/models/interface/models.qface +++ b/tests/models/interface/models.qface @@ -42,4 +42,44 @@ interface ModelInterface { void deleteModelItems(int first, int last); void insertNewModelItems(int first, int last); void renameModelItem(int first, int last, int serial); + + OversizedStruct oversizedStruct; + HugeStruct hugeStruct; + HugeStruct hungryBeast(HugeStruct hugeStruct); +} + + +struct FirstLevel { +string someString; +int someInt; +bool someBool; +string someOtherString; +int someOtherInt; +bool someOtherBool; +} + +struct SecondLevel { +FirstLevel firstLevel; +FirstLevel anotherfirstLevel; +FirstLevel yetAnotherFirstLevel; +} + +struct ThirdLevel { +SecondLevel secondLevel; +SecondLevel anotherSecondLevel; +SecondLevel yetAnotherSecondLevel; +} + +struct HugeStruct { + ThirdLevel thirdLevel; + ThirdLevel anotherThirdLevel; + ThirdLevel yetAnotherThirdLevel; +} + +@serializeOverIPC: true +struct OversizedStruct { +ThirdLevel thirdLevel; +ThirdLevel anotherThirdLevel; +ThirdLevel yetAnotherThirdLevel; +ThirdLevel theKiller; } From 2cf600dde78105c3a8d684154abe3c072aed6580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Sun, 20 Sep 2020 11:14:30 +0200 Subject: [PATCH 05/12] standardize_dbus communication fix conversion of enum to int Use workaround since Qt doesn't allow regsitering custom types on dbus as built-in types --- .../templates/IPCAdapter.template.cpp | 2 + .../facelift/templates/IPCProxy.template.cpp | 2 + .../facelift/templates/Struct.template.cpp | 4 +- src/ipc/dbus/DBusIPCProxyBinder.h | 61 +++++++++++++++---- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 27 +++++++- src/ipc/ipc-common/IPCServiceAdapterBase.h | 20 +++++- src/ipc/local/LocalIPCServiceAdapterBase.h | 12 ++-- src/model/FaceliftEnum.h | 12 +--- 8 files changed, 106 insertions(+), 34 deletions(-) diff --git a/codegen/facelift/templates/IPCAdapter.template.cpp b/codegen/facelift/templates/IPCAdapter.template.cpp index f94389cb..e7dfd617 100644 --- a/codegen/facelift/templates/IPCAdapter.template.cpp +++ b/codegen/facelift/templates/IPCAdapter.template.cpp @@ -104,6 +104,7 @@ struct {{interfaceName}}IPCAdapter::Impl { #ifdef DBUS_IPC_ENABLED {% for type in interface.referencedTypes %} {% if (not type.is_primitive) %} + {% if (not type.is_enum) %} {% if (not type.is_model) %} {% if (not type.is_interface) %} qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); @@ -122,6 +123,7 @@ struct {{interfaceName}}IPCAdapter::Impl { {% endif %} {% endif %} {% endif %} + {% endif %} {% endfor %} #endif } diff --git a/codegen/facelift/templates/IPCProxy.template.cpp b/codegen/facelift/templates/IPCProxy.template.cpp index bf98e9ba..c9178172 100644 --- a/codegen/facelift/templates/IPCProxy.template.cpp +++ b/codegen/facelift/templates/IPCProxy.template.cpp @@ -93,6 +93,7 @@ struct {{className}}::Impl { #ifdef DBUS_IPC_ENABLED {% for type in interface.referencedTypes %} {% if (not type.is_primitive) %} + {% if (not type.is_enum) %} {% if (not type.is_model) %} {% if (not type.is_interface) %} qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); @@ -101,6 +102,7 @@ struct {{className}}::Impl { {% endif %} {% endif %} {% endif %} + {% endif %} {% endfor %} #endif diff --git a/codegen/facelift/templates/Struct.template.cpp b/codegen/facelift/templates/Struct.template.cpp index 15407b2c..60dc0e05 100644 --- a/codegen/facelift/templates/Struct.template.cpp +++ b/codegen/facelift/templates/Struct.template.cpp @@ -141,11 +141,11 @@ void {{struct.name}}::registerDBusTypes() {% if field.type.nested.is_struct %} {{field.type.nested.cppType}}::registerDBusTypes(); {% endif %} - {% if (not field.type.is_primitive and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} + {% if (not field.type.is_primitive and not field.type.is_enum and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} qDBusRegisterMetaType<{{field.cppType}}>(); {% endif %} {% if (field.type.is_list or field.type.is_map) %} - {% if (not field.type.nested.is_primitive) %} + {% if (not field.type.nested.is_primitive) or (not field.type.nested.is_enum) %} qDBusRegisterMetaType<{{field.cppType}}>(); qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); {% endif %} diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index 85ca2554..3e52e732 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -100,7 +100,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendSetterCall(const QString& property, const PropertyType &value); template - DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args) const; + DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args); template void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); @@ -109,7 +109,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - QList sendMethodCallWithReturn(const char *methodName, Args && ... args) const; + QList sendMethodCallWithReturn(const char *methodName, Args && ... args); void setHandler(DBusRequestHandler *handler); @@ -124,23 +124,30 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase } template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(QVariant::fromValue(value)); + QVariant castToVariant(const T& value) { + return castToVariantSpecialized(HelperType(), value); } - QDBusVariant castToDBusVariant(const QList& value) { - return QDBusVariant(QVariant::fromValue(QStringList(value))); // workaround to use QList since its signature matches the QStringList + template + QDBusVariant castToDBusVariant(const T& value) { + return QDBusVariant(castToVariant(value)); } + private: void checkRegistry(); template struct HelperType { }; - template::value, int> = 0> + template::value && !std::is_enum::value, int> = 0> T castFromVariantSpecialized(HelperType, const QVariant& value) { return qdbus_cast(value); } + template::value && std::is_enum::value, int> = 0> + T castFromVariantSpecialized(HelperType, const QVariant& value) { + return static_cast(qdbus_cast(value)); + } + QList castFromVariantSpecialized(HelperType>, const QVariant& value) { return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList } @@ -170,6 +177,34 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase return ret; } + template::value && !std::is_enum::value, int> = 0> + QVariant castToVariantSpecialized(HelperType, const T& value) { + return QVariant::fromValue(value); + } + + QVariant castToVariantSpecialized(HelperType>, const QList& value) { + return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList + } + + template::value && std::is_enum::value, int> = 0> + QVariant castToVariantSpecialized(HelperType, const T& value) { + return QVariant::fromValue(static_cast(value)); + } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType>, const QList& value) { + return QVariant::fromValue(static_cast>(value)); + } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QMap ret; + for (const QString& key: value.keys()) { + ret[key] = static_cast(value[key]); + } + return QVariant::fromValue(ret); + } + QString m_interfaceName; QDBusServiceWatcher m_busWatcher; DBusRequestHandler *m_serviceObject = nullptr; @@ -179,12 +214,12 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase template -inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) const +inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << QVariant::fromValue(std::forward(args))), 0)... + (void(msg << castToVariant(std::forward(args))), 0)... }; auto replyMessage = this->call(msg); if (replyMessage.isErrorMessage()) { @@ -199,7 +234,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << QVariant::fromValue(std::forward(args))), 0)... + (void(msg << castToVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; @@ -220,7 +255,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << QVariant::fromValue(std::forward(args))), 0)... + (void(msg << castToVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [answer](DBusIPCMessage &msg) { Q_UNUSED(msg) @@ -229,7 +264,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face } template -inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) const +inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) { DBusIPCMessage msg = sendMethodCall(methodName, args ...); QList ret; @@ -244,7 +279,7 @@ inline void DBusIPCProxyBinder::sendSetterCall(const QString &property, const Pr { DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY); msg << QVariant::fromValue(m_interfaceName); - msg << QVariant::fromValue(property); + msg << castToVariant(property); msg << QVariant::fromValue(castToDBusVariant(value)); if (isSynchronous()) { auto replyMessage = call(msg); diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index f23f7059..7a7ef5b2 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -177,11 +177,16 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda return qvariant_cast(qdbus_cast(value).variant()); } - template::value, int> = 0> + template::value && !std::is_enum::value, int> = 0> QVariant castToVariantSpecialized(HelperType, const T& value) { return QVariant::fromValue(value); } + template::value && std::is_enum::value, int> = 0> + QVariant castToVariantSpecialized(HelperType, const T& value) { + return QVariant::fromValue(static_cast(value)); + } + QVariant castToVariantSpecialized(HelperType>, const QList& value) { return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } @@ -212,6 +217,22 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } return QVariant::fromValue(objectPathesMap); } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QList ret; + std::transform(value.begin(), value.end(), std::back_inserter(ret), [](const T& entry){return static_cast(entry);}); + return QVariant::fromValue(ret); + } + + template::value, int> = 0> + QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QMap ret; + for (const QString& key: value.keys()) { + ret[key] = static_cast(value[key]); + } + return QVariant::fromValue(ret); + } }; template @@ -229,7 +250,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg DBusIPCMessage signal(objectPath(), interfaceName(), signalName); using expander = int[]; (void)expander{0, - (void(signal << QVariant::fromValue(std::forward(args))), 0)... + (void(signal << castToVariant(std::forward(args))), 0)... }; this->send(signal); } @@ -237,7 +258,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg template inline void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue) { - replyMessage << QVariant::fromValue(returnValue); + replyMessage << castToVariant(returnValue); send(replyMessage); } diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index c8b95ca5..436e0985 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -118,12 +118,18 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject } private: template struct HelperType { }; - template::value, int> = 0> + template::value && !std::is_enum::value, int> = 0> const char* typeToSignatureSpecialized(HelperType) const { return QDBusMetaType::typeToSignature(qMetaTypeId()); } + template::value && std::is_enum::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + template::value, int> = 0> inline const char* typeToSignatureSpecialized(HelperType) const { @@ -147,6 +153,18 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject return QDBusMetaType::typeToSignature(qMetaTypeId>()); } + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + QList > m_subAdapters; QString m_objectPath; QString m_interfaceName; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 8ec9e19a..e8635552 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -114,7 +114,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA return qvariant_cast(qvariant_cast(value).variant()); } - template::value, int> = 0> + template::value && !std::is_enum::value, int> = 0> QVariant castToVariant(const T& value) { return QVariant::fromValue(value); } @@ -123,6 +123,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } + template::value && std::is_enum::value, int> = 0> + QVariant castToVariant(const T& value) { + return QVariant::fromValue(static_cast(value)); + } + template::value, int> = 0> QVariant castToVariant(const T& value) { DBusObjectPath dbusObjectPath; @@ -155,12 +160,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA return QDBusVariant(castToVariant(value)); } - QDBusVariant castToDBusVariant(const QList& value) { - return QDBusVariant(castToVariant(value)); - } - protected: - std::unique_ptr m_pendingOutgoingMessage; QString m_introspectionData; QString m_serviceName; diff --git a/src/model/FaceliftEnum.h b/src/model/FaceliftEnum.h index 61d584e0..c581ff20 100644 --- a/src/model/FaceliftEnum.h +++ b/src/model/FaceliftEnum.h @@ -52,21 +52,15 @@ class QDBusEnumMarshal::value>::type> public: static QDBusArgument& marshal(QDBusArgument &argument, const T& source) { - argument.beginStructure(); argument << static_cast(source); - argument.endStructure(); return argument; } static const QDBusArgument& unmarshal(const QDBusArgument &argument, T &source) { - int a; - argument.beginStructure(); - argument >> a; - argument.endStructure(); - - source = static_cast(a); - + int tmp; + argument >> tmp; + source = static_cast(tmp); return argument; } }; From a3e6151418ce168365bbc50063aff39b45368998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Sun, 20 Sep 2020 22:44:54 +0200 Subject: [PATCH 06/12] Fix consistency of the interface in case of multiple property change --- .../IPCDBusServiceAdapter.template.h | 4 ++++ .../templates/IPCProxyAdapter.template.cpp | 10 +++++++- .../templates/IPCServiceAdapter.template.cpp | 23 ++++++++++++++++--- .../templates/IPCServiceAdapter.template.h | 4 ++++ src/ipc/dbus/IPCDBusServiceAdapterBase.h | 9 +++----- src/ipc/local/LocalIPCServiceAdapterBase.h | 8 +++---- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index 8ab9b6f6..feffd8a6 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -86,6 +86,8 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; + QMap changedProperties(); + void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; @@ -110,6 +112,8 @@ class {{classExport}} {{className}}: public {{baseClass}} {% for property in interface.properties %} {% if property.type.is_model %} ::facelift::IPCAdapterModelPropertyHandler m_{{property.name}}Handler; + {% else %} + {{property.interfaceCppType}} m_previous{{property.name}} {}; {% endif %} {% endfor %} }; diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 75be4c8f..69bf72c9 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -164,7 +164,15 @@ void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) {% else %} m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); {% endif %} - emit {{property.name}}Changed(); // trust the propertiesChanged signal and emit without checking + } + {% endfor %} + } + for (const QString &propertyName: changedProperties.keys()) { + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if not property.type.is_model %} + emit {{property.name}}Changed(); + {% endif %} } {% endfor %} } diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 41dee83a..4f7ecbbe 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -150,7 +150,8 @@ void {{className}}::connectSignals() {% for property in interface.properties %} {% if property.type.is_model %} m_{{property.name}}Handler.connectModel(QStringLiteral("{{property.name}}"), theService->{{property.name}}()); - {% elif property.type.is_interface %} + {% else %} + m_previous{{property.name}} = theService->{{property.name}}(); {% endif %} {% endfor %} @@ -158,13 +159,13 @@ void {{className}}::connectSignals() {% for property in interface.properties %} {% if (not property.type.is_model) %} QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this, theService] () { - this->sendPropertiesChanged("{{property.name}}", theService->{{property.name}}()); + this->sendPropertiesChanged(changedProperties()); }); {% endif %} {% endfor %} QObject::connect(theService, &ServiceType::readyChanged, this, [this, theService] () { - this->sendPropertiesChanged("ready", theService->ready()); + this->sendPropertiesChanged(QMap{ {"ready", castToDBusVariant(theService->ready())} }); }); // Signals @@ -173,6 +174,22 @@ void {{className}}::connectSignals() {% endfor %} } +QMap {{className}}::changedProperties() +{ + QMap ret; + auto theService = service(); + Q_UNUSED(theService); + {% for property in interface.properties %} + {% if not property.type.is_model %} + if (m_previous{{property.name}} != theService->{{property.name}}()) { + ret[QStringLiteral("{{property.name}}")] = castToDBusVariant(theService->{{property.name}}()); + m_previous{{property.name}} = theService->{{property.name}}(); + } + {% endif %} + {% endfor %} + return ret; +} + void {{className}}::marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) { QListIterator argumentsIterator(arguments); diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index b15404a2..d2f0bc0b 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -82,6 +82,8 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; + QMap changedProperties(); + void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; @@ -106,6 +108,8 @@ class {{classExport}} {{className}}: public {{baseClass}} {% for property in interface.properties %} {% if property.type.is_model %} ::facelift::IPCAdapterModelPropertyHandler m_{{property.name}}Handler; + {% else %} + {{property.interfaceCppType}} m_previous{{property.name}} {}; {% endif %} {% endfor %} }; diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 7a7ef5b2..740874e9 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -88,9 +88,7 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool handleMessage(const QDBusMessage &dbusMsg); - - template - inline void sendPropertiesChanged(const QString& property , const Value & value); + inline void sendPropertiesChanged(const QMap& changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -235,12 +233,11 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } }; -template -inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QString& property, const Value &value) +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties) { DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariant::fromValue(QMap{{property, castToDBusVariant(value)}}); + reply << QVariant::fromValue(changedProperties); this->send(reply); } diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index e8635552..0d9f7e43 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -63,8 +63,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA IPCHandlingResult handleMessage(LocalIPCMessage &message); - template - inline void sendPropertiesChanged(const QString& property , const Value & value); + inline void sendPropertiesChanged(const QMap &changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -170,12 +169,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA bool m_alreadyInitialized = false; }; -template -inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QString& property , const Value & value) +inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties ) { LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariant::fromValue(QMap{{property, castToDBusVariant(value)}}); + reply << QVariant::fromValue(changedProperties); this->send(reply); } From 10557c39931c72ee41f51db9c96a1d7bacd40d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Sun, 20 Sep 2020 23:09:14 +0200 Subject: [PATCH 07/12] Fix review comments --- codegen/facelift/facelift-codegen.py | 23 +- .../templates/IPCAdapter.template.cpp | 46 --- .../IPCDBusServiceAdapter.template.h | 9 +- .../facelift/templates/IPCProxy.template.cpp | 25 -- .../templates/IPCProxyAdapter.template.cpp | 100 ++++--- .../templates/IPCProxyAdapter.template.h | 5 +- .../templates/IPCServiceAdapter.template.cpp | 163 +++++------ .../templates/IPCServiceAdapter.template.h | 9 +- .../templates/ImplementationBase.template.h | 1 - .../facelift/templates/Service.template.cpp | 1 - .../facelift/templates/Struct.template.cpp | 84 +----- codegen/facelift/templates/Struct.template.h | 14 +- doc/page-annotations.h | 2 +- src/ipc/dbus/CMakeLists.txt | 1 + src/ipc/dbus/DBusIPCCommon.h | 13 +- src/ipc/dbus/DBusIPCMessage.cpp | 13 +- src/ipc/dbus/DBusIPCMessage.h | 2 +- src/ipc/dbus/DBusIPCProxy.h | 9 +- src/ipc/dbus/DBusIPCProxyBinder.cpp | 13 +- src/ipc/dbus/DBusIPCProxyBinder.h | 115 ++++---- src/ipc/dbus/DBusObjectRegistry.cpp | 2 +- src/ipc/dbus/DBusRequestHandler.h | 4 +- src/ipc/dbus/FaceliftDBusMarshaller.h | 269 ++++++++++++++++++ src/ipc/dbus/IPCDBusServiceAdapter.h | 56 +++- src/ipc/dbus/IPCDBusServiceAdapterBase.cpp | 50 +++- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 111 ++++---- src/ipc/ipc-common/CMakeLists.txt | 5 +- src/ipc/ipc-common/DBusSignatureHelper.cpp | 92 ++++++ src/ipc/ipc-common/DBusSignatureHelper.h | 48 ++++ .../IPCAdapterModelPropertyHandler.h | 20 +- src/ipc/ipc-common/IPCProxyModelProperty.h | 46 +-- src/ipc/ipc-common/IPCServiceAdapterBase.h | 57 ---- src/ipc/ipc-common/ipc-common.h | 12 +- src/ipc/local/FaceliftIPCCommon.h | 11 +- src/ipc/local/LocalIPC-serialization.h | 7 +- src/ipc/local/LocalIPCProxy.h | 43 ++- src/ipc/local/LocalIPCProxyBase.h | 1 - src/ipc/local/LocalIPCProxyBinder.cpp | 13 +- src/ipc/local/LocalIPCRequestHandler.h | 4 +- src/ipc/local/LocalIPCServiceAdapter.h | 6 + src/ipc/local/LocalIPCServiceAdapterBase.cpp | 25 +- src/ipc/local/LocalIPCServiceAdapterBase.h | 62 ++-- src/model/CMakeLists.txt | 7 - src/model/FaceliftEnum.h | 72 ----- tests/combined/check_combined.js | 11 + .../impl/cpp/CombinedTestsCppImplementation.h | 19 ++ .../qml/CombinedTestsQmlImplementation.qml | 7 + tests/combined/interface/another.qface | 37 +++ tests/combined/interface/combined.qface | 55 +++- tests/combined/interface/other.qface | 3 + tests/models/interface/models.qface | 2 +- tests/objectregistry/client.cpp | 2 +- 52 files changed, 1073 insertions(+), 734 deletions(-) create mode 100644 src/ipc/dbus/FaceliftDBusMarshaller.h create mode 100644 src/ipc/ipc-common/DBusSignatureHelper.cpp create mode 100644 src/ipc/ipc-common/DBusSignatureHelper.h create mode 100644 tests/combined/interface/another.qface diff --git a/codegen/facelift/facelift-codegen.py b/codegen/facelift/facelift-codegen.py index e35890a4..7e5e28ab 100755 --- a/codegen/facelift/facelift-codegen.py +++ b/codegen/facelift/facelift-codegen.py @@ -132,7 +132,7 @@ def requiredIncludeFromType(symbol, suffix): def insertUniqueType(symbol, unique_types): type = symbol.type.nested if symbol.type.nested else symbol.type - if type not in (t.name for t in unique_types): + if type.name not in (t.name for t in unique_types): unique_types.append(type) def referencedTypes(self): @@ -149,21 +149,23 @@ def referencedTypes(self): insertUniqueType(param, types) return types -def appendTypeIfStructure(symbol, list): +def appendTypeIfStructureAndUnique(symbol, unique_list): type = symbol.type.nested if symbol.type.nested else symbol.type - if type.is_struct: - list.append(type) + if type.is_struct and type.name not in (t.name for t in unique_list): + unique_list.append(type) def referencedStructureTypes(self): interfaces = [] for property in self.properties: - appendTypeIfStructure(property, interfaces) + appendTypeIfStructureAndUnique(property, interfaces) for m in self.operations: for param in m.parameters: - appendTypeIfStructure(param, interfaces) + appendTypeIfStructureAndUnique(param, interfaces) + if m.hasReturnValue: + appendTypeIfStructureAndUnique(m.type, interfaces) for m in self.signals: for param in m.parameters: - appendTypeIfStructure(param, interfaces) + appendTypeIfStructureAndUnique(param, interfaces) return interfaces def appendTypeIfInterface(symbol, list): @@ -211,8 +213,8 @@ def isQMLImplementationEnabled(self): def isSerializable(self): return True if self.tags.get('serializable') else generateAll -def serializeOverIPC(self): - return True if self.tags.get('serializeOverIPC') else generateAll +def toByteArrayOverDBus(self): + return True if self.tags.get('toByteArrayOverDBus') else generateAll def isQObjectWrapperEnabled(self): return True if self.tags.get('qml-component') else False @@ -312,7 +314,7 @@ def cppMethodArgumentType(self): setattr(qface.idl.domain.Struct, 'verifyStruct', property(verifyStruct)) setattr(qface.idl.domain.Struct, 'isSerializable', property(isSerializable)) -setattr(qface.idl.domain.Struct, 'serializeOverIPC', property(serializeOverIPC)) +setattr(qface.idl.domain.Struct, 'toByteArrayOverDBus', property(toByteArrayOverDBus)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperEnabled', property(isQObjectWrapperEnabled)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperDeprecated', property(isQObjectWrapperDeprecated)) @@ -371,6 +373,7 @@ def run_generation(input, output, dependency, libraryName, all): generateFile(generator, 'module/{{path}}/Module.cpp', 'Module.template.cpp', ctx, libraryName, "") generateFile(generator, 'ipc/{{path}}/ModuleIPC.h', 'ModuleIPC.template.h', ctx, libraryName, "") generateFile(generator, 'ipc/{{path}}/ModuleIPC.cpp', 'ModuleIPC.template.cpp', ctx, libraryName, "") + for interface in module.interfaces: log.debug('process interface %s' % interface) ctx.update({'interface': interface}) diff --git a/codegen/facelift/templates/IPCAdapter.template.cpp b/codegen/facelift/templates/IPCAdapter.template.cpp index e7dfd617..331dacf7 100644 --- a/codegen/facelift/templates/IPCAdapter.template.cpp +++ b/codegen/facelift/templates/IPCAdapter.template.cpp @@ -39,31 +39,10 @@ #include "InterfaceManager.h" #ifdef DBUS_IPC_ENABLED -#include #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusAdapter.h" -{% for struct in module.structs %} -#include "{{struct.fullyQualifiedPath}}.h" -{% endfor %} - -{% for enum in module.enums %} -#include "{{enum.fullyQualifiedPath}}.h" -{% endfor %} - {% for property in interface.referencedInterfaceTypes %} #include "{{property.fullyQualifiedPath}}{% if generateAsyncProxy %}Async{% endif %}IPCDBusAdapter.h" {% endfor %} - -#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255 - -{% for type in interface.referencedTypes %} -{% if (not type.is_primitive) %} -{% if (not type.is_model) %} -{% if (not type.is_interface) %} -{{type.requiredInclude}} -{% endif %} -{% endif %} -{% endif %} -{% endfor %} #endif {{module.namespaceCppOpen}} @@ -101,31 +80,6 @@ struct {{interfaceName}}IPCAdapter::Impl { {{interfaceName}}IPCAdapter::{{interfaceName}}IPCAdapter(QObject* parent) : BaseType(facelift::InterfaceManager::instance(), parent) { -#ifdef DBUS_IPC_ENABLED - {% for type in interface.referencedTypes %} - {% if (not type.is_primitive) %} - {% if (not type.is_enum) %} - {% if (not type.is_model) %} - {% if (not type.is_interface) %} - qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); - qDBusRegisterMetaType>(); - qDBusRegisterMetaType>(); - {% if type.is_struct %} - {{type.fullyQualifiedCppType}}::registerDBusTypes(); - Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", - "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to byte array stream of the struct over dbus, but yet better rethink your structure!"); - {% endif %} - {% if type.nested.is_struct %} - {{type.nested.fullyQualifiedCppType}}::registerDBusTypes(); - Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", - "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to binary array stream of the struct over dbus, but yet better rethink your structure!"); - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} -#endif } {{interfaceName}}IPCAdapter::~{{interfaceName}}IPCAdapter() { diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index feffd8a6..3d5f0cf5 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -44,6 +44,7 @@ #include "IPCDBusServiceAdapter.h" #include "IPCAdapterModelPropertyHandler.h" #include "DBusManager.h" +#include "FaceliftDBusMarshaller.h" #include "{{module.fullyQualifiedPath}}/{{interfaceName}}.h" #include "{{module.fullyQualifiedPath}}/{{interfaceName}}QMLAdapter.h" @@ -86,13 +87,13 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - QMap changedProperties(); + QVariantMap changedProperties(); - void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + QVariantMap marshalProperties() override; - void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + QVariant marshalProperty(const QString& propertyName) override; - void setProperty(const QList& arguments) override; + void setProperty(const QString& propertyName, const QVariant& value) override; {% for event in interface.signals %} void {{event}}( diff --git a/codegen/facelift/templates/IPCProxy.template.cpp b/codegen/facelift/templates/IPCProxy.template.cpp index c9178172..5d100338 100644 --- a/codegen/facelift/templates/IPCProxy.template.cpp +++ b/codegen/facelift/templates/IPCProxy.template.cpp @@ -39,15 +39,6 @@ #ifdef DBUS_IPC_ENABLED #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusProxy.h" -{% for type in interface.referencedTypes %} -{% if (not type.is_primitive) %} -{% if (not type.is_model) %} -{% if (not type.is_interface) %} -{{type.requiredInclude}} -{% endif %} -{% endif %} -{% endif %} -{% endfor %} #endif {% set className = interfaceName + "IPCProxy" %} @@ -90,22 +81,6 @@ struct {{className}}::Impl { {{className}}::{{className}}(QObject *parent) : BaseType(facelift::InterfaceManager::instance(), parent), m_impl(std::make_unique()) { -#ifdef DBUS_IPC_ENABLED - {% for type in interface.referencedTypes %} - {% if (not type.is_primitive) %} - {% if (not type.is_enum) %} - {% if (not type.is_model) %} - {% if (not type.is_interface) %} - qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); - qDBusRegisterMetaType>(); - qDBusRegisterMetaType>(); - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} -#endif - ipc()->setObjectPath(SINGLETON_OBJECT_PATH); {% if generateAsyncProxy %} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 69bf72c9..34929979 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -36,8 +36,6 @@ {% set className = interfaceName + proxyTypeNameSuffix %} #include "{{className}}.h" -#include "FaceliftEnum.h" - {{module.namespaceCppOpen}} {{className}}::{{className}}(QObject *parent) : BaseType(parent) @@ -53,53 +51,56 @@ {% endif %} } -void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) +void {{className}}::unmarshalProperties(const QVariantMap& values) { - QListIterator argumentsIterator(msg.arguments()); - if (argumentsIterator.hasNext()) { - QMap values = castFromVariant>(argumentsIterator.next()); - for (const QString &propertyName: values.keys()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_interface %} - const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); - bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% elif property.type.is_model %} - bool emit_{{property.name}}ChangeSignal = true; - int {{property.name}}Size = castFromDBusVariant(values[propertyName]); - m_{{property.name}}.beginResetModel(); - m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); - m_{{property.name}}.endResetModel(); - {% else %} - const auto previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); - bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% endif %} - if (emit_{{property.name}}ChangeSignal) - emit {{property.name}}Changed(); - } - {% endfor %} - if (propertyName == QStringLiteral("ready")) { - bool previousIsReady = this->ready(); - m_serviceReady = castFromDBusVariant(values[propertyName]); - bool emit_ReadyChangeSignal = (previousIsReady != m_serviceReady); - if (emit_ReadyChangeSignal) - emit readyChanged(); - } + QMap emitChangeSignal; + for (const QString &propertyName: values.keys()) { + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_interface %} + const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); + emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% elif property.type.is_model %} + emitChangeSignal[QStringLiteral("{{property.name}}")] = true; + int {{property.name}}Size = castFromQVariant(values[propertyName]); + m_{{property.name}}.beginResetModel(); + m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); + m_{{property.name}}.endResetModel(); + {% else %} + const auto previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); + emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% endif %} + } + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + bool previousIsReady = this->ready(); + m_serviceReady = castFromQVariant(values[propertyName]); + emitChangeSignal[QStringLiteral("ready")] = (previousIsReady != m_serviceReady); + } + } + for (const QString &propertyName: emitChangeSignal.keys()) { + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}") && emitChangeSignal[propertyName]) { + emit {{property.name}}Changed(); + } + {% endfor %} + if (propertyName == QStringLiteral("ready") && emitChangeSignal[propertyName]) { + emit readyChanged(); } } } void {{className}}::handleSignals(InputIPCMessage& msg) { - Q_UNUSED(msg); + Q_UNUSED(msg) {% for event in interface.signals %} if (msg.member() == QStringLiteral("{{event}}")) { QListIterator argumentsIterator(msg.arguments()); {% for parameter in event.parameters %} {{parameter.interfaceCppType}} param_{{parameter.name}}; - param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); + param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromQVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); {% endfor %} emit {{event}}( {%- set comma = joiner(", ") -%} @@ -121,11 +122,11 @@ const QList& {{className}}::getSignals() const "{{event}}", {% endfor %} {% if interface.hasModelProperty %} - "ModelUpdateEventDataChanged", - "ModelUpdateEventInsert", - "ModelUpdateEventRemove", - "ModelUpdateEventMove", - "ModelUpdateEventReset" + facelift::IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME, + facelift::IPCCommon::MODEL_INSERT_MESSAGE_NAME, + facelift::IPCCommon::MODEL_REMOVE_MESSAGE_NAME, + facelift::IPCCommon::MODEL_MOVE_MESSAGE_NAME, + facelift::IPCCommon::MODEL_RESET_MESSAGE_NAME, {% endif %} }; @@ -136,7 +137,7 @@ const QList& {{className}}::getSignals() const void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) { QListIterator argumentsIterator(msg.arguments()); - const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); {% for property in interface.properties %} {% if property.type.is_model %} if (modelPropertyName == QStringLiteral("{{property.name}}")) { @@ -147,22 +148,19 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) } {% endif %} -void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) +void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedProperties) { {% if interface.properties %} - QListIterator argumentsIterator(msg.arguments()); - QString interfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QVariantMap()); for (const QString &propertyName: changedProperties.keys()) { {% for property in interface.properties %} if (propertyName == QStringLiteral("{{property.name}}")) { {% if property.type.is_model %} - int {{property.name}}Size = castFromDBusVariant(changedProperties[propertyName]); + int {{property.name}}Size = castFromQVariant(changedProperties[propertyName]); m_{{property.name}}.beginResetModel(); m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); m_{{property.name}}.endResetModel(); {% else %} - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); {% endif %} } {% endfor %} @@ -177,7 +175,7 @@ void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) {% endfor %} } {% else %} - Q_UNUSED(msg); + Q_UNUSED(changedProperties); {% endif %} } @@ -226,7 +224,7 @@ void {{className}}::{{operation.name}}( {%- for parameter in operation.parameters -%} , {{parameter.name}} {%- endfor -%} ); - return (!args.isEmpty() ? castFromVariant<{{operation.interfaceCppType}}>(args[0]):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); + return (!args.isEmpty() ? castFromQVariant<{{operation.interfaceCppType}}>(args.first()):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); {% else %} ipc()->sendMethodCall(memberID(MethodID::{{operation.name}}, "{{operation.name}}") {%- for parameter in operation.parameters -%} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index b3d321fc..5431d646 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -67,7 +67,7 @@ class {{classExport}} {{className}} : public {{baseClass}} {{className}}(QObject *parent = nullptr); - void unmarshalPropertyValues(InputIPCMessage &msg) override; + void unmarshalProperties(const QVariantMap& values) override; {% if interface.hasModelProperty %} void setServiceRegistered(bool isRegistered) override @@ -85,9 +85,10 @@ class {{classExport}} {{className}} : public {{baseClass}} {% endif %} void handleSignals(InputIPCMessage& msg) override; + const QList& getSignals() const override; - void unmarshalPropertiesChanged(InputIPCMessage &msg) override; + void unmarshalPropertiesChanged(const QVariantMap& changedProperties) override; {% for operation in interface.operations %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 4f7ecbbe..52395c60 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -35,7 +35,8 @@ {% set className = interfaceName + proxyTypeNameSuffix %} -#include +#include "ipc-common.h" +#include "DBusSignatureHelper.h" #include "{{className}}.h" {{module.namespaceCppOpen}} @@ -56,7 +57,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for operation in interface.operations %} if (member == memberID(MethodID::{{operation.name}}, "{{operation.name}}")) { {% for parameter in operation.parameters %} - {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.cppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.cppType}}(){% else %}nullptr{% endif %}); + {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromQVariant<{{parameter.cppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.cppType}}(){% else %}nullptr{% endif %}); {% endfor %} {% if operation.isAsync %} theService->{{operation.name}}({% for parameter in operation.parameters %} param_{{parameter.name}}, {%- endfor -%} @@ -74,7 +75,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {{ comma() }}param_{{parameter.name}} {%- endfor -%}); {% if operation.hasReturnValue %} - replyMessage << castToVariant(returnValue); + replyMessage << castToQVariant(returnValue); {% endif %} {% endif %} } else @@ -82,7 +83,10 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for property in interface.properties %} {% if property.type.is_model %} if (member == memberID(MethodID::{{property.name}}, "{{property.name}}")) { - m_{{property.name}}Handler.handleModelRequest(requestMessage, replyMessage); + QListIterator argumentsIterator(requestMessage.arguments()); + int first = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): int()); + m_{{property.name}}Handler.handleModelRequest(first, last, replyMessage); } else {% endif %} {% endfor %} @@ -95,50 +99,41 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa void {{className}}::appendDBUSIntrospectionData(QTextStream &s) const { - Q_UNUSED(s); // For empty interfaces + Q_UNUSED(s) // For empty interfaces {% for property in interface.properties %} {% if not property.type.is_model %} - s << QStringLiteral("").arg(typeToSignature<{{property.type.interfaceCppType}}>(), - {{ property.readonly | cppBool }} ? QStringLiteral("read"): QStringLiteral("readwrite")); + facelift::appendPropertySignature(s, "{{property.name}}", typeToSignature<{{property.type.interfaceCppType}}>(), {{ property.readonly | cppBool }}); {% endif %} {% endfor %} - s << QStringLiteral(""); + facelift::appendReadyProperty(s); {% for operation in interface.operations %} - s << ""; - {%- for parameter in operation.parameters -%} - s << "(); - s << "\" direction=\"in\"/>"; - {%- endfor -%} - + facelift::appendDBusMethodSignature(s, "{{operation.name}}", std::list>{ + {%- set comma = joiner(", ") -%} + {% for parameter in operation.parameters %} + {{ comma() }}{"{{parameter.name}}", typeToSignature<{{parameter.type.interfaceCppType}}>()} + {% endfor %} + } {% if operation.hasReturnValue %} - s << "(); - s << "\" direction=\"out\"/>"; - {% endif %}; - s << ""; + , typeToSignature<{{operation.interfaceCppType}}>() + {% endif %} + ); {% endfor %} // signals {% for signal in interface.signals %} { - s << ""; - {%- for parameter in signal.parameters -%} - s << "(); - s << "\" direction=\"out\"/>"; - {%- endfor -%} - s << ""; + facelift::appendDBusSignalSignature(s, "{{signal.name}}", std::list>{ + {%- set comma = joiner(", ") -%} + {% for parameter in signal.parameters %} + {{ comma() }}{"{{parameter.name}}", typeToSignature<{{parameter.type.interfaceCppType}}>()} + {% endfor %} + }); } {% endfor %} {% if interface.hasModelProperty %} - s << ""; - s << ""; - s << ""; - s << ""; - s << ""; + facelift::appendDBusModelSignals(s); {% endif %} } @@ -154,6 +149,7 @@ void {{className}}::connectSignals() m_previous{{property.name}} = theService->{{property.name}}(); {% endif %} {% endfor %} + m_previousReadyState = theService->ready(); // Properties {% for property in interface.properties %} @@ -165,7 +161,7 @@ void {{className}}::connectSignals() {% endfor %} QObject::connect(theService, &ServiceType::readyChanged, this, [this, theService] () { - this->sendPropertiesChanged(QMap{ {"ready", castToDBusVariant(theService->ready())} }); + this->sendPropertiesChanged(changedProperties()); }); // Signals @@ -174,86 +170,77 @@ void {{className}}::connectSignals() {% endfor %} } -QMap {{className}}::changedProperties() +QVariantMap {{className}}::changedProperties() { - QMap ret; + QMap ret; auto theService = service(); Q_UNUSED(theService); {% for property in interface.properties %} {% if not property.type.is_model %} if (m_previous{{property.name}} != theService->{{property.name}}()) { - ret[QStringLiteral("{{property.name}}")] = castToDBusVariant(theService->{{property.name}}()); + ret[QStringLiteral("{{property.name}}")] = castToQVariant(theService->{{property.name}}()); m_previous{{property.name}} = theService->{{property.name}}(); } {% endif %} {% endfor %} + if (m_previousReadyState != theService->ready()) { + ret[QStringLiteral("ready")] = castToQVariant(theService->ready()); + m_previousReadyState = theService->ready(); + } return ret; } -void {{className}}::marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) +QVariantMap {{className}}::marshalProperties() { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto theService = service(); - QMap ret; - {#% if (not interface.properties) %#} - Q_UNUSED(theService); - {#% endif %#} + QVariantMap ret; + auto theService = service(); + {#% if (not interface.properties) %#} + Q_UNUSED(theService); + {#% endif %#} - {% for property in interface.properties %} - {% if property.type.is_model %} - ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}().size()); - {% else %} - ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}()); - {% endif %} - {% endfor %} - ret["ready"] = castToDBusVariant(theService->ready()); - msg << castToVariant(ret); - } + {% for property in interface.properties %} + {% if property.type.is_model %} + ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}().size()); + {% else %} + ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}()); + {% endif %} + {% endfor %} + ret["ready"] = castToQVariant(theService->ready()); + return ret; } -void {{className}}::marshalProperty(const QList& arguments, OutputIPCMessage& msg) +QVariant {{className}}::marshalProperty(const QString& propertyName) { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_model %} + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_model %} - {% else %} - msg << castToVariant(service()->{{property.name}}()); - {% endif %} - } - {% endfor %} - if (propertyName == QStringLiteral("ready")) { - msg << castToVariant(service()->ready()); - } + {% else %} + return castToQVariant(service()->{{property.name}}()); + {% endif %} + } + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + return castToQVariant(service()->ready()); } +return QVariant(); } -void {{className}}::setProperty(const QList& arguments) +void {{className}}::setProperty(const QString& propertyName, const QVariant& value) { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (argumentsIterator.hasNext()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_interface %} - Q_ASSERT(false); // Writable interface properties are unsupported - {% elif property.type.is_model %} + Q_UNUSED(propertyName) + Q_UNUSED(value) + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_interface %} + Q_ASSERT(false); // Writable interface properties are unsupported + {% elif property.type.is_model %} - {% elif (not property.readonly) %} - service()->set{{property.name}}(castFromDBusVariant<{{property.cppType}}>(argumentsIterator.next())); - {% endif %} - } - {% endfor %} - } + {% elif (not property.readonly) %} + service()->set{{property.name}}(castFromQVariant<{{property.cppType}}>(value)); + {% endif %} } + {% endfor %} } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index d2f0bc0b..0caf13f1 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -82,13 +82,13 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - QMap changedProperties(); + QVariantMap changedProperties(); - void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + QVariantMap marshalProperties() override; - void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + QVariant marshalProperty(const QString& propertyName) override; - void setProperty(const QList& arguments) override; + void setProperty(const QString& propertyName, const QVariant& value) override; {% for event in interface.signals %} void {{event}}( @@ -112,6 +112,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{property.interfaceCppType}} m_previous{{property.name}} {}; {% endif %} {% endfor %} + bool m_previousReadyState = false; }; {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/ImplementationBase.template.h b/codegen/facelift/templates/ImplementationBase.template.h index 9ee36edb..6f9a23e5 100644 --- a/codegen/facelift/templates/ImplementationBase.template.h +++ b/codegen/facelift/templates/ImplementationBase.template.h @@ -91,7 +91,6 @@ class {{classExport}} {{interfaceName}}ImplementationBase : public {{interfaceNa {% endif %} {% endfor %} - Q_PROPERTY(bool ready READ ready) bool ready() const override { return m_ready.value(); diff --git a/codegen/facelift/templates/Service.template.cpp b/codegen/facelift/templates/Service.template.cpp index 82728d66..23b1a86b 100644 --- a/codegen/facelift/templates/Service.template.cpp +++ b/codegen/facelift/templates/Service.template.cpp @@ -58,7 +58,6 @@ constexpr const char* {{interfaceName}}::FULLY_QUALIFIED_INTERFACE_NAME; }); } #endif - registerTypes(""); } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Struct.template.cpp b/codegen/facelift/templates/Struct.template.cpp index 60dc0e05..75649dcf 100644 --- a/codegen/facelift/templates/Struct.template.cpp +++ b/codegen/facelift/templates/Struct.template.cpp @@ -36,12 +36,7 @@ ****************************************************************************/ #include "{{struct}}.h" -#ifdef DBUS_IPC_ENABLED -#include -#include -#endif #include "FaceliftConversion.h" -#include "FaceliftEnum.h" {{module.namespaceCppOpen}} @@ -100,6 +95,12 @@ void {{struct.name}}::deserialize(const QByteArray &array) {% endif %} +{% if struct.toByteArrayOverDBus %} +bool {{struct.name}}::toByteArrayOverDBus() +{ + return true; +} +{% endif %} const {{struct}}::FieldNames {{struct}}::FIELD_NAMES = { { {%- for field in struct.fields -%} @@ -131,77 +132,4 @@ QString {{struct.name}}::toString() const return toStringWithFields(CLASS_ID, FIELD_NAMES); } -#ifdef DBUS_IPC_ENABLED -void {{struct.name}}::registerDBusTypes() -{ - {% for field in struct.fields %} - {% if field.type.is_struct %} - {{field.type.cppType}}::registerDBusTypes(); - {% endif %} - {% if field.type.nested.is_struct %} - {{field.type.nested.cppType}}::registerDBusTypes(); - {% endif %} - {% if (not field.type.is_primitive and not field.type.is_enum and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - {% endif %} - {% if (field.type.is_list or field.type.is_map) %} - {% if (not field.type.nested.is_primitive) or (not field.type.nested.is_enum) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); - {% endif %} - {% endif %} - {% endfor %} -} - -QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% if not struct.serializeOverIPC %} - {% for field in struct.fields %} - argument << {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - {% else %} - QByteArray byteArray; - QDataStream dataStream(&byteArray, QIODevice::WriteOnly); - dataStream << {{struct.name|lower}}; - argument << byteArray; - {% endif %} - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% if not struct.serializeOverIPC %} - {% for field in struct.fields %} - argument >> {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - {% else %} - QByteArray byteArray; - QDataStream dataStream(&byteArray, QIODevice::ReadOnly); - argument >> byteArray; - dataStream >> {{struct.name|lower}}; - {% endif %} - argument.endStructure(); - - return argument; -} - -QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ) -{ - {% for field in struct.fields %} - dataStream << {{struct.name|lower}}.m_{{field}}; - {% endfor %} - return dataStream; -} - -QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ) -{ - {% for field in struct.fields %} - dataStream >> {{struct.name|lower}}.m_{{field}}; - {% endfor %} - return dataStream; -} -#endif {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Struct.template.h b/codegen/facelift/templates/Struct.template.h index 4f0439e4..8b604db7 100644 --- a/codegen/facelift/templates/Struct.template.h +++ b/codegen/facelift/templates/Struct.template.h @@ -47,7 +47,6 @@ {{field.type.requiredInclude}} {% endfor %} -class QDBusArgument; {{module.namespaceCppOpen}} {% if struct.isQObjectWrapperEnabled %} @@ -85,15 +84,6 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {{struct.name}}& operator=(const {{struct.name}} &right); - friend QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}); - friend const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}); - - - friend QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ); - friend QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ); - - static void registerDBusTypes(); - Q_INVOKABLE {{struct.fullyQualifiedCppType}} clone() const; {% if struct.isSerializable %} @@ -106,6 +96,10 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {% endif %} + {% if struct.toByteArrayOverDBus %} + static bool toByteArrayOverDBus(); + {% endif %} + QString toString() const; {% for field in struct.fields %} diff --git a/doc/page-annotations.h b/doc/page-annotations.h index 334a8f3c..03a6f8ee 100644 --- a/doc/page-annotations.h +++ b/doc/page-annotations.h @@ -39,7 +39,7 @@ The following annotations can be used in structure definitions: |Annotation | Description | Supported over IPC | |-------------------------------|-------------------------------------------------------------|--------------------| -|\@serializeOverIPC: true | Treat the whole structure as byte array over IPC reducing structure signature only to DBUS Type BYTE | Yes | +|\@toByteArrayOverDBus: true | Serialize the whole structure as one byte array over IPC reducing structure signature only to DBUS Type ARRAY OF BYTE | Yes | |\@serializable: true | Adds serialization/deserialization capability to the structure | Yes | |\@qml-component: true | Enables the creation and registration of a creatable QML component for the corresponding structure | Yes | diff --git a/src/ipc/dbus/CMakeLists.txt b/src/ipc/dbus/CMakeLists.txt index e865445a..cbc9cf9a 100644 --- a/src/ipc/dbus/CMakeLists.txt +++ b/src/ipc/dbus/CMakeLists.txt @@ -25,6 +25,7 @@ if(Qt5DBus_FOUND) DBusManager.h DBusManagerInterface.h DBusIPCProxy.h + FaceliftDBusMarshaller.h IPCDBusServiceAdapter.h DBusObjectRegistry.h DBusIPCMessage.h diff --git a/src/ipc/dbus/DBusIPCCommon.h b/src/ipc/dbus/DBusIPCCommon.h index 676a0bdc..f39a1561 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -36,20 +36,19 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif - namespace facelift { namespace dbus { using namespace facelift; - struct FaceliftIPCLibDBus_EXPORT DBusIPCCommon { - static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; - static constexpr const char *GET_PROPERTY = "Get"; - static constexpr const char *SET_PROPERTY = "Set"; + static constexpr const char *DEFAULT_SERVICE_NAME = "facelift.registry"; + static constexpr const char *GET_ALL_PROPERTIES_MESSAGE_NAME = "GetAll"; + static constexpr const char *GET_PROPERTY_MESSAGE_NAME = "Get"; + static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "Set"; static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; - static constexpr const char *DEFAULT_SERVICE_NAME = "facelift.registry"; + static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; + static constexpr const int FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH = 255; }; } diff --git a/src/ipc/dbus/DBusIPCMessage.cpp b/src/ipc/dbus/DBusIPCMessage.cpp index 77bc35f8..f259afa4 100644 --- a/src/ipc/dbus/DBusIPCMessage.cpp +++ b/src/ipc/dbus/DBusIPCMessage.cpp @@ -74,14 +74,7 @@ QList DBusIPCMessage::arguments() const DBusIPCMessage &DBusIPCMessage::operator<<(const QVariant &arg) { - static int qListStringTypeId = qMetaTypeId>(); - if (arg.userType() != qListStringTypeId) { // workaround to use QList since its signature matches the QStringList - m_message << arg; - } - else { - QStringList stringList(arg.value>()); - m_message << stringList; - } + m_message << arg; return *this; } @@ -117,9 +110,9 @@ DBusIPCMessage DBusIPCMessage::createReply() return DBusIPCMessage(m_message.createReply()); } -DBusIPCMessage DBusIPCMessage::createErrorReply(const QString &msg, const QString &member) +DBusIPCMessage DBusIPCMessage::createErrorReply(const QString &name, const QString &msg) { - return DBusIPCMessage(m_message.createErrorReply(msg, member)); + return DBusIPCMessage(m_message.createErrorReply(name, msg)); } QString DBusIPCMessage::signature() const diff --git a/src/ipc/dbus/DBusIPCMessage.h b/src/ipc/dbus/DBusIPCMessage.h index e517d322..b8f07b26 100644 --- a/src/ipc/dbus/DBusIPCMessage.h +++ b/src/ipc/dbus/DBusIPCMessage.h @@ -63,7 +63,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCMessage QList arguments() const; DBusIPCMessage &operator<<(const QVariant &arg); DBusIPCMessage createReply(); - DBusIPCMessage createErrorReply(const QString &msg, const QString &member); + DBusIPCMessage createErrorReply(const QString &name, const QString &msg); QString signature() const; bool isReplyMessage() const; bool isErrorMessage() const; diff --git a/src/ipc/dbus/DBusIPCProxy.h b/src/ipc/dbus/DBusIPCProxy.h index 1d29e475..e09c675c 100644 --- a/src/ipc/dbus/DBusIPCProxy.h +++ b/src/ipc/dbus/DBusIPCProxy.h @@ -106,13 +106,8 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa } template - T castFromVariant(const QVariant& value) { - return m_ipcBinder.castFromVariant(value); - } - - template - T castFromDBusVariant(const QVariant& value) { - return m_ipcBinder.castFromDBusVariant(value); + T castFromQVariant(const QVariant& value) { + return m_ipcBinder.castFromQVariant(value); } protected: diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 97355801..6f62ff5d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -32,7 +32,6 @@ #include "DBusIPCProxyBinder.h" #include "DBusManagerInterface.h" #include "DBusRequestHandler.h" -#include "DBusIPCCommon.h" #include "DBusObjectRegistry.h" namespace facelift { @@ -71,7 +70,12 @@ void DBusIPCProxyBinder::onServerNotAvailableError(const QString &propertyName) void DBusIPCProxyBinder::onPropertiesChanged(const QDBusMessage &dbusMessage) { DBusIPCMessage msg(dbusMessage); - m_serviceObject->unmarshalPropertiesChanged(msg); + QListIterator argumentsIterator(msg.arguments()); + QString interfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (interfaceName == m_interfaceName) { + QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(changedProperties); + } } void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) @@ -83,11 +87,12 @@ void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) void DBusIPCProxyBinder::requestPropertyValues() { - DBusIPCMessage msg(serviceName(), objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::GET_ALL_PROPERTIES); + DBusIPCMessage msg(serviceName(), objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME); msg << QVariant::fromValue(interfaceName()); auto replyHandler = [this](DBusIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->unmarshalPropertyValues(replyMessage); + QVariantMap values = (!replyMessage.arguments().isEmpty() ? castFromQVariant(replyMessage.arguments().first()): QVariantMap()); + m_serviceObject->unmarshalProperties(values); m_serviceObject->setServiceRegistered(true); } else { qCDebug(LogIpc) << "Service not yet available : " << objectPath(); diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index 3e52e732..c10fd53d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -40,8 +40,9 @@ #include #include "IPCProxyBinderBase.h" #include "DBusIPCMessage.h" -#include "FaceliftUtils.h" #include "DBusIPCCommon.h" +#include "FaceliftUtils.h" +#include "FaceliftDBusMarshaller.h" #include "DBusManagerInterface.h" #include "IPCServiceAdapterBase.h" @@ -100,7 +101,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendSetterCall(const QString& property, const PropertyType &value); template - DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args); + DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args) const; template void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); @@ -109,95 +110,107 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - QList sendMethodCallWithReturn(const char *methodName, Args && ... args); + QList sendMethodCallWithReturn(const char *methodName, Args && ... args) const; void setHandler(DBusRequestHandler *handler); template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); + T castFromQVariant(const QVariant& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castFromQVariantSpecialized(HelperType(), value); } template - T castFromDBusVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); - } - - template - QVariant castToVariant(const T& value) { - return castToVariantSpecialized(HelperType(), value); - } - - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); + QVariant castToQVariant(const T& value) const { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castToQVariantSpecialized(HelperType(), value); } private: void checkRegistry(); - template struct HelperType { }; - template::value && !std::is_enum::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qdbus_cast(value); } + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + template::value && std::is_enum::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return static_cast(qdbus_cast(value)); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + template::value && std::is_enum::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + QList tmp = qdbus_cast>(value); + std::transform(tmp.begin(), tmp.end(), std::back_inserter(ret), [](const int entry){return static_cast(entry);}); + return ret; + } + + template::value && std::is_enum::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + QMap tmp = qdbus_cast>(value); + for (const QString& key: tmp.keys()) { + ret[key] = static_cast(tmp[key]); + } + return ret; } template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { - return getOrCreateSubProxy::type::IPCDBusProxyType>(qdbus_cast(value)); + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCDBusProxyType>(qdbus_cast(value)); } - template - QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { - QMap ret; - auto objectPaths = qdbus_cast>(value); + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qdbus_cast>(value); for (const QString& key: objectPaths.keys()) { - ret[key] = getOrCreateSubProxy(objectPaths[key]); + ret[key] = getOrCreateSubProxy::type::IPCDBusProxyType>(objectPaths[key]); } return ret; } - template - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - QList ret; - auto objectPaths = qdbus_cast*/>(value); - for (const DBusObjectPath& objectPath: objectPaths) { - ret.append(getOrCreateSubProxy(objectPath)); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qdbus_cast(value); + for (const QString& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy::type::IPCDBusProxyType>(objectPath)); } return ret; } template::value && !std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) const { return QVariant::fromValue(value); } - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) const { return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } template::value && std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) const { return QVariant::fromValue(static_cast(value)); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QList& value) { - return QVariant::fromValue(static_cast>(value)); + QVariant castToQVariantSpecialized(HelperType>, const QList& value) const { + QList ret; + std::transform(value.begin(), value.end(), std::back_inserter(ret), [](const T entry){return static_cast(entry);}); + return QVariant::fromValue(ret); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) const { QMap ret; for (const QString& key: value.keys()) { ret[key] = static_cast(value[key]); @@ -214,12 +227,12 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase template -inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) +inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) const { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; auto replyMessage = this->call(msg); if (replyMessage.isErrorMessage()) { @@ -234,13 +247,13 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { if (!msg.arguments().isEmpty()) { - returnValue = castFromVariant(msg.arguments()[0]); + returnValue = castFromQVariant(msg.arguments().first()); } answer(returnValue); } else { @@ -255,7 +268,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [answer](DBusIPCMessage &msg) { Q_UNUSED(msg) @@ -264,7 +277,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face } template -inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) +inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) const { DBusIPCMessage msg = sendMethodCall(methodName, args ...); QList ret; @@ -277,10 +290,10 @@ inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char * template inline void DBusIPCProxyBinder::sendSetterCall(const QString &property, const PropertyType &value) { - DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY); + DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY_MESSAGE_NAME); msg << QVariant::fromValue(m_interfaceName); - msg << castToVariant(property); - msg << QVariant::fromValue(castToDBusVariant(value)); + msg << castToQVariant(property); + msg << QVariant::fromValue(QDBusVariant(castToQVariant(value))); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { diff --git a/src/ipc/dbus/DBusObjectRegistry.cpp b/src/ipc/dbus/DBusObjectRegistry.cpp index d07c490f..d91a4ccc 100644 --- a/src/ipc/dbus/DBusObjectRegistry.cpp +++ b/src/ipc/dbus/DBusObjectRegistry.cpp @@ -122,7 +122,7 @@ void DBusObjectRegistry::syncObjects() ObjectRegistryIPCDBusProxy objectRegistryProxy; objectRegistryProxy.ipc()->setServiceName(m_serviceName); objectRegistryProxy.connectToServer(); - // Q_ASSERT(objectRegistryProxy.ready()); + Q_ASSERT(objectRegistryProxy.ready()); updateObjects(objectRegistryProxy.getObjects()); } diff --git a/src/ipc/dbus/DBusRequestHandler.h b/src/ipc/dbus/DBusRequestHandler.h index a72f0af7..4588ab16 100644 --- a/src/ipc/dbus/DBusRequestHandler.h +++ b/src/ipc/dbus/DBusRequestHandler.h @@ -45,8 +45,8 @@ class FaceliftIPCLibDBus_EXPORT DBusRequestHandler { public: - virtual void unmarshalPropertyValues(DBusIPCMessage &msg) = 0; - virtual void unmarshalPropertiesChanged(DBusIPCMessage &msg) = 0; + virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; virtual void handleSignals(DBusIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/dbus/FaceliftDBusMarshaller.h b/src/ipc/dbus/FaceliftDBusMarshaller.h new file mode 100644 index 00000000..14507ce9 --- /dev/null +++ b/src/ipc/dbus/FaceliftDBusMarshaller.h @@ -0,0 +1,269 @@ +/********************************************************************** +** +** Copyright (C) 2018 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +#pragma once + +#include +#include // std::once_flag +#include "FaceliftUtils.h" +#include "StructureBase.h" +#include "DBusIPCCommon.h" + +template struct HelperType { }; + +template::value && !std::is_enum::value, int> = 0> +void registerDBusType(HelperType) +{ + // DO NOTHIG FOR BUILTIN TYPES +} + +template::value && std::is_enum::value, int> = 0> +void registerDBusType(HelperType) +{ + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround is to handle in castToQVariant the conversion + //qDBusRegisterMetaType(); +} + +template::value, int> = 0> +void registerDBusType(HelperType) +{ + qDBusRegisterMetaType(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} +template::value, int> = 0> +void registerDBusType(HelperType>) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId>())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} + +template::value, int> = 0> +void registerDBusType(HelperType>) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId>())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} + +struct ToQDBusArgument +{ + ToQDBusArgument(QDBusArgument& argument): m_argument(argument) + {} + template + void operator()(T &&value) + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType::type>());}); + m_argument << value; + } + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround to convert enum to int + template::type>::value, int> = 0> + void operator()(const QList &value) + { + QList tmp; + std::transform(value.begin(), value.end(), std::back_inserter(tmp), [](const T entry){return static_cast(entry);}); + m_argument << tmp; + } + template::type>::value, int> = 0> + void operator()(const QMap &value) + { + QMap tmp; + for (const QString key: value.keys()) { + tmp[key] = static_cast(value[key]); + } + m_argument << tmp; + } + QDBusArgument m_argument; +}; + +struct FromQDBusArgument +{ + FromQDBusArgument(const QDBusArgument& argument): m_argument(argument) + {} + template + void operator()(T &&value) + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType::type>());}); + m_argument >> value; + } + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround to convert enum to int + template::type>::value, int> = 0> + void operator()(const QList &value) + { + QList tmp; + m_argument >> tmp; + std::transform(tmp.begin(), tmp.end(), std::back_inserter(value), [](const int entry){return static_cast(entry);}); + } + template::type>::value, int> = 0> + void operator()(const QMap &value) + { + QMap tmp; + m_argument >> tmp; + for (const QString& key: tmp.keys()) { + value[key] = static_cast(tmp[key]); + } + } + const QDBusArgument& m_argument; +}; + +struct FromQDataStream +{ + FromQDataStream(QDataStream& dataStream): m_dataStream(dataStream) + {} + template + void operator()(T &&value) + { + m_dataStream >> value; + } + QDataStream& m_dataStream; +}; + +struct ToQDataStream +{ + ToQDataStream(QDataStream& dataStream): m_dataStream(dataStream) + {} + template + void operator()(T &&value) + { + m_dataStream << value; + } + QDataStream& m_dataStream; +}; + +template +class ToByteArrayOverDBus +{ +private: + typedef char YesType[1]; + typedef char NoType[2]; + + template static YesType& test( decltype(&C::toByteArrayOverDBus) ) ; + template static NoType& test(...); +public: + enum { value = sizeof(test(0)) == sizeof(YesType) }; +}; + + +template::value, int> = 0> +inline QDataStream& operator<<(QDataStream &dataStream, const T& source) +{ + dataStream << static_cast(source); + return dataStream; +} + +template::value, int> = 0> +inline const QDataStream& operator>>(QDataStream &dataStream, T &source) +{ + int value; + dataStream >> value; + source = static_cast(value); + return dataStream; +} + +template::value, int> = 0> +inline QDataStream& operator<<( QDataStream& dataStream, const T &structure) +{ + facelift::for_each_in_tuple_const(structure.asTuple(), ToQDataStream(dataStream)); + return dataStream; +} + +template::value, int> = 0> +inline QDataStream& operator>>( QDataStream& dataStream, T &structure) +{ + facelift::for_each_in_tuple(structure.asTuple(), FromQDataStream(dataStream)); + return dataStream; +} + +// not neccessary if Qt allows defining Enum as INT +template::value, int> = 0> +inline QDBusArgument& operator<<(QDBusArgument &argument, const T& source) +{ + argument << static_cast(source); + return argument; +} + +template::value, int> = 0> +inline const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) +{ + int tmp; + argument >> tmp; + source = static_cast(tmp); + return argument; +} + +template::value && !ToByteArrayOverDBus::value, int> = 0> +inline QDBusArgument &operator<<(QDBusArgument &argument, const T &structure) +{ + argument.beginStructure(); + facelift::for_each_in_tuple_const(structure.asTuple(), ToQDBusArgument(argument)); + argument.endStructure(); + return argument; +} + +template::value && ToByteArrayOverDBus::value, int> = 0> +inline QDBusArgument &operator<<(QDBusArgument &argument, const T &structure) +{ + argument.beginStructure(); + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::WriteOnly); + dataStream << structure; + argument << byteArray; + argument.endStructure(); + return argument; +} + +template::value && !ToByteArrayOverDBus::value, int> = 0> +inline const QDBusArgument &operator>>(const QDBusArgument &argument, T &structure) +{ + argument.beginStructure(); + facelift::for_each_in_tuple(structure.asTuple(), FromQDBusArgument(argument)); + argument.endStructure(); + return argument; +} + +template::value && ToByteArrayOverDBus::value, int> = 0> +inline const QDBusArgument &operator>>(const QDBusArgument &argument, T &structure) +{ + argument.beginStructure(); + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::ReadOnly); + argument >> byteArray; + dataStream >> structure; + argument.endStructure(); + return argument; +} diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index 4a65cb27..0447b6dd 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -90,9 +90,63 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase Q_ASSERT(qobject_cast(serverObject) != nullptr); registerService(objectPath, static_cast(serverObject)); } + + template + const char* typeToSignature() const + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return typeToSignatureSpecialized(HelperType()); + } protected: - QPointer m_service; + template::value && !std::is_enum::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value && std::is_enum::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + QPointer m_service; }; } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp index 616dffb5..6e65a310 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp @@ -51,7 +51,6 @@ #include "DBusIPCProxy.h" #include "DBusObjectRegistry.h" -#include "DBusIPCCommon.h" #include "IPCDBusServiceAdapterBase.h" namespace facelift { @@ -60,8 +59,8 @@ namespace dbus { bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) { DBusIPCMessage requestMessage(dbusMsg); - DBusIPCMessage replyMessage = requestMessage.createReply(); + bool retVal = false; qCDebug(LogIpc) << "Handling incoming message: " << requestMessage.toString(); @@ -73,16 +72,43 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) qCDebug(LogIpc) << "Enabling IPCDBusServiceAdapter for" << this->service(); connectSignals(); } - if (dbusMsg.member() == DBusIPCCommon::GET_ALL_PROPERTIES) { - marshalPropertyValues(dbusMsg.arguments(), replyMessage); - send(replyMessage); + if (dbusMsg.member() == DBusIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME) { + QListIterator argumentsIterator(dbusMsg.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QVariantMap ret = marshalProperties(); + QMap convertedToDBusVariant; + for (const QString& key: ret.keys()) { + convertedToDBusVariant[key] = QDBusVariant(ret[key]); + } + replyMessage << QVariant::fromValue(convertedToDBusVariant); + send(replyMessage); + retVal = true; + } } - else if (dbusMsg.member() == DBusIPCCommon::GET_PROPERTY) { - marshalProperty(dbusMsg.arguments(), replyMessage); - send(replyMessage); + else if (dbusMsg.member() == DBusIPCCommon::GET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(dbusMsg.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + QVariant value = marshalProperty(propertyName); + if (value.isValid()) { + replyMessage << QVariant::fromValue(QDBusVariant(value)); + send(replyMessage); + retVal = true; + } + } } - else if (dbusMsg.member() == DBusIPCCommon::SET_PROPERTY) { - setProperty(dbusMsg.arguments()); + else if (dbusMsg.member() == DBusIPCCommon::SET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QString propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (argumentsIterator.hasNext()) { + setProperty(propertyName, qdbus_cast(argumentsIterator.next()).variant()); + retVal = true; + } + } send(replyMessage); } } else if (dbusMsg.interface() == interfaceName()) { @@ -97,13 +123,13 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) if (sendReply) { send(replyMessage); } - return true; + retVal = true; } else { qCWarning(LogIpc) << "DBus request received for object which has been destroyed" << this; } } - return false; + return retVal; } IPCDBusServiceAdapterBase::IPCDBusServiceAdapterBase(DBusManagerInterface& dbusManager, QObject *parent) : diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 740874e9..789de167 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -37,12 +37,14 @@ #endif #include +#include #include "IPCServiceAdapterBase.h" #include "DBusIPCMessage.h" #include "DBusIPCCommon.h" #include "ipc-common.h" #include "FaceliftUtils.h" #include "DBusManagerInterface.h" +#include "FaceliftDBusMarshaller.h" namespace facelift { @@ -88,7 +90,7 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool handleMessage(const QDBusMessage &dbusMsg); - inline void sendPropertiesChanged(const QMap& changedProperties); + inline void sendPropertiesChanged(const QVariantMap& changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -102,11 +104,11 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda virtual IPCHandlingResult handleMethodCallMessage(DBusIPCMessage &requestMessage, DBusIPCMessage &replyMessage) = 0; - virtual void marshalPropertyValues(const QList& arguments, DBusIPCMessage &msg) = 0; + virtual QVariantMap marshalProperties() = 0; - virtual void marshalProperty(const QList& arguments, DBusIPCMessage &msg) = 0; + virtual QVariant marshalProperty(const QString& propertyName) = 0; - virtual void setProperty(const QList& arguments) = 0; + virtual void setProperty(const QString& propertyName, const QVariant& value) = 0; void registerService() override; @@ -125,23 +127,17 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); + T castFromQVariant(const QVariant& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castFromQVariantSpecialized(HelperType(), value); } template - T castFromDBusVariant(const QVariant& value) { - return castFromDBusVariantSpecialized(HelperType(), value); - } - - template - QVariant castToVariant(const T& value) { - return castToVariantSpecialized(HelperType(), value); - } - - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); + QVariant castToQVariant(const T& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castToQVariantSpecialized(HelperType(), value); } protected: @@ -156,75 +152,88 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda DBusManagerInterface& m_dbusManager; private: - template struct HelperType { }; - template - T castFromVariantSpecialized(HelperType, const QVariant& value) { + template::value, int> = 0> + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qdbus_cast(value); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList } - template - T castFromDBusVariantSpecialized(HelperType, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); + template::value, int> = 0> + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return static_cast(qdbus_cast(value)); } - QList castFromDBusVariantSpecialized(HelperType>, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList tmp = qdbus_cast>(value); + QList ret; + std::transform(tmp.begin(), tmp.end(), std::back_inserter(ret), [](const int entry){return static_cast(entry);}); + return ret; + } + + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + QMap tmp = qdbus_cast>(value); + for (const QString& key: tmp.keys()) { + ret[key] = static_cast(tmp[key]); + } + return ret; } template::value && !std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) { return QVariant::fromValue(value); } template::value && std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) { return QVariant::fromValue(static_cast(value)); } - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { - DBusObjectPath dbusObjectPath; + QVariant castToQVariantSpecialized(HelperType, const T& value) { + QString objectPath; if (value != nullptr) { - dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCDBusAdapterType>(value)->objectPath()); + objectPath = getOrCreateAdapter::type::IPCDBusAdapterType>(value)->objectPath(); } - return QVariant::fromValue(dbusObjectPath); + return QVariant::fromValue(objectPath); } - template - QVariant castToVariantSpecialized(HelperType>, const QList& value) { - QStringList /*QList*/ objectPathes; - for (T* service: value) { - objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + template::value, int> = 0> + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { + QStringList objectPathes; + for (T service: value) { + objectPathes.append(getOrCreateAdapter::type::IPCDBusAdapterType>(service)->objectPath()); } return QVariant::fromValue(objectPathes); } - template - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { - QMap objectPathesMap; + template::value, int> = 0> + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) { + QMap objectPathesMap; for (const QString& key: value.keys()) { - objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + objectPathesMap[key] = getOrCreateAdapter::type::IPCDBusAdapterType>(value[key])->objectPath(); } return QVariant::fromValue(objectPathesMap); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { QList ret; std::transform(value.begin(), value.end(), std::back_inserter(ret), [](const T& entry){return static_cast(entry);}); return QVariant::fromValue(ret); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) { QMap ret; for (const QString& key: value.keys()) { ret[key] = static_cast(value[key]); @@ -233,11 +242,15 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } }; -inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties) +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties) { DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariant::fromValue(changedProperties); + QMap convertedToDBusVariant; + for (const QString& key: changedProperties.keys()) { + convertedToDBusVariant[key] = QDBusVariant(changedProperties[key]); + } + reply << QVariant::fromValue(convertedToDBusVariant); this->send(reply); } @@ -247,7 +260,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg DBusIPCMessage signal(objectPath(), interfaceName(), signalName); using expander = int[]; (void)expander{0, - (void(signal << castToVariant(std::forward(args))), 0)... + (void(signal << castToQVariant(std::forward(args))), 0)... }; this->send(signal); } @@ -255,7 +268,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg template inline void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue) { - replyMessage << castToVariant(returnValue); + replyMessage << castToQVariant(returnValue); send(replyMessage); } diff --git a/src/ipc/ipc-common/CMakeLists.txt b/src/ipc/ipc-common/CMakeLists.txt index 3b59cfbc..e44a4723 100644 --- a/src/ipc/ipc-common/CMakeLists.txt +++ b/src/ipc/ipc-common/CMakeLists.txt @@ -1,8 +1,7 @@ -find_package(Qt5DBus REQUIRED) - facelift_add_library(FaceliftIPCCommonLib SOURCES ipc-common.cpp + DBusSignatureHelper.cpp ModuleIPCBase.cpp IPCServiceAdapterBase.cpp NotAvailableImplBase.cpp @@ -15,6 +14,7 @@ facelift_add_library(FaceliftIPCCommonLib LocalProviderBinderBase.cpp HEADERS ipc-common.h + DBusSignatureHelper.h NotAvailableImpl.h NotAvailableImplBase.h IPCProxyNewBase.h @@ -38,6 +38,5 @@ facelift_add_library(FaceliftIPCCommonLib LINK_LIBRARIES FaceliftModelLib FaceliftCommonLib - Qt5::DBus MONOLITHIC_SUPPORTED ) diff --git a/src/ipc/ipc-common/DBusSignatureHelper.cpp b/src/ipc/ipc-common/DBusSignatureHelper.cpp new file mode 100644 index 00000000..325a72fa --- /dev/null +++ b/src/ipc/ipc-common/DBusSignatureHelper.cpp @@ -0,0 +1,92 @@ +/********************************************************************** +** +** Copyright (C) 2020 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +#include "DBusSignatureHelper.h" +#include "ipc-common.h" + +void facelift::appendPropertySignature(QTextStream& s, const char* propertyName, const char* type, bool readonly) +{ + s << ""; +} + +void facelift::appendReadyProperty(QTextStream& s) +{ + s << ""; +} + +void facelift::appendDBusMethodSignature(QTextStream &s, const char* methodName, const std::list>& inputArgs, const char* outputArgType) +{ + s << ""; + for (const auto& arg: inputArgs) { + s << ""; + } + if (strlen(outputArgType) != 0) { + s << ""; + } + s << ""; +} + +void facelift::appendDBusSignalSignature(QTextStream &s, const char* signalName, const std::list>& args) +{ + s << ""; + for (const auto& arg: args) { + s << ""; + } + s << ""; +} + +void facelift::appendDBusModelSignals(QTextStream &s) +{ + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; +} diff --git a/src/ipc/ipc-common/DBusSignatureHelper.h b/src/ipc/ipc-common/DBusSignatureHelper.h new file mode 100644 index 00000000..1d6aa925 --- /dev/null +++ b/src/ipc/ipc-common/DBusSignatureHelper.h @@ -0,0 +1,48 @@ +/********************************************************************** +** +** Copyright (C) 2020 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +#pragma once + +#if defined(FaceliftIPCCommonLib_LIBRARY) +# define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT +#else +# define FaceliftIPCCommonLib_EXPORT Q_DECL_IMPORT +#endif + +#include + +namespace facelift { + +void appendPropertySignature(QTextStream& s, const char* propertyName, const char* type, bool readonly); +void appendReadyProperty(QTextStream& s); +void appendDBusMethodSignature(QTextStream &s, const char* methodName, const std::list>& inputArgs, const char* outputArgType = ""); +void appendDBusSignalSignature(QTextStream &s, const char* signalName, const std::list>& args); +void appendDBusModelSignals(QTextStream &s); +} diff --git a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h index bae9eca0..d172b171 100644 --- a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h +++ b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h @@ -30,7 +30,6 @@ #pragma once #include -#include #include "ipc-common.h" #if defined(FaceliftIPCCommonLib_LIBRARY) @@ -60,7 +59,7 @@ class IPCAdapterModelPropertyHandler for (int i = first ; i <= last ; i++) { changedItems.append(m_model->elementAt(i)); } - m_adapter.sendSignal("ModelUpdateEventDataChanged", modelPropertyName, first, changedItems); + m_adapter.sendSignal(IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME, modelPropertyName, first, changedItems); }); QObject::connect(m_model, &facelift::ModelBase::beginRemoveElements, &m_adapter, [this] (int first, int last) { m_removeFirst = first; @@ -69,7 +68,7 @@ class IPCAdapterModelPropertyHandler QObject::connect(m_model, &facelift::ModelBase::endRemoveElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_removeFirst != UNDEFINED); Q_ASSERT(m_removeLast != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventRemove", modelPropertyName, m_removeFirst, m_removeLast); + m_adapter.sendSignal(IPCCommon::MODEL_REMOVE_MESSAGE_NAME, modelPropertyName, m_removeFirst, m_removeLast); m_removeFirst = UNDEFINED; m_removeLast = UNDEFINED; }); @@ -82,7 +81,7 @@ class IPCAdapterModelPropertyHandler Q_ASSERT(m_moveSourceFirstIndex != UNDEFINED); Q_ASSERT(m_moveSourceLastIndex != UNDEFINED); Q_ASSERT(m_moveDestinationIndex != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventMove", modelPropertyName, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); + m_adapter.sendSignal(IPCCommon::MODEL_MOVE_MESSAGE_NAME, modelPropertyName, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); m_moveSourceFirstIndex = UNDEFINED; m_moveSourceLastIndex = UNDEFINED; m_moveDestinationIndex = UNDEFINED; @@ -94,7 +93,7 @@ class IPCAdapterModelPropertyHandler QObject::connect(m_model, &facelift::ModelBase::endInsertElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_insertFirst != UNDEFINED); Q_ASSERT(m_insertLast != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventInsert", modelPropertyName, m_insertFirst, m_insertLast); + m_adapter.sendSignal(IPCCommon::MODEL_INSERT_MESSAGE_NAME, modelPropertyName, m_insertFirst, m_insertLast); m_insertFirst = UNDEFINED; m_insertLast = UNDEFINED; }); @@ -103,16 +102,13 @@ class IPCAdapterModelPropertyHandler }); QObject::connect(m_model, &facelift::ModelBase::endResetModel, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_resettingModel); - m_adapter.sendSignal("ModelUpdateEventReset", modelPropertyName, m_model->size()); + m_adapter.sendSignal(IPCCommon::MODEL_RESET_MESSAGE_NAME, modelPropertyName, m_model->size()); m_resettingModel = false; }); } - void handleModelRequest(typename IPCAdapterType::InputIPCMessage &requestMessage, typename IPCAdapterType::OutputIPCMessage &replyMessage) + void handleModelRequest(int first, int last, typename IPCAdapterType::OutputIPCMessage &replyMessage) { - QListIterator argumentsIterator(requestMessage.arguments()); - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); QList list; // Make sure we do not request items which are out of range @@ -123,8 +119,8 @@ class IPCAdapterModelPropertyHandler list.append(m_model->elementAt(i)); } - replyMessage << QVariant::fromValue(first); - replyMessage << QVariant::fromValue(list); + replyMessage << m_adapter.template castToQVariant(first); + replyMessage << m_adapter.template castToQVariant(list); } private: diff --git a/src/ipc/ipc-common/IPCProxyModelProperty.h b/src/ipc/ipc-common/IPCProxyModelProperty.h index c0457ac1..34de15d8 100644 --- a/src/ipc/ipc-common/IPCProxyModelProperty.h +++ b/src/ipc/ipc-common/IPCProxyModelProperty.h @@ -30,9 +30,9 @@ #pragma once #include -#include #include "FaceliftUtils.h" #include "ModelProperty.h" +#include "ipc-common.h" #if defined(FaceliftIPCCommonLib_LIBRARY) # define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT @@ -56,14 +56,14 @@ class IPCProxyModelProperty : public facelift::ModelProperty void handleSignal(const typename IPCProxyType::InputIPCMessage &msg) { QListIterator argumentsIterator(msg.arguments()); - const QString& modelPropertyName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): QString()); Q_ASSERT(!modelPropertyName.isEmpty()); - const QString& eventName = msg.member(); + const QString& messageName = msg.member(); - if (eventName == QStringLiteral("ModelUpdateEventDataChanged")) + if (messageName == IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); int last = first + list.size() - 1; for (int i = first; i <= last; ++i) { @@ -71,38 +71,38 @@ class IPCProxyModelProperty : public facelift::ModelProperty } emit this->dataChanged(first, last); } - else if (eventName == QStringLiteral("ModelUpdateEventInsert")) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + else if (messageName == IPCCommon::MODEL_INSERT_MESSAGE_NAME) { + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginInsertElements(first, last); clear(); // TODO: insert elements in cache without clear() emit this->endInsertElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventRemove")) + else if (messageName == IPCCommon::MODEL_REMOVE_MESSAGE_NAME) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginRemoveElements(first, last); m_cache.clear(); // TODO: remove elements from cache without clear() emit this->endRemoveElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventMove")) { - int sourceFirstIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int sourceLastIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int destinationIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + else if (messageName == IPCCommon::MODEL_MOVE_MESSAGE_NAME) { + int sourceFirstIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int sourceLastIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int destinationIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); m_cache.clear(); // TODO: move elements in cache without clear() emit this->endMoveElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventReset")) { + else if (messageName == IPCCommon::MODEL_RESET_MESSAGE_NAME) { emit this->beginResetModel(); - int size = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int size = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); this->setSize(size); clear(); emit this->endResetModel(); } else { - qCWarning(LogIpc) << "Unhandled event for model property" << eventName; + qCCritical(LogIpc) << "Unhandled event for model property" << messageName; } } @@ -130,8 +130,8 @@ class IPCProxyModelProperty : public facelift::ModelProperty QList args = m_proxy.ipc()->sendMethodCallWithReturn(requestMemberID, first, last); QListIterator argumentsIterator(args); - first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); last = first + list.size() - 1; for (int i = first; i <= last; ++i) { @@ -182,8 +182,8 @@ class IPCProxyModelProperty : public facelift::ModelProperty m_proxy.ipc()->sendAsyncMethodCall(requestMemberID, facelift::AsyncAnswer>(&m_proxy, [this](QList arguments) { // qCDebug(LogIpc) << "Received model items " << first << "-" << last; QListIterator argumentsIterator(arguments); - auto first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - auto list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + auto first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + auto list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); auto last = first + list.size() - 1; for (int i = first; i <= last; ++i) { auto &newItem = list[i - first]; diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index 436e0985..cd7c84c3 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -30,7 +30,6 @@ #pragma once #include -#include #include "FaceliftModel.h" @@ -42,8 +41,6 @@ namespace facelift { -typedef QString DBusObjectPath; // potentially could be QDBusObjectPath but no empty QDBusObjectPath is allowed - class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject { Q_OBJECT @@ -110,61 +107,7 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject return serviceAdapter; } - - template - const char* typeToSignature() const - { - return typeToSignatureSpecialized(HelperType()); - } private: - template struct HelperType { }; - template::value && !std::is_enum::value, int> = 0> - const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template::value && std::is_enum::value, int> = 0> - const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - QList > m_subAdapters; QString m_objectPath; QString m_interfaceName; diff --git a/src/ipc/ipc-common/ipc-common.h b/src/ipc/ipc-common/ipc-common.h index 809fed4e..034646df 100644 --- a/src/ipc/ipc-common/ipc-common.h +++ b/src/ipc/ipc-common/ipc-common.h @@ -37,7 +37,6 @@ #endif #include - #include "FaceliftModel.h" namespace facelift { @@ -52,5 +51,16 @@ enum class IPCHandlingResult { INVALID, // Message is invalid and could not be handled }; +struct FaceliftIPCCommonLib_EXPORT IPCCommon +{ + static constexpr const char *MODEL_DATA_CHANGED_MESSAGE_NAME = "ModelUpdateEventDataChanged"; + static constexpr const char *MODEL_INSERT_MESSAGE_NAME = "ModelUpdateEventInsert"; + static constexpr const char *MODEL_REMOVE_MESSAGE_NAME = "ModelUpdateEventRemove"; + static constexpr const char *MODEL_MOVE_MESSAGE_NAME = "ModelUpdateEventMove"; + static constexpr const char *MODEL_RESET_MESSAGE_NAME = "ModelUpdateEventReset"; +}; + + + } diff --git a/src/ipc/local/FaceliftIPCCommon.h b/src/ipc/local/FaceliftIPCCommon.h index 9c121c28..3d0b5d36 100644 --- a/src/ipc/local/FaceliftIPCCommon.h +++ b/src/ipc/local/FaceliftIPCCommon.h @@ -42,11 +42,12 @@ namespace local { struct FaceliftIPCLocalLib_EXPORT FaceliftIPCCommon { - static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; - static constexpr const char *GET_PROPERTY = "Get"; - static constexpr const char *SET_PROPERTY = "Set"; - static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static constexpr const char *GET_ALL_PROPERTIES_MESSAGE_NAME = "GetAll"; + static constexpr const char *GET_PROPERTY_MESSAGE_NAME = "Get"; + static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "Set"; + static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; + static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; }; } diff --git a/src/ipc/local/LocalIPC-serialization.h b/src/ipc/local/LocalIPC-serialization.h index 3a3c7d28..848f3cde 100644 --- a/src/ipc/local/LocalIPC-serialization.h +++ b/src/ipc/local/LocalIPC-serialization.h @@ -36,7 +36,6 @@ # define FaceliftIPCLocalLib_EXPORT Q_DECL_IMPORT #endif -#include #include "LocalIPCMessage.h" #include "LocalIPCProxy.h" #include "LocalIPCServiceAdapter.h" @@ -72,7 +71,7 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac asyncCall(msg, this, [this, answer](LocalIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { - returnValue = (!msg.arguments().isEmpty() ? qvariant_cast(msg.arguments()[0]): ReturnType()); + returnValue = (!msg.arguments().isEmpty() ? qvariant_cast(msg.arguments().first()): ReturnType()); answer(returnValue); } else { qCWarning(LogIpc) << "Error received" << msg.toString(); @@ -97,10 +96,10 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac template inline void LocalIPCProxyBinder::sendSetterCall(const QString& property, const PropertyType &value) { - LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::SET_PROPERTY); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::SET_PROPERTY_MESSAGE_NAME); msg << QVariant::fromValue(m_interfaceName); msg << QVariant::fromValue(property); - msg << QVariant::fromValue(QDBusVariant(QVariant::fromValue(value))); + msg << QVariant::fromValue(QVariant::fromValue(value)); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { diff --git a/src/ipc/local/LocalIPCProxy.h b/src/ipc/local/LocalIPCProxy.h index 9ecd9353..49057cb9 100644 --- a/src/ipc/local/LocalIPCProxy.h +++ b/src/ipc/local/LocalIPCProxy.h @@ -42,8 +42,6 @@ namespace facelift { -typedef QString DBusObjectPath; - namespace local { using namespace facelift; @@ -105,47 +103,38 @@ class LocalIPCProxy : public IPCProxyBase, protected LocalIPCProx } template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); - } - - template - T castFromDBusVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), qvariant_cast(value).variant()); + T castFromQVariant(const QVariant& value) { + return castFromQVariantSpecialized(HelperType(), value); } private: template struct HelperType { }; template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qvariant_cast(value); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - return qvariant_cast(value); // workaround to use QList since its signature matches the QStringList - } - template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { - return getOrCreateSubProxy::type::IPCLocalProxyType>(qvariant_cast(value)); + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCLocalProxyType>(qvariant_cast(value)); } - template - QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { - QMap ret; - auto objectPaths = qvariant_cast>(value); + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qvariant_cast>(value); for (const QString& key: objectPaths.keys()) { - ret[key] = getOrCreateSubProxy(objectPaths[key]); + ret[key] = getOrCreateSubProxy::type::IPCLocalProxyType>(objectPaths[key]); } return ret; } - template - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - QList ret; - auto objectPaths = qvariant_cast*/>(value); - for (const DBusObjectPath& objectPath: objectPaths) { - ret.append(getOrCreateSubProxy(objectPath)); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qvariant_cast(value); + for (const QString& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy::type::IPCLocalProxyType>(objectPath)); } return ret; } diff --git a/src/ipc/local/LocalIPCProxyBase.h b/src/ipc/local/LocalIPCProxyBase.h index a0e0f426..d8476c6d 100644 --- a/src/ipc/local/LocalIPCProxyBase.h +++ b/src/ipc/local/LocalIPCProxyBase.h @@ -34,7 +34,6 @@ #include "IPCProxyBase.h" #include "LocalIPCRequestHandler.h" #include "LocalIPCProxyBinder.h" -#include #if defined(FaceliftIPCLocalLib_LIBRARY) # define FaceliftIPCLocalLib_EXPORT Q_DECL_EXPORT diff --git a/src/ipc/local/LocalIPCProxyBinder.cpp b/src/ipc/local/LocalIPCProxyBinder.cpp index 87e4db32..f593061e 100644 --- a/src/ipc/local/LocalIPCProxyBinder.cpp +++ b/src/ipc/local/LocalIPCProxyBinder.cpp @@ -37,7 +37,6 @@ #include "LocalIPCProxy.h" #include "LocalIPC-serialization.h" #include "LocalIPCRegistry.h" -#include "FaceliftIPCCommon.h" namespace facelift { @@ -127,7 +126,12 @@ void LocalIPCProxyBinder::onServerNotAvailableError(const QString& methodName) c void LocalIPCProxyBinder::onPropertiesChanged(LocalIPCMessage &msg) { - m_serviceObject->unmarshalPropertiesChanged(msg); + QListIterator argumentsIterator(msg.arguments()); + QString interfaceName = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QString()); + if (interfaceName == m_interfaceName) { + QVariantMap changedProperties = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(changedProperties); + } } LocalIPCMessage LocalIPCProxyBinder::call(LocalIPCMessage &message) const @@ -151,12 +155,13 @@ void LocalIPCProxyBinder::asyncCall(LocalIPCMessage &requestMessage, QObject *co void LocalIPCProxyBinder::requestPropertyValues() { - LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::GET_ALL_PROPERTIES); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME); msg << interfaceName(); auto replyHandler = [this](LocalIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->unmarshalPropertyValues(replyMessage); + QVariantMap values = (!replyMessage.arguments().isEmpty() ? qvariant_cast(replyMessage.arguments().first()): QVariantMap()); + m_serviceObject->unmarshalProperties(values); m_serviceObject->setServiceRegistered(true); emit serviceAvailableChanged(); } else { diff --git a/src/ipc/local/LocalIPCRequestHandler.h b/src/ipc/local/LocalIPCRequestHandler.h index 3bed1008..0f336439 100644 --- a/src/ipc/local/LocalIPCRequestHandler.h +++ b/src/ipc/local/LocalIPCRequestHandler.h @@ -60,8 +60,8 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCRequestHandler { public: - virtual void unmarshalPropertyValues(LocalIPCMessage &msg) = 0; - virtual void unmarshalPropertiesChanged(LocalIPCMessage &msg) = 0; + virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; virtual void handleSignals(LocalIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index 004439d8..742d3728 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -91,6 +91,12 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } + template + const char* typeToSignature() const + { + return ""; + } + protected: QPointer m_service; }; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.cpp b/src/ipc/local/LocalIPCServiceAdapterBase.cpp index 3b5987a8..1157e8c8 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.cpp +++ b/src/ipc/local/LocalIPCServiceAdapterBase.cpp @@ -50,14 +50,27 @@ IPCHandlingResult LocalIPCServiceAdapterBase::handleMessage(LocalIPCMessage &req bool sendReply = true; if (requestMessage.interface() == FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME) { - if (requestMessage.member() == FaceliftIPCCommon::GET_ALL_PROPERTIES) { - marshalPropertyValues(requestMessage.arguments(), replyMessage); + if (requestMessage.member() == FaceliftIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME) { + replyMessage << QVariant::fromValue(marshalProperties()); } - else if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTY) { - marshalProperty(requestMessage.arguments(), replyMessage); + else if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + // no need to check interface name in local variant + auto propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + QVariant value = marshalProperty(propertyName); + replyMessage << value; + send(replyMessage); } - else if (requestMessage.member() == FaceliftIPCCommon::SET_PROPERTY) { - setProperty(requestMessage.arguments()); + else if (requestMessage.member() == FaceliftIPCCommon::SET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QString propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (argumentsIterator.hasNext()) { + setProperty(propertyName, argumentsIterator.next()); + } + } } } else { diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 0d9f7e43..9f09527c 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -30,7 +30,6 @@ #pragma once -#include #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" #include "FaceliftIPCCommon.h" @@ -63,7 +62,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA IPCHandlingResult handleMessage(LocalIPCMessage &message); - inline void sendPropertiesChanged(const QMap &changedProperties); + inline void sendPropertiesChanged(const QVariantMap &changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -75,11 +74,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA virtual IPCHandlingResult handleMethodCallMessage(LocalIPCMessage &requestMessage, LocalIPCMessage &replyMessage) = 0; - virtual void marshalPropertyValues(const QList& arguments, LocalIPCMessage &msg) = 0; + virtual QVariantMap marshalProperties() = 0; - virtual void marshalProperty(const QList& arguments, LocalIPCMessage &msg) = 0; + virtual QVariant marshalProperty(const QString& propertyName) = 0; - virtual void setProperty(const QList& arguments) = 0; + virtual void setProperty(const QString& propertyName, const QVariant& value) = 0; void registerService() override; @@ -104,61 +103,42 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA } template - T castFromVariant(const QVariant& value) { + T castFromQVariant(const QVariant& value) { return qvariant_cast(value); } - template - T castFromDBusVariant(const QVariant& value) { - return qvariant_cast(qvariant_cast(value).variant()); - } - - template::value && !std::is_enum::value, int> = 0> - QVariant castToVariant(const T& value) { + template::value, int> = 0> + QVariant castToQVariant(const T& value) { return QVariant::fromValue(value); } - QVariant castToVariant(const QList& value) { - return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList - } - - template::value && std::is_enum::value, int> = 0> - QVariant castToVariant(const T& value) { - return QVariant::fromValue(static_cast(value)); - } - template::value, int> = 0> - QVariant castToVariant(const T& value) { - DBusObjectPath dbusObjectPath; + QVariant castToQVariant(const T& value) { + QString objectPath; if (value != nullptr) { - dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCLocalAdapterType>(value)->objectPath()); + objectPath = getOrCreateAdapter::type::IPCLocalAdapterType>(value)->objectPath(); } - return QVariant::fromValue(dbusObjectPath); + return QVariant::fromValue(objectPath); } - template - QVariant castToVariant(const QList& value) { - QStringList /*QList*/ objectPathes; - for (T* service: value) { - objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + template::value, int> = 0> + QVariant castToQVariant(const QList& value) { + QStringList objectPathes; + for (T service: value) { + objectPathes.append(getOrCreateAdapter::type::IPCLocalAdapterType>(service)->objectPath()); } return QVariant::fromValue(objectPathes); } - template - QVariant castToVariant(const QMap& value) { - QMap objectPathesMap; + template::value, int> = 0> + QVariant castToQVariant(const QMap& value) { + QMap objectPathesMap; for (const QString& key: value.keys()) { - objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + objectPathesMap[key] = getOrCreateAdapter::type::IPCLocalAdapterType>(value[key])->objectPath(); } return QVariant::fromValue(objectPathesMap); } - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); - } - protected: QString m_introspectionData; @@ -169,7 +149,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA bool m_alreadyInitialized = false; }; -inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties ) +inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties ) { LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index 65325977..83131aeb 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -1,10 +1,4 @@ -set(QtDBusDependency "") -if(FACELIFT_DBUS_IPC_ENABLED) -find_package(Qt5DBus REQUIRED) -set(QtDBusDependency "Qt5::DBus") -endif() - facelift_add_library(FaceliftModelLib SOURCES StructureBase.cpp @@ -87,7 +81,6 @@ facelift_add_library(FaceliftModelLib LINK_LIBRARIES Qt5::Qml Qt5::Quick - ${QtDBusDependency} FaceliftCommonLib MONOLITHIC_SUPPORTED ) diff --git a/src/model/FaceliftEnum.h b/src/model/FaceliftEnum.h index c581ff20..df45946d 100644 --- a/src/model/FaceliftEnum.h +++ b/src/model/FaceliftEnum.h @@ -39,78 +39,6 @@ #include "FaceliftCommon.h" #include #include -#include -#ifdef DBUS_IPC_ENABLED -#include - -template -class QDBusEnumMarshal; - -template -class QDBusEnumMarshal::value>::type> -{ -public: - static QDBusArgument& marshal(QDBusArgument &argument, const T& source) - { - argument << static_cast(source); - return argument; - } - - static const QDBusArgument& unmarshal(const QDBusArgument &argument, T &source) - { - int tmp; - argument >> tmp; - source = static_cast(tmp); - return argument; - } -}; - -template -QDBusArgument& operator<<(QDBusArgument &argument, const T& source) -{ - return QDBusEnumMarshal::marshal(argument, source); -} - -template -const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) -{ - return QDBusEnumMarshal::unmarshal(argument, source); -} -#endif - -template -class QDataStreamMarshal; - -template -class QDataStreamMarshal::value>::type> -{ -public: - static QDataStream& marshal(QDataStream &dataStream, const T& source) - { - dataStream << static_cast(source); - return dataStream; - } - - static const QDataStream& unmarshal(QDataStream &dataStream, T &source) - { - int value; - dataStream >> value; - source = static_cast(value); - return dataStream; - } -}; - -template -inline QDataStream& operator<<(QDataStream &dataStream, const T& source) -{ - return QDataStreamMarshal::marshal(dataStream, source); -} - -template -inline const QDataStream& operator>>(QDataStream &dataStream, T &source) -{ - return QDataStreamMarshal::unmarshal(dataStream, source); -} namespace facelift { diff --git a/tests/combined/check_combined.js b/tests/combined/check_combined.js index c93e9c9a..460dcb30 100644 --- a/tests/combined/check_combined.js +++ b/tests/combined/check_combined.js @@ -42,6 +42,8 @@ function defaults() { compare(api.structProperty2.cs.aString, ""); compare(api.structProperty2.e, 0); + compare(api.structWithExtDependency.otherEnums, []); + compare(api.intListProperty, []); compare(api.boolListProperty.length, 0); compare(api.enumListProperty.length, 0); @@ -66,6 +68,8 @@ function initialized() { compare(api.structProperty2.cs.aString, "ok"); compare(api.structProperty2.e, 1); + compare(api.structWithExtDependency.otherEnums[0], 1); + compare(api.intListProperty.length, 5); compare(api.intListProperty[2], 3); compare(api.boolListProperty.length, 3); @@ -85,6 +89,8 @@ function initialized() { compare(api.intMapProperty.one, 1); compare(api.intMapProperty.two, 2); + + compare(api.emptyString, ""); } function methods() { @@ -119,6 +125,8 @@ function methods() { os.ival = 101; compare(api.method7(os), OtherEnum.O3); + compare(api.listOfAnotherEnums()[0], OtherEnum.O2); + if (!api.qmlImplementationUsed) { api.interfaceProperty.doSomething(); compare(api.otherInterfaceProperty.otherMethod(OtherEnum.O3), "O3"); @@ -128,6 +136,9 @@ function methods() { asyncResult.answer = result; }); tryCompare(asyncResult, "answer", 42); + + api.interfaceMapProperty["key1"].doSomething(); + api.interfaceListProperty[0].doSomething(); } } diff --git a/tests/combined/impl/cpp/CombinedTestsCppImplementation.h b/tests/combined/impl/cpp/CombinedTestsCppImplementation.h index b14c4c9b..a62cd4c1 100644 --- a/tests/combined/impl/cpp/CombinedTestsCppImplementation.h +++ b/tests/combined/impl/cpp/CombinedTestsCppImplementation.h @@ -100,9 +100,17 @@ class CombinedInterfaceImplementation : public CombinedInterfaceImplementationBa s2.sete(CombiEnum::E2); m_structProperty2 = s2; + StructWithExtDependency structWithExtDep; + structWithExtDep.setotherEnums({OtherEnum::O2}); + structWithExtDep.setotherEnumMap({{"O1", OtherEnum::O1}, {"O2", OtherEnum::O2}}); + m_structWithExtDependency.setValue(structWithExtDep); + m_interfaceProperty.setValue(new CombinedInterface2Implementation(this, "#7")); m_otherInterfaceProperty.setValue(new OtherInterfaceImplementation(this)); + m_interfaceListProperty.addElement(new CombinedInterface2Implementation(this, "")); + m_interfaceMapProperty = facelift::Map({{"key1", new CombinedInterface2Implementation(this, "blabla")}}); + m_intListProperty = { 1, 2, 3, 5, 8 }; m_boolListProperty = { false, true, true }; m_enumListProperty = { CombiEnum::E2 }; @@ -239,4 +247,15 @@ class CombinedInterfaceImplementation : public CombinedInterfaceImplementationBa return OtherEnum::O3; return OtherEnum::O1; } + + HugeStruct hungryBeast(const tests::combined::HugeStruct& hugeStruct) override + { + return hugeStruct; + } + + QList listOfAnotherEnums() override + { + QList anotherEnums{tests::combined::another::AnotherEnum::O2}; + return anotherEnums; + } }; diff --git a/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml b/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml index a520400d..ce075e33 100644 --- a/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml +++ b/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml @@ -100,6 +100,10 @@ CombinedInterfaceImplementationBase { return OtherEnum.O1; } + listOfAnotherEnums: function() { + return [OtherEnum.O2]; + } + initialize: function() { enumProperty = CombiEnum.E2; @@ -112,6 +116,9 @@ CombinedInterfaceImplementationBase { structProperty2.cs.aString = "ok"; structProperty2.e = CombiEnum.E2; + structWithExtDependency.otherEnums = [OtherEnum.O2]; + structWithExtDependency.otherEnumMap = {"O1": OtherEnum.O1, "O2": OtherEnum.O2}; + intListProperty = [ 1, 2, 3, 5, 8 ]; boolListProperty = [ false, true, true ]; enumListProperty = [ CombiEnum.E2 ]; diff --git a/tests/combined/interface/another.qface b/tests/combined/interface/another.qface new file mode 100644 index 00000000..aa9ef41f --- /dev/null +++ b/tests/combined/interface/another.qface @@ -0,0 +1,37 @@ +/********************************************************************** +** +** Copyright (C) 2018 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +module tests.combined.another 1.0 + +enum AnotherEnum { + O1, + O2, + O3 +} diff --git a/tests/combined/interface/combined.qface b/tests/combined/interface/combined.qface index 1ae09edc..af4a77fa 100644 --- a/tests/combined/interface/combined.qface +++ b/tests/combined/interface/combined.qface @@ -30,6 +30,7 @@ module tests.combined 1.0 import tests.combined.other 1.0 +import tests.combined.another 1.0 @ipc-async: true @ipc-sync: true @@ -45,6 +46,7 @@ interface CombinedInterface { int intProperty; CombiStruct structProperty; CombiStruct2 structProperty2; + StructWithExtDependency structWithExtDependency; readonly CombinedInterface2 interfaceProperty; readonly list interfaceListProperty; @@ -79,7 +81,15 @@ interface CombinedInterface { signal eventBoolAndCombiStruct(bool p, CombiStruct q); signal eventWithList(list p, bool q); signal eventWithMap(map p); - signal eventWithStructWithList(StructWithList p) + signal eventWithStructWithList(StructWithList p); + + list listOfAnotherEnums(); + + readonly string emptyString; // check QVariant delivery + + OversizedStruct oversizedStruct; + HugeStruct hugeStruct; + HugeStruct hungryBeast(HugeStruct hugeStruct); } @ipc-async: true @@ -98,6 +108,14 @@ struct CombiStruct2 { CombiEnum e; } +struct StructWithExtDependency { + string aString; + int anInt; + tests.combined.other.OtherStruct otherStruct; + list otherEnums; + map otherEnumMap; +} + struct StructWithList { list listOfInts; list listOfStructs; @@ -109,3 +127,38 @@ enum CombiEnum { E2, E3, } + +struct FirstLevel { +string someString; +int someInt; +bool someBool; +string someOtherString; +int someOtherInt; +bool someOtherBool; +} + +struct SecondLevel { +FirstLevel firstLevel; +FirstLevel anotherfirstLevel; +FirstLevel yetAnotherFirstLevel; +} + +struct ThirdLevel { +SecondLevel secondLevel; +SecondLevel anotherSecondLevel; +SecondLevel yetAnotherSecondLevel; +} + +struct HugeStruct { + ThirdLevel thirdLevel; + ThirdLevel anotherThirdLevel; + ThirdLevel yetAnotherThirdLevel; +} + +@toByteArrayOverDBus: true +struct OversizedStruct { +ThirdLevel thirdLevel; +ThirdLevel anotherThirdLevel; +ThirdLevel yetAnotherThirdLevel; +ThirdLevel theKiller; +} diff --git a/tests/combined/interface/other.qface b/tests/combined/interface/other.qface index 512461b2..2e78260d 100644 --- a/tests/combined/interface/other.qface +++ b/tests/combined/interface/other.qface @@ -29,6 +29,7 @@ **********************************************************************/ module tests.combined.other 1.0 +import tests.combined.another 1.0 @ipc-async: true @ipc-sync: true @@ -44,6 +45,8 @@ interface OtherInterface { struct OtherStruct { string str; int ival; + tests.combined.another.AnotherEnum anotherenum; + OtherEnum otherEnum; } enum OtherEnum { diff --git a/tests/models/interface/models.qface b/tests/models/interface/models.qface index c183c520..2ce5297a 100644 --- a/tests/models/interface/models.qface +++ b/tests/models/interface/models.qface @@ -76,7 +76,7 @@ struct HugeStruct { ThirdLevel yetAnotherThirdLevel; } -@serializeOverIPC: true +@toByteArrayOverDBus: true struct OversizedStruct { ThirdLevel thirdLevel; ThirdLevel anotherThirdLevel; diff --git a/tests/objectregistry/client.cpp b/tests/objectregistry/client.cpp index 30d94104..b224e4ac 100644 --- a/tests/objectregistry/client.cpp +++ b/tests/objectregistry/client.cpp @@ -30,8 +30,8 @@ #include "client.h" #include #include "DBusManager.h" -#include "DBusIPCMessage.h" #include "DBusIPCCommon.h" +#include "DBusIPCMessage.h" #include void tests::ipc::Tester::registerAnotherAdapter() From 3ed6fe9e70058a54e924f1bcd2a72722e9993a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Wed, 7 Oct 2020 17:28:35 +0200 Subject: [PATCH 08/12] enable defining bus address --- src/ipc/dbus/DBusIPCProxyBinder.cpp | 39 +++++++++++-------- src/ipc/dbus/DBusIPCProxyBinder.h | 3 ++ src/ipc/dbus/DBusManager.cpp | 19 +-------- src/ipc/dbus/DBusManager.h | 17 -------- src/ipc/dbus/DBusManagerInterface.h | 4 -- src/ipc/dbus/DBusObjectRegistry.cpp | 8 ++-- src/ipc/dbus/DBusObjectRegistry.h | 4 +- src/ipc/dbus/IPCDBusServiceAdapter.h | 14 ++++++- src/ipc/dbus/IPCDBusServiceAdapterBase.cpp | 19 ++++----- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 3 +- src/ipc/ipc-common/IPCProxy.h | 1 + src/ipc/ipc-common/IPCProxyBinderBase.cpp | 6 +++ src/ipc/ipc-common/IPCProxyBinderBase.h | 9 ++++- src/ipc/ipc-common/IPCServiceAdapterBase.h | 2 +- .../ipc-common/NewIPCServiceAdapterBase.cpp | 14 ++++++- src/ipc/ipc-common/NewIPCServiceAdapterBase.h | 18 +++++++++ src/ipc/local/LocalIPCServiceAdapter.h | 4 +- tests/objectregistry/client.cpp | 3 +- 18 files changed, 106 insertions(+), 81 deletions(-) diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 6f62ff5d..6c81fb99 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -39,7 +39,8 @@ namespace dbus { DBusIPCProxyBinder::DBusIPCProxyBinder(DBusManagerInterface& dbusManager, InterfaceBase &owner, QObject *parent) : IPCProxyBinderBase(owner, parent), - m_dbusManager(dbusManager) + m_dbusManager(dbusManager), + m_connection(QDBusConnection::sessionBus()) { m_busWatcher.setWatchMode(QDBusServiceWatcher::WatchForRegistration); } @@ -110,22 +111,20 @@ void DBusIPCProxyBinder::requestPropertyValues() void DBusIPCProxyBinder::onServiceNameKnown() { - auto& connection = m_dbusManager.connection(); - - auto successPropertyChangeSignal = connection.connect(m_serviceName, + auto successPropertyChangeSignal = m_connection.connect(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); Q_UNUSED(successPropertyChangeSignal); // TODO: check for (const QString& signalEntry: m_serviceObject->getSignals()) { - auto signalConnected = connection.connect(m_serviceName, + auto signalConnected = m_connection.connect(m_serviceName, objectPath(), m_interfaceName, signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); Q_UNUSED(signalConnected) // TODO: check } m_busWatcher.addWatchedService(m_serviceName); - m_busWatcher.setConnection(connection); + m_busWatcher.setConnection(m_connection); QObject::connect(&m_busWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this](){ requestPropertyValues(); }); @@ -143,21 +142,19 @@ void DBusIPCProxyBinder::checkRegistry() if (serviceName != m_serviceName) { m_serviceName = serviceName; - if (!m_serviceName.isEmpty() && !m_interfaceName.isEmpty() && m_dbusManager.isDBusConnected()) { + if (!m_serviceName.isEmpty() && !m_interfaceName.isEmpty() && m_connection.isConnected()) { onServiceNameKnown(); } } } else if (!m_serviceName.isEmpty()){ // no point to proceed on empty service name m_busWatcher.removeWatchedService(m_serviceName); - auto& connection = m_dbusManager.connection(); - - connection.disconnect(m_serviceName, + m_connection.disconnect(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); for (const QString& signalEntry: m_serviceObject->getSignals()) { - connection.disconnect(m_serviceName, + m_connection.disconnect(m_serviceName, objectPath(), interfaceName(), signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); } @@ -175,9 +172,8 @@ void DBusIPCProxyBinder::handleGenericSignals(const QDBusMessage& msg) void DBusIPCProxyBinder::asyncCall(DBusIPCMessage &message, const QObject *context, std::function callback) { - auto& connection = m_dbusManager.connection(); qCDebug(LogIpc) << "Sending async IPC message : " << message.toString(); - auto reply = new QDBusPendingCallWatcher(connection.asyncCall(message.outputMessage())); + auto reply = new QDBusPendingCallWatcher(m_connection.asyncCall(message.outputMessage())); QObject::connect(reply, &QDBusPendingCallWatcher::finished, context, [callback, reply]() { DBusIPCMessage msg(reply->reply()); if (msg.isReplyMessage()) { @@ -189,19 +185,30 @@ void DBusIPCProxyBinder::asyncCall(DBusIPCMessage &message, const QObject *conte DBusIPCMessage DBusIPCProxyBinder::call(DBusIPCMessage &message) const { - auto& connection = m_dbusManager.connection(); qCDebug(LogIpc) << "Sending blocking IPC message : " << message.toString(); - auto replyDbusMessage = connection.call(message.outputMessage()); + auto replyDbusMessage = m_connection.call(message.outputMessage()); DBusIPCMessage reply(replyDbusMessage); return reply; } void DBusIPCProxyBinder::setObjectPath(const QString &objectPath) { - m_dbusManager.objectRegistry().objects(false).addListener(objectPath, this, &DBusIPCProxyBinder::checkRegistry); + if (!m_explicitServiceName) { + m_dbusManager.objectRegistry().objects(false).addListener(objectPath, this, &DBusIPCProxyBinder::checkRegistry); + } IPCProxyBinderBase::setObjectPath(objectPath); } +void DBusIPCProxyBinder::setAddress(const QString& address) +{ + if (!address.isEmpty()) { + m_connection = QDBusConnection::connectToBus(address, address); + if (!m_connection.isConnected()) { + qFatal("Can't connect to DBUS at address: %s", qPrintable(address)); + } + IPCProxyBinderBase::setAddress(address); + } +} void DBusIPCProxyBinder::bindToIPC() { if (m_explicitServiceName) { diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index c10fd53d..b35b83d8 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -72,6 +72,8 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void setObjectPath(const QString &objectPath) override; + void setAddress(const QString& address) override; + void setInterfaceName(const QString &name); Q_SLOT void onPropertiesChanged(const QDBusMessage &dbusMessage); @@ -223,6 +225,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase DBusRequestHandler *m_serviceObject = nullptr; bool m_serviceAvailable = false; DBusManagerInterface &m_dbusManager; + QDBusConnection m_connection; }; diff --git a/src/ipc/dbus/DBusManager.cpp b/src/ipc/dbus/DBusManager.cpp index 2f6dcb77..9cd9a2ab 100644 --- a/src/ipc/dbus/DBusManager.cpp +++ b/src/ipc/dbus/DBusManager.cpp @@ -34,12 +34,8 @@ namespace facelift { namespace dbus { -DBusManager::DBusManager() : m_busConnection(QDBusConnection::sessionBus()) +DBusManager::DBusManager() { - m_dbusConnected = m_busConnection.isConnected(); - if (!m_dbusConnected) { - qCCritical(LogIpc) << "NOT connected to DBUS"; - } } DBusManager &DBusManager::instance() @@ -65,18 +61,5 @@ DBusObjectRegistry &DBusManager::objectRegistry() return *m_objectRegistry; } -bool DBusManager::registerServiceName(const QString &serviceName) -{ - qCDebug(LogIpc) << "Registering serviceName " << serviceName; - auto success = m_busConnection.registerService(serviceName); - return success; -} - -QString DBusManager::serviceName() const -{ - return m_busConnection.baseService(); -} - - } // end namespace dbus } // end namespace facelift diff --git a/src/ipc/dbus/DBusManager.h b/src/ipc/dbus/DBusManager.h index 3fffed5f..191619a8 100644 --- a/src/ipc/dbus/DBusManager.h +++ b/src/ipc/dbus/DBusManager.h @@ -57,27 +57,10 @@ class FaceliftIPCLibDBus_EXPORT DBusManager : public DBusManagerInterface static DBusManager &instance(); - bool isDBusConnected() const override - { - return m_dbusConnected; - } - - bool registerServiceName(const QString &serviceName) override; - - QDBusConnection &connection() override - { - return m_busConnection; - } - - QString serviceName() const override; - DBusObjectRegistry &objectRegistry() override; private: - QDBusConnection m_busConnection; DBusObjectRegistry *m_objectRegistry = nullptr; - bool m_dbusConnected = false; - // singleton DBusManager(); }; diff --git a/src/ipc/dbus/DBusManagerInterface.h b/src/ipc/dbus/DBusManagerInterface.h index 08d761ee..d2bdf289 100644 --- a/src/ipc/dbus/DBusManagerInterface.h +++ b/src/ipc/dbus/DBusManagerInterface.h @@ -48,10 +48,6 @@ class FaceliftIPCLibDBus_EXPORT DBusManagerInterface { public: virtual ~DBusManagerInterface() = default; - virtual bool isDBusConnected() const = 0; - virtual bool registerServiceName(const QString &serviceName) = 0; - virtual QDBusConnection &connection() = 0; - virtual QString serviceName() const = 0; virtual DBusObjectRegistry &objectRegistry() = 0; }; diff --git a/src/ipc/dbus/DBusObjectRegistry.cpp b/src/ipc/dbus/DBusObjectRegistry.cpp index d91a4ccc..dfcc14bb 100644 --- a/src/ipc/dbus/DBusObjectRegistry.cpp +++ b/src/ipc/dbus/DBusObjectRegistry.cpp @@ -53,7 +53,7 @@ void DBusObjectRegistry::init() { if (!m_initialized) { m_initialized = true; - if (!m_dbusManager.isDBusConnected() || m_dbusManager.registerServiceName(m_serviceName)) { + if (!QDBusConnection::sessionBus().isConnected() || QDBusConnection::sessionBus().registerService(m_serviceName)) { m_master = std::make_unique(); m_master->init(); QObject::connect(m_master.get(), &MasterImpl::objectAdded, this, &DBusObjectRegistry::onObjectAdded); @@ -73,10 +73,9 @@ void DBusObjectRegistry::init() } } -void DBusObjectRegistry::registerObject(const QString &objectPath, facelift::AsyncAnswer answer) +void DBusObjectRegistry::registerObject(const QString &objectPath, const QString& serviceName, facelift::AsyncAnswer answer) { init(); - auto serviceName = m_dbusManager.serviceName(); if (isMaster()) { auto isSuccessful = m_master->registerObject(objectPath, serviceName); answer(isSuccessful); @@ -85,10 +84,9 @@ void DBusObjectRegistry::registerObject(const QString &objectPath, facelift::Asy } } -void DBusObjectRegistry::unregisterObject(const QString &objectPath) +void DBusObjectRegistry::unregisterObject(const QString &objectPath, const QString& serviceName) { init(); - auto serviceName = m_dbusManager.serviceName(); if (isMaster()) { m_master->unregisterObject(objectPath, serviceName); } else { diff --git a/src/ipc/dbus/DBusObjectRegistry.h b/src/ipc/dbus/DBusObjectRegistry.h index dabd46c0..9b489b88 100644 --- a/src/ipc/dbus/DBusObjectRegistry.h +++ b/src/ipc/dbus/DBusObjectRegistry.h @@ -74,9 +74,9 @@ class FaceliftIPCLibDBus_EXPORT DBusObjectRegistry : public QObject DBusObjectRegistry(DBusManagerInterface &dbusManager); - void registerObject(const QString &objectPath, facelift::AsyncAnswer answer); + void registerObject(const QString &objectPath, const QString& serviceName, facelift::AsyncAnswer answer); - void unregisterObject(const QString &objectPath); + void unregisterObject(const QString &objectPath, const QString& serviceName); const Registry& objects(bool blocking); diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index 0447b6dd..b5fb02a2 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -86,8 +86,20 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase return m_service; } - void registerService(const QString &objectPath, InterfaceBase* serverObject) override { + void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase* serverObject) override { Q_ASSERT(qobject_cast(serverObject) != nullptr); + if (address.isEmpty()) { + m_connection = QDBusConnection::sessionBus(); + } + else { + m_connection = QDBusConnection::connectToBus(address, address); + } + if (m_connection.isConnected()) { + m_connection.registerService(serviceName); + } + else { + qCCritical(LogIpc()) << "Not connected to DBUS at address:" << (address.isEmpty() ? QStringLiteral("session bus"): address); + } registerService(objectPath, static_cast(serverObject)); } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp index 6e65a310..b3541b14 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp @@ -135,7 +135,8 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) IPCDBusServiceAdapterBase::IPCDBusServiceAdapterBase(DBusManagerInterface& dbusManager, QObject *parent) : IPCServiceAdapterBase(parent), m_dbusVirtualObject(*this), - m_dbusManager(dbusManager) + m_dbusManager(dbusManager), + m_connection(QDBusConnection::sessionBus()) { } @@ -147,7 +148,7 @@ void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage void IPCDBusServiceAdapterBase::send(DBusIPCMessage &message) { qCDebug(LogIpc) << "Sending IPC message : " << message.toString(); - bool successful = m_dbusManager.connection().send(message.outputMessage()); + bool successful = m_connection.send(message.outputMessage()); Q_ASSERT(successful); } @@ -178,9 +179,9 @@ QString IPCDBusServiceAdapterBase::introspect(const QString &path) const void IPCDBusServiceAdapterBase::unregisterService() { if (m_alreadyInitialized) { - m_dbusManager.connection().unregisterObject(objectPath()); + m_connection.unregisterObject(objectPath()); qCDebug(LogIpc) << "Unregistered IPCDBusServiceAdapter object at " << objectPath(); - m_dbusManager.objectRegistry().unregisterObject(objectPath()); + m_dbusManager.objectRegistry().unregisterObject(objectPath(), m_connection.baseService()); m_alreadyInitialized = false; } } @@ -188,19 +189,15 @@ void IPCDBusServiceAdapterBase::unregisterService() void IPCDBusServiceAdapterBase::registerService() { if (!m_alreadyInitialized) { - if (m_dbusManager.isDBusConnected()) { - - if (!m_serviceName.isEmpty()) { - m_dbusManager.registerServiceName(m_serviceName); - } + if (m_connection.isConnected()) { qCDebug(LogIpc) << "Registering IPCDBusServiceAdapter object at " << objectPath(); - m_alreadyInitialized = m_dbusManager.connection().registerVirtualObject(objectPath(), &m_dbusVirtualObject); + m_alreadyInitialized = m_connection.registerVirtualObject(objectPath(), &m_dbusVirtualObject); if (!m_alreadyInitialized) { qFatal("Could not register service at object path '%s'", qPrintable(objectPath())); } - m_dbusManager.objectRegistry().registerObject(objectPath(), facelift::AsyncAnswer(this, [](bool isSuccessful) { + m_dbusManager.objectRegistry().registerObject(objectPath(), m_connection.baseService(), facelift::AsyncAnswer(this, [](bool isSuccessful) { Q_ASSERT(isSuccessful); })); } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 789de167..3489d309 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -144,13 +144,14 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda DBusVirtualObject m_dbusVirtualObject; QString m_introspectionData; - QString m_serviceName; bool m_previousReadyState = false; bool m_signalsConnected = false; bool m_alreadyInitialized = false; DBusManagerInterface& m_dbusManager; + QDBusConnection m_connection; + QString m_address; private: template::value, int> = 0> T castFromQVariantSpecialized(HelperType, const QVariant& value) { diff --git a/src/ipc/ipc-common/IPCProxy.h b/src/ipc/ipc-common/IPCProxy.h index 37b8836b..15948990 100644 --- a/src/ipc/ipc-common/IPCProxy.h +++ b/src/ipc/ipc-common/IPCProxy.h @@ -75,6 +75,7 @@ class IPCProxy : public WrapperType, public IPCProxyNewBase void enableBinder(IPCProxyBinderBase * ipcBinder) { ipcBinder->setObjectPath(ipc()->objectPath()); + ipcBinder->setAddress(ipc()->address()); const auto &serviceName = ipc()->serviceName(); if (!serviceName.isEmpty()) { ipcBinder->setServiceName(serviceName); diff --git a/src/ipc/ipc-common/IPCProxyBinderBase.cpp b/src/ipc/ipc-common/IPCProxyBinderBase.cpp index 33b6e0b8..7584727f 100644 --- a/src/ipc/ipc-common/IPCProxyBinderBase.cpp +++ b/src/ipc/ipc-common/IPCProxyBinderBase.cpp @@ -83,6 +83,12 @@ void IPCProxyBinderBase::setObjectPath(const QString &objectPath) checkInit(); } +void IPCProxyBinderBase::setAddress(const QString& address) +{ + m_address = address; + checkInit(); +} + bool IPCProxyBinderBase::isServiceAvailable() const { Q_ASSERT(false); // TODO: remove return true; diff --git a/src/ipc/ipc-common/IPCProxyBinderBase.h b/src/ipc/ipc-common/IPCProxyBinderBase.h index 40244750..11df58eb 100644 --- a/src/ipc/ipc-common/IPCProxyBinderBase.h +++ b/src/ipc/ipc-common/IPCProxyBinderBase.h @@ -48,6 +48,7 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName) + Q_PROPERTY(QString address READ address WRITE setAddress) IPCProxyBinderBase(InterfaceBase &owner, QObject *parent); @@ -70,9 +71,14 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject return m_objectPath; } - virtual void setObjectPath(const QString &objectPath); + inline const QString& address() + { + return m_address; + } + virtual void setAddress(const QString& address); + void onComponentCompleted(); void checkInit(); @@ -140,6 +146,7 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject InterfaceBase &m_owner; bool m_alreadyInitialized = false; bool m_enabled = true; + QString m_address; bool m_componentCompleted = false; bool m_isSynchronous = true; }; diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index cd7c84c3..90709bc7 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -74,7 +74,7 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject m_objectPath = objectPath; } - virtual void registerService(const QString &objectPath, InterfaceBase* serverObject) = 0; + virtual void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase* serverObject) = 0; virtual void unregisterService() = 0; diff --git a/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp b/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp index d35c1697..0f5ece85 100644 --- a/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp +++ b/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp @@ -59,7 +59,7 @@ void NewIPCServiceAdapterBase::registerService() registerLocalService(); createAdapters(); for (auto& ipcAdapter : m_ipcServiceAdapters) { - ipcAdapter->registerService(objectPath(), service()); + ipcAdapter->registerService(objectPath(), address(), serviceName(), service()); } } @@ -85,6 +85,18 @@ void NewIPCServiceAdapterBase::onValueChanged() } } +void NewIPCServiceAdapterBase::setAddress(const QString &address) +{ + m_address = address; + onValueChanged(); +} + +void NewIPCServiceAdapterBase::setServiceName(const QString& serviceName) +{ + m_serviceName = serviceName; + onValueChanged(); +} + void NewIPCServiceAdapterBase::setEnabled(bool enabled) { m_enabled = enabled; diff --git a/src/ipc/ipc-common/NewIPCServiceAdapterBase.h b/src/ipc/ipc-common/NewIPCServiceAdapterBase.h index 00bd55a4..9cce7de0 100644 --- a/src/ipc/ipc-common/NewIPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/NewIPCServiceAdapterBase.h @@ -53,6 +53,8 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject Q_PROPERTY(QObject * service READ service WRITE checkedSetService) Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) + Q_PROPERTY(QString address READ address WRITE setAddress) + Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName) NewIPCServiceAdapterBase(InterfaceManagerInterface& interfaceManager, QObject *parent); @@ -63,6 +65,20 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject return m_enabled; } + const QString& address() const + { + return m_address; + } + + const QString& serviceName() const + { + return m_serviceName; + } + + void setAddress(const QString& address); + + void setServiceName(const QString& serviceName); + void setEnabled(bool enabled); void checkedSetService(QObject *service); @@ -138,6 +154,8 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject bool m_enabled = true; bool m_providerReady = false; bool m_registered = false; + QString m_address; + QString m_serviceName; InterfaceManagerInterface& m_interfaceManager; }; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index 742d3728..6168ec95 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -85,8 +85,10 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase return m_service; } - void registerService(const QString &objectPath, InterfaceBase *serverObject) override + void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase *serverObject) override { + Q_UNUSED(serviceName) + Q_UNUSED(address) Q_ASSERT(qobject_cast(serverObject) != nullptr); registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } diff --git a/tests/objectregistry/client.cpp b/tests/objectregistry/client.cpp index b224e4ac..26049d33 100644 --- a/tests/objectregistry/client.cpp +++ b/tests/objectregistry/client.cpp @@ -36,13 +36,12 @@ void tests::ipc::Tester::registerAnotherAdapter() { - auto &manager = facelift::dbus::DBusManager::instance(); facelift::dbus::DBusIPCMessage msg( facelift::dbus::DBusIPCCommon::DEFAULT_SERVICE_NAME, m_async->ipc()->objectPath(), tests::ipc::IPCTestInterfaceAsyncIPCProxy::FULLY_QUALIFIED_INTERFACE_NAME, "registerOtherIPCTestInterface"); - manager.connection().call(msg.outputMessage()); + QDBusConnection::sessionBus().call(msg.outputMessage()); } void tests::ipc::Tester::runTest() From 92e7677b8c050d4ffb34c480294cd2185c7d86b9 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Thu, 8 Oct 2020 22:35:17 +0200 Subject: [PATCH 09/12] fix more review comments use QLatin1String more often --- .../IPCDBusServiceAdapter.template.h | 2 +- .../templates/IPCProxyAdapter.template.cpp | 77 +++++++++---------- .../templates/IPCServiceAdapter.template.cpp | 18 ++--- .../templates/IPCServiceAdapter.template.h | 2 +- 4 files changed, 48 insertions(+), 51 deletions(-) diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index 3d5f0cf5..1bedc2e5 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -102,7 +102,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{ comma() }}{{parameter.interfaceCppType}} {{parameter.name}} {%- endfor -%} ) { - sendSignal("{{event}}" + sendSignal(QLatin1String("{{event}}") {%- for parameter in event.parameters -%} , {{parameter.name}} {%- endfor -%} ); diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 34929979..18e2923b 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -53,50 +53,47 @@ void {{className}}::unmarshalProperties(const QVariantMap& values) { - QMap emitChangeSignal; - for (const QString &propertyName: values.keys()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_interface %} - const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); - emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% elif property.type.is_model %} - emitChangeSignal[QStringLiteral("{{property.name}}")] = true; - int {{property.name}}Size = castFromQVariant(values[propertyName]); - m_{{property.name}}.beginResetModel(); - m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); - m_{{property.name}}.endResetModel(); - {% else %} - const auto previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); - emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% endif %} - } - {% endfor %} - if (propertyName == QStringLiteral("ready")) { - bool previousIsReady = this->ready(); - m_serviceReady = castFromQVariant(values[propertyName]); - emitChangeSignal[QStringLiteral("ready")] = (previousIsReady != m_serviceReady); - } + {% for property in interface.properties %} + bool emit_{{property.name}}ChangeSignal = false; + if (values.contains(QLatin1String("{{property.name}}"))) { + {% if property.type.is_interface %} + const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[QLatin1String("{{property.name}}")]); + emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% elif property.type.is_model %} + int {{property.name}}Size = castFromQVariant(values[QLatin1String("{{property.name}}")]); + m_{{property.name}}.beginResetModel(); + m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); + m_{{property.name}}.endResetModel(); + emit_{{property.name}}ChangeSignal = true; + {% else %} + const auto previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[QLatin1String("{{property.name}}")]); + emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% endif %} } - for (const QString &propertyName: emitChangeSignal.keys()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}") && emitChangeSignal[propertyName]) { - emit {{property.name}}Changed(); - } - {% endfor %} - if (propertyName == QStringLiteral("ready") && emitChangeSignal[propertyName]) { - emit readyChanged(); - } + {% endfor %} + bool emit_ReadyChangeSignal = false; + if (values.contains(QLatin1String("ready"))) { + bool previousIsReady = this->ready(); + m_serviceReady = castFromQVariant(values[QLatin1String("ready")]); + emit_ReadyChangeSignal = (previousIsReady != m_serviceReady); } + + {% for property in interface.properties %} + if (emit_{{property.name}}ChangeSignal) + emit {{property.name}}Changed(); + {% endfor %} + + if (emit_ReadyChangeSignal) + emit readyChanged(); } void {{className}}::handleSignals(InputIPCMessage& msg) { Q_UNUSED(msg) {% for event in interface.signals %} - if (msg.member() == QStringLiteral("{{event}}")) { + if (msg.member() == QLatin1String("{{event}}")) { QListIterator argumentsIterator(msg.arguments()); {% for parameter in event.parameters %} {{parameter.interfaceCppType}} param_{{parameter.name}}; @@ -140,7 +137,7 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); {% for property in interface.properties %} {% if property.type.is_model %} - if (modelPropertyName == QStringLiteral("{{property.name}}")) { + if (modelPropertyName == QLatin1String("{{property.name}}")) { m_{{property.name}}.handleSignal(msg); } {% endif %} @@ -153,7 +150,7 @@ void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedPropert {% if interface.properties %} for (const QString &propertyName: changedProperties.keys()) { {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { + if (propertyName == QLatin1String("{{property.name}}")) { {% if property.type.is_model %} int {{property.name}}Size = castFromQVariant(changedProperties[propertyName]); m_{{property.name}}.beginResetModel(); @@ -167,7 +164,7 @@ void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedPropert } for (const QString &propertyName: changedProperties.keys()) { {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { + if (propertyName == QLatin1String("{{property.name}}")) { {% if not property.type.is_model %} emit {{property.name}}Changed(); {% endif %} @@ -186,7 +183,7 @@ void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedPropert void {{className}}::set{{property}}({{property.cppMethodArgumentType}} newValue) { {% if (not property.type.is_interface) %} - ipc()->sendSetterCall("{{property.name}}", newValue); + ipc()->sendSetterCall(QLatin1String("{{property.name}}"), newValue); {% else %} Q_ASSERT(false); // Writable interface properties are unsupported {% endif %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 52395c60..26b24032 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -144,7 +144,7 @@ void {{className}}::connectSignals() {% for property in interface.properties %} {% if property.type.is_model %} - m_{{property.name}}Handler.connectModel(QStringLiteral("{{property.name}}"), theService->{{property.name}}()); + m_{{property.name}}Handler.connectModel(QLatin1String("{{property.name}}"), theService->{{property.name}}()); {% else %} m_previous{{property.name}} = theService->{{property.name}}(); {% endif %} @@ -178,13 +178,13 @@ QVariantMap {{className}}::changedProperties() {% for property in interface.properties %} {% if not property.type.is_model %} if (m_previous{{property.name}} != theService->{{property.name}}()) { - ret[QStringLiteral("{{property.name}}")] = castToQVariant(theService->{{property.name}}()); + ret[QLatin1String("{{property.name}}")] = castToQVariant(theService->{{property.name}}()); m_previous{{property.name}} = theService->{{property.name}}(); } {% endif %} {% endfor %} if (m_previousReadyState != theService->ready()) { - ret[QStringLiteral("ready")] = castToQVariant(theService->ready()); + ret[QLatin1String("ready")] = castToQVariant(theService->ready()); m_previousReadyState = theService->ready(); } return ret; @@ -200,19 +200,19 @@ QVariantMap {{className}}::marshalProperties() {% for property in interface.properties %} {% if property.type.is_model %} - ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}().size()); + ret[QLatin1String("{{property.name}}")] = castToQVariant(theService->{{property.name}}().size()); {% else %} - ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}()); + ret[QLatin1String("{{property.name}}")] = castToQVariant(theService->{{property.name}}()); {% endif %} {% endfor %} - ret["ready"] = castToQVariant(theService->ready()); + ret[QLatin1String("ready")] = castToQVariant(theService->ready()); return ret; } QVariant {{className}}::marshalProperty(const QString& propertyName) { {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { + if (propertyName == QLatin1String("{{property.name}}")) { {% if property.type.is_model %} {% else %} @@ -220,7 +220,7 @@ QVariant {{className}}::marshalProperty(const QString& propertyName) {% endif %} } {% endfor %} - if (propertyName == QStringLiteral("ready")) { + if (propertyName == QLatin1String("ready")) { return castToQVariant(service()->ready()); } return QVariant(); @@ -231,7 +231,7 @@ void {{className}}::setProperty(const QString& propertyName, const QVariant& val Q_UNUSED(propertyName) Q_UNUSED(value) {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { + if (propertyName == QLatin1String("{{property.name}}")) { {% if property.type.is_interface %} Q_ASSERT(false); // Writable interface properties are unsupported {% elif property.type.is_model %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index 0caf13f1..36383456 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -97,7 +97,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{ comma() }}{{parameter.interfaceCppType}} {{parameter.name}} {%- endfor -%} ) { - sendSignal("{{event}}" + sendSignal(QLatin1String("{{event}}") {%- for parameter in event.parameters -%} , {{parameter.name}} {%- endfor -%} ); From 277b7e55100e9968e8a1509b0a5eeab26ffaeee4 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Fri, 9 Oct 2020 12:07:45 +0200 Subject: [PATCH 10/12] Revert "enable defining bus address" Mistakenly commited This reverts commit 3ed6fe9e70058a54e924f1bcd2a72722e9993a22. --- src/ipc/dbus/DBusIPCProxyBinder.cpp | 39 ++++++++----------- src/ipc/dbus/DBusIPCProxyBinder.h | 3 -- src/ipc/dbus/DBusManager.cpp | 19 ++++++++- src/ipc/dbus/DBusManager.h | 17 ++++++++ src/ipc/dbus/DBusManagerInterface.h | 4 ++ src/ipc/dbus/DBusObjectRegistry.cpp | 8 ++-- src/ipc/dbus/DBusObjectRegistry.h | 4 +- src/ipc/dbus/IPCDBusServiceAdapter.h | 14 +------ src/ipc/dbus/IPCDBusServiceAdapterBase.cpp | 19 +++++---- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 3 +- src/ipc/ipc-common/IPCProxy.h | 1 - src/ipc/ipc-common/IPCProxyBinderBase.cpp | 6 --- src/ipc/ipc-common/IPCProxyBinderBase.h | 9 +---- src/ipc/ipc-common/IPCServiceAdapterBase.h | 2 +- .../ipc-common/NewIPCServiceAdapterBase.cpp | 14 +------ src/ipc/ipc-common/NewIPCServiceAdapterBase.h | 18 --------- src/ipc/local/LocalIPCServiceAdapter.h | 4 +- tests/objectregistry/client.cpp | 3 +- 18 files changed, 81 insertions(+), 106 deletions(-) diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 6c81fb99..6f62ff5d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -39,8 +39,7 @@ namespace dbus { DBusIPCProxyBinder::DBusIPCProxyBinder(DBusManagerInterface& dbusManager, InterfaceBase &owner, QObject *parent) : IPCProxyBinderBase(owner, parent), - m_dbusManager(dbusManager), - m_connection(QDBusConnection::sessionBus()) + m_dbusManager(dbusManager) { m_busWatcher.setWatchMode(QDBusServiceWatcher::WatchForRegistration); } @@ -111,20 +110,22 @@ void DBusIPCProxyBinder::requestPropertyValues() void DBusIPCProxyBinder::onServiceNameKnown() { - auto successPropertyChangeSignal = m_connection.connect(m_serviceName, + auto& connection = m_dbusManager.connection(); + + auto successPropertyChangeSignal = connection.connect(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); Q_UNUSED(successPropertyChangeSignal); // TODO: check for (const QString& signalEntry: m_serviceObject->getSignals()) { - auto signalConnected = m_connection.connect(m_serviceName, + auto signalConnected = connection.connect(m_serviceName, objectPath(), m_interfaceName, signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); Q_UNUSED(signalConnected) // TODO: check } m_busWatcher.addWatchedService(m_serviceName); - m_busWatcher.setConnection(m_connection); + m_busWatcher.setConnection(connection); QObject::connect(&m_busWatcher, &QDBusServiceWatcher::serviceRegistered, this, [this](){ requestPropertyValues(); }); @@ -142,19 +143,21 @@ void DBusIPCProxyBinder::checkRegistry() if (serviceName != m_serviceName) { m_serviceName = serviceName; - if (!m_serviceName.isEmpty() && !m_interfaceName.isEmpty() && m_connection.isConnected()) { + if (!m_serviceName.isEmpty() && !m_interfaceName.isEmpty() && m_dbusManager.isDBusConnected()) { onServiceNameKnown(); } } } else if (!m_serviceName.isEmpty()){ // no point to proceed on empty service name m_busWatcher.removeWatchedService(m_serviceName); - m_connection.disconnect(m_serviceName, + auto& connection = m_dbusManager.connection(); + + connection.disconnect(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME, this, SLOT(onPropertiesChanged(const QDBusMessage&))); for (const QString& signalEntry: m_serviceObject->getSignals()) { - m_connection.disconnect(m_serviceName, + connection.disconnect(m_serviceName, objectPath(), interfaceName(), signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); } @@ -172,8 +175,9 @@ void DBusIPCProxyBinder::handleGenericSignals(const QDBusMessage& msg) void DBusIPCProxyBinder::asyncCall(DBusIPCMessage &message, const QObject *context, std::function callback) { + auto& connection = m_dbusManager.connection(); qCDebug(LogIpc) << "Sending async IPC message : " << message.toString(); - auto reply = new QDBusPendingCallWatcher(m_connection.asyncCall(message.outputMessage())); + auto reply = new QDBusPendingCallWatcher(connection.asyncCall(message.outputMessage())); QObject::connect(reply, &QDBusPendingCallWatcher::finished, context, [callback, reply]() { DBusIPCMessage msg(reply->reply()); if (msg.isReplyMessage()) { @@ -185,30 +189,19 @@ void DBusIPCProxyBinder::asyncCall(DBusIPCMessage &message, const QObject *conte DBusIPCMessage DBusIPCProxyBinder::call(DBusIPCMessage &message) const { + auto& connection = m_dbusManager.connection(); qCDebug(LogIpc) << "Sending blocking IPC message : " << message.toString(); - auto replyDbusMessage = m_connection.call(message.outputMessage()); + auto replyDbusMessage = connection.call(message.outputMessage()); DBusIPCMessage reply(replyDbusMessage); return reply; } void DBusIPCProxyBinder::setObjectPath(const QString &objectPath) { - if (!m_explicitServiceName) { - m_dbusManager.objectRegistry().objects(false).addListener(objectPath, this, &DBusIPCProxyBinder::checkRegistry); - } + m_dbusManager.objectRegistry().objects(false).addListener(objectPath, this, &DBusIPCProxyBinder::checkRegistry); IPCProxyBinderBase::setObjectPath(objectPath); } -void DBusIPCProxyBinder::setAddress(const QString& address) -{ - if (!address.isEmpty()) { - m_connection = QDBusConnection::connectToBus(address, address); - if (!m_connection.isConnected()) { - qFatal("Can't connect to DBUS at address: %s", qPrintable(address)); - } - IPCProxyBinderBase::setAddress(address); - } -} void DBusIPCProxyBinder::bindToIPC() { if (m_explicitServiceName) { diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index b35b83d8..c10fd53d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -72,8 +72,6 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void setObjectPath(const QString &objectPath) override; - void setAddress(const QString& address) override; - void setInterfaceName(const QString &name); Q_SLOT void onPropertiesChanged(const QDBusMessage &dbusMessage); @@ -225,7 +223,6 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase DBusRequestHandler *m_serviceObject = nullptr; bool m_serviceAvailable = false; DBusManagerInterface &m_dbusManager; - QDBusConnection m_connection; }; diff --git a/src/ipc/dbus/DBusManager.cpp b/src/ipc/dbus/DBusManager.cpp index 9cd9a2ab..2f6dcb77 100644 --- a/src/ipc/dbus/DBusManager.cpp +++ b/src/ipc/dbus/DBusManager.cpp @@ -34,8 +34,12 @@ namespace facelift { namespace dbus { -DBusManager::DBusManager() +DBusManager::DBusManager() : m_busConnection(QDBusConnection::sessionBus()) { + m_dbusConnected = m_busConnection.isConnected(); + if (!m_dbusConnected) { + qCCritical(LogIpc) << "NOT connected to DBUS"; + } } DBusManager &DBusManager::instance() @@ -61,5 +65,18 @@ DBusObjectRegistry &DBusManager::objectRegistry() return *m_objectRegistry; } +bool DBusManager::registerServiceName(const QString &serviceName) +{ + qCDebug(LogIpc) << "Registering serviceName " << serviceName; + auto success = m_busConnection.registerService(serviceName); + return success; +} + +QString DBusManager::serviceName() const +{ + return m_busConnection.baseService(); +} + + } // end namespace dbus } // end namespace facelift diff --git a/src/ipc/dbus/DBusManager.h b/src/ipc/dbus/DBusManager.h index 191619a8..3fffed5f 100644 --- a/src/ipc/dbus/DBusManager.h +++ b/src/ipc/dbus/DBusManager.h @@ -57,10 +57,27 @@ class FaceliftIPCLibDBus_EXPORT DBusManager : public DBusManagerInterface static DBusManager &instance(); + bool isDBusConnected() const override + { + return m_dbusConnected; + } + + bool registerServiceName(const QString &serviceName) override; + + QDBusConnection &connection() override + { + return m_busConnection; + } + + QString serviceName() const override; + DBusObjectRegistry &objectRegistry() override; private: + QDBusConnection m_busConnection; DBusObjectRegistry *m_objectRegistry = nullptr; + bool m_dbusConnected = false; + // singleton DBusManager(); }; diff --git a/src/ipc/dbus/DBusManagerInterface.h b/src/ipc/dbus/DBusManagerInterface.h index d2bdf289..08d761ee 100644 --- a/src/ipc/dbus/DBusManagerInterface.h +++ b/src/ipc/dbus/DBusManagerInterface.h @@ -48,6 +48,10 @@ class FaceliftIPCLibDBus_EXPORT DBusManagerInterface { public: virtual ~DBusManagerInterface() = default; + virtual bool isDBusConnected() const = 0; + virtual bool registerServiceName(const QString &serviceName) = 0; + virtual QDBusConnection &connection() = 0; + virtual QString serviceName() const = 0; virtual DBusObjectRegistry &objectRegistry() = 0; }; diff --git a/src/ipc/dbus/DBusObjectRegistry.cpp b/src/ipc/dbus/DBusObjectRegistry.cpp index dfcc14bb..d91a4ccc 100644 --- a/src/ipc/dbus/DBusObjectRegistry.cpp +++ b/src/ipc/dbus/DBusObjectRegistry.cpp @@ -53,7 +53,7 @@ void DBusObjectRegistry::init() { if (!m_initialized) { m_initialized = true; - if (!QDBusConnection::sessionBus().isConnected() || QDBusConnection::sessionBus().registerService(m_serviceName)) { + if (!m_dbusManager.isDBusConnected() || m_dbusManager.registerServiceName(m_serviceName)) { m_master = std::make_unique(); m_master->init(); QObject::connect(m_master.get(), &MasterImpl::objectAdded, this, &DBusObjectRegistry::onObjectAdded); @@ -73,9 +73,10 @@ void DBusObjectRegistry::init() } } -void DBusObjectRegistry::registerObject(const QString &objectPath, const QString& serviceName, facelift::AsyncAnswer answer) +void DBusObjectRegistry::registerObject(const QString &objectPath, facelift::AsyncAnswer answer) { init(); + auto serviceName = m_dbusManager.serviceName(); if (isMaster()) { auto isSuccessful = m_master->registerObject(objectPath, serviceName); answer(isSuccessful); @@ -84,9 +85,10 @@ void DBusObjectRegistry::registerObject(const QString &objectPath, const QString } } -void DBusObjectRegistry::unregisterObject(const QString &objectPath, const QString& serviceName) +void DBusObjectRegistry::unregisterObject(const QString &objectPath) { init(); + auto serviceName = m_dbusManager.serviceName(); if (isMaster()) { m_master->unregisterObject(objectPath, serviceName); } else { diff --git a/src/ipc/dbus/DBusObjectRegistry.h b/src/ipc/dbus/DBusObjectRegistry.h index 9b489b88..dabd46c0 100644 --- a/src/ipc/dbus/DBusObjectRegistry.h +++ b/src/ipc/dbus/DBusObjectRegistry.h @@ -74,9 +74,9 @@ class FaceliftIPCLibDBus_EXPORT DBusObjectRegistry : public QObject DBusObjectRegistry(DBusManagerInterface &dbusManager); - void registerObject(const QString &objectPath, const QString& serviceName, facelift::AsyncAnswer answer); + void registerObject(const QString &objectPath, facelift::AsyncAnswer answer); - void unregisterObject(const QString &objectPath, const QString& serviceName); + void unregisterObject(const QString &objectPath); const Registry& objects(bool blocking); diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index b5fb02a2..0447b6dd 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -86,20 +86,8 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase return m_service; } - void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase* serverObject) override { + void registerService(const QString &objectPath, InterfaceBase* serverObject) override { Q_ASSERT(qobject_cast(serverObject) != nullptr); - if (address.isEmpty()) { - m_connection = QDBusConnection::sessionBus(); - } - else { - m_connection = QDBusConnection::connectToBus(address, address); - } - if (m_connection.isConnected()) { - m_connection.registerService(serviceName); - } - else { - qCCritical(LogIpc()) << "Not connected to DBUS at address:" << (address.isEmpty() ? QStringLiteral("session bus"): address); - } registerService(objectPath, static_cast(serverObject)); } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp index b3541b14..6e65a310 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp @@ -135,8 +135,7 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) IPCDBusServiceAdapterBase::IPCDBusServiceAdapterBase(DBusManagerInterface& dbusManager, QObject *parent) : IPCServiceAdapterBase(parent), m_dbusVirtualObject(*this), - m_dbusManager(dbusManager), - m_connection(QDBusConnection::sessionBus()) + m_dbusManager(dbusManager) { } @@ -148,7 +147,7 @@ void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage void IPCDBusServiceAdapterBase::send(DBusIPCMessage &message) { qCDebug(LogIpc) << "Sending IPC message : " << message.toString(); - bool successful = m_connection.send(message.outputMessage()); + bool successful = m_dbusManager.connection().send(message.outputMessage()); Q_ASSERT(successful); } @@ -179,9 +178,9 @@ QString IPCDBusServiceAdapterBase::introspect(const QString &path) const void IPCDBusServiceAdapterBase::unregisterService() { if (m_alreadyInitialized) { - m_connection.unregisterObject(objectPath()); + m_dbusManager.connection().unregisterObject(objectPath()); qCDebug(LogIpc) << "Unregistered IPCDBusServiceAdapter object at " << objectPath(); - m_dbusManager.objectRegistry().unregisterObject(objectPath(), m_connection.baseService()); + m_dbusManager.objectRegistry().unregisterObject(objectPath()); m_alreadyInitialized = false; } } @@ -189,15 +188,19 @@ void IPCDBusServiceAdapterBase::unregisterService() void IPCDBusServiceAdapterBase::registerService() { if (!m_alreadyInitialized) { - if (m_connection.isConnected()) { + if (m_dbusManager.isDBusConnected()) { + + if (!m_serviceName.isEmpty()) { + m_dbusManager.registerServiceName(m_serviceName); + } qCDebug(LogIpc) << "Registering IPCDBusServiceAdapter object at " << objectPath(); - m_alreadyInitialized = m_connection.registerVirtualObject(objectPath(), &m_dbusVirtualObject); + m_alreadyInitialized = m_dbusManager.connection().registerVirtualObject(objectPath(), &m_dbusVirtualObject); if (!m_alreadyInitialized) { qFatal("Could not register service at object path '%s'", qPrintable(objectPath())); } - m_dbusManager.objectRegistry().registerObject(objectPath(), m_connection.baseService(), facelift::AsyncAnswer(this, [](bool isSuccessful) { + m_dbusManager.objectRegistry().registerObject(objectPath(), facelift::AsyncAnswer(this, [](bool isSuccessful) { Q_ASSERT(isSuccessful); })); } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 3489d309..789de167 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -144,14 +144,13 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda DBusVirtualObject m_dbusVirtualObject; QString m_introspectionData; + QString m_serviceName; bool m_previousReadyState = false; bool m_signalsConnected = false; bool m_alreadyInitialized = false; DBusManagerInterface& m_dbusManager; - QDBusConnection m_connection; - QString m_address; private: template::value, int> = 0> T castFromQVariantSpecialized(HelperType, const QVariant& value) { diff --git a/src/ipc/ipc-common/IPCProxy.h b/src/ipc/ipc-common/IPCProxy.h index 15948990..37b8836b 100644 --- a/src/ipc/ipc-common/IPCProxy.h +++ b/src/ipc/ipc-common/IPCProxy.h @@ -75,7 +75,6 @@ class IPCProxy : public WrapperType, public IPCProxyNewBase void enableBinder(IPCProxyBinderBase * ipcBinder) { ipcBinder->setObjectPath(ipc()->objectPath()); - ipcBinder->setAddress(ipc()->address()); const auto &serviceName = ipc()->serviceName(); if (!serviceName.isEmpty()) { ipcBinder->setServiceName(serviceName); diff --git a/src/ipc/ipc-common/IPCProxyBinderBase.cpp b/src/ipc/ipc-common/IPCProxyBinderBase.cpp index 7584727f..33b6e0b8 100644 --- a/src/ipc/ipc-common/IPCProxyBinderBase.cpp +++ b/src/ipc/ipc-common/IPCProxyBinderBase.cpp @@ -83,12 +83,6 @@ void IPCProxyBinderBase::setObjectPath(const QString &objectPath) checkInit(); } -void IPCProxyBinderBase::setAddress(const QString& address) -{ - m_address = address; - checkInit(); -} - bool IPCProxyBinderBase::isServiceAvailable() const { Q_ASSERT(false); // TODO: remove return true; diff --git a/src/ipc/ipc-common/IPCProxyBinderBase.h b/src/ipc/ipc-common/IPCProxyBinderBase.h index 11df58eb..40244750 100644 --- a/src/ipc/ipc-common/IPCProxyBinderBase.h +++ b/src/ipc/ipc-common/IPCProxyBinderBase.h @@ -48,7 +48,6 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName) - Q_PROPERTY(QString address READ address WRITE setAddress) IPCProxyBinderBase(InterfaceBase &owner, QObject *parent); @@ -71,13 +70,8 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject return m_objectPath; } - virtual void setObjectPath(const QString &objectPath); - inline const QString& address() - { - return m_address; - } - virtual void setAddress(const QString& address); + virtual void setObjectPath(const QString &objectPath); void onComponentCompleted(); @@ -146,7 +140,6 @@ class FaceliftIPCCommonLib_EXPORT IPCProxyBinderBase : public QObject InterfaceBase &m_owner; bool m_alreadyInitialized = false; bool m_enabled = true; - QString m_address; bool m_componentCompleted = false; bool m_isSynchronous = true; }; diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index 90709bc7..cd7c84c3 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -74,7 +74,7 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject m_objectPath = objectPath; } - virtual void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase* serverObject) = 0; + virtual void registerService(const QString &objectPath, InterfaceBase* serverObject) = 0; virtual void unregisterService() = 0; diff --git a/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp b/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp index 0f5ece85..d35c1697 100644 --- a/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp +++ b/src/ipc/ipc-common/NewIPCServiceAdapterBase.cpp @@ -59,7 +59,7 @@ void NewIPCServiceAdapterBase::registerService() registerLocalService(); createAdapters(); for (auto& ipcAdapter : m_ipcServiceAdapters) { - ipcAdapter->registerService(objectPath(), address(), serviceName(), service()); + ipcAdapter->registerService(objectPath(), service()); } } @@ -85,18 +85,6 @@ void NewIPCServiceAdapterBase::onValueChanged() } } -void NewIPCServiceAdapterBase::setAddress(const QString &address) -{ - m_address = address; - onValueChanged(); -} - -void NewIPCServiceAdapterBase::setServiceName(const QString& serviceName) -{ - m_serviceName = serviceName; - onValueChanged(); -} - void NewIPCServiceAdapterBase::setEnabled(bool enabled) { m_enabled = enabled; diff --git a/src/ipc/ipc-common/NewIPCServiceAdapterBase.h b/src/ipc/ipc-common/NewIPCServiceAdapterBase.h index 9cce7de0..00bd55a4 100644 --- a/src/ipc/ipc-common/NewIPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/NewIPCServiceAdapterBase.h @@ -53,8 +53,6 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject Q_PROPERTY(QObject * service READ service WRITE checkedSetService) Q_PROPERTY(QString objectPath READ objectPath WRITE setObjectPath) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) - Q_PROPERTY(QString address READ address WRITE setAddress) - Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName) NewIPCServiceAdapterBase(InterfaceManagerInterface& interfaceManager, QObject *parent); @@ -65,20 +63,6 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject return m_enabled; } - const QString& address() const - { - return m_address; - } - - const QString& serviceName() const - { - return m_serviceName; - } - - void setAddress(const QString& address); - - void setServiceName(const QString& serviceName); - void setEnabled(bool enabled); void checkedSetService(QObject *service); @@ -154,8 +138,6 @@ class FaceliftIPCCommonLib_EXPORT NewIPCServiceAdapterBase : public QObject bool m_enabled = true; bool m_providerReady = false; bool m_registered = false; - QString m_address; - QString m_serviceName; InterfaceManagerInterface& m_interfaceManager; }; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index 6168ec95..742d3728 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -85,10 +85,8 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase return m_service; } - void registerService(const QString &objectPath, const QString& address, const QString& serviceName, InterfaceBase *serverObject) override + void registerService(const QString &objectPath, InterfaceBase *serverObject) override { - Q_UNUSED(serviceName) - Q_UNUSED(address) Q_ASSERT(qobject_cast(serverObject) != nullptr); registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } diff --git a/tests/objectregistry/client.cpp b/tests/objectregistry/client.cpp index 26049d33..b224e4ac 100644 --- a/tests/objectregistry/client.cpp +++ b/tests/objectregistry/client.cpp @@ -36,12 +36,13 @@ void tests::ipc::Tester::registerAnotherAdapter() { + auto &manager = facelift::dbus::DBusManager::instance(); facelift::dbus::DBusIPCMessage msg( facelift::dbus::DBusIPCCommon::DEFAULT_SERVICE_NAME, m_async->ipc()->objectPath(), tests::ipc::IPCTestInterfaceAsyncIPCProxy::FULLY_QUALIFIED_INTERFACE_NAME, "registerOtherIPCTestInterface"); - QDBusConnection::sessionBus().call(msg.outputMessage()); + manager.connection().call(msg.outputMessage()); } void tests::ipc::Tester::runTest() From 73c9a06861073c551c607c6b6daa9b3ba9b132e1 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Tue, 13 Oct 2020 22:28:49 +0200 Subject: [PATCH 11/12] Fix more review comments changedProperties -> dirtyProperties more specialized DBus and Local IPC proxy methods --- .../templates/IPCDBusProxyAdapter.template.cpp | 2 ++ .../templates/IPCDBusProxyAdapter.template.h | 1 + .../templates/IPCDBusServiceAdapter.template.cpp | 1 + .../templates/IPCDBusServiceAdapter.template.h | 2 +- .../templates/IPCProxyAdapter.template.cpp | 16 ++++++++-------- .../templates/IPCProxyAdapter.template.h | 4 +++- .../templates/IPCServiceAdapter.template.cpp | 10 +++++----- .../templates/IPCServiceAdapter.template.h | 6 +++--- src/ipc/dbus/DBusIPCProxyBinder.cpp | 4 ++-- src/ipc/dbus/DBusRequestHandler.h | 4 ++-- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 8 ++++---- src/ipc/local/LocalIPCProxyBinder.cpp | 4 ++-- src/ipc/local/LocalIPCRequestHandler.h | 5 ++--- src/ipc/local/LocalIPCServiceAdapterBase.cpp | 6 ------ src/ipc/local/LocalIPCServiceAdapterBase.h | 10 +++------- tests/combined/client.cpp | 0 16 files changed, 39 insertions(+), 44 deletions(-) create mode 100644 tests/combined/client.cpp diff --git a/codegen/facelift/templates/IPCDBusProxyAdapter.template.cpp b/codegen/facelift/templates/IPCDBusProxyAdapter.template.cpp index 2d88467c..d4fe5fc9 100644 --- a/codegen/facelift/templates/IPCDBusProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCDBusProxyAdapter.template.cpp @@ -34,4 +34,6 @@ ****************************************************************************/ {% set baseClass = "::facelift::dbus::DBusIPCProxy<" + interfaceName + ">" %} {% set proxyTypeNameSuffix = "IPCDBusProxy" %} +{% set proxyType = "DBus" %} + {% include "IPCProxyAdapter.template.cpp" %} diff --git a/codegen/facelift/templates/IPCDBusProxyAdapter.template.h b/codegen/facelift/templates/IPCDBusProxyAdapter.template.h index 41ec8d1f..33e0f75f 100644 --- a/codegen/facelift/templates/IPCDBusProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusProxyAdapter.template.h @@ -34,6 +34,7 @@ ****************************************************************************/ {% set baseClass = "::facelift::dbus::DBusIPCProxy<" + interfaceName + ">" %} {% set proxyTypeNameSuffix = "IPCDBusProxy" %} +{% set proxyType = "DBus" %} #include "DBusIPCProxy.h" diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.cpp b/codegen/facelift/templates/IPCDBusServiceAdapter.template.cpp index edea8dfe..b2fd93c9 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.cpp @@ -34,5 +34,6 @@ ****************************************************************************/ {% set baseClass = "::facelift::dbus::IPCDBusServiceAdapter<" + interfaceName + ">" %} {% set proxyTypeNameSuffix = "IPCDBusAdapter" %} +{% set proxyType = "DBus" %} {% include "IPCServiceAdapter.template.cpp" %} diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index 1bedc2e5..af51b798 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -87,7 +87,7 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - QVariantMap changedProperties(); + QVariantMap dirtyProperties(); QVariantMap marshalProperties() override; diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 18e2923b..e992b1f3 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -111,7 +111,7 @@ void {{className}}::handleSignals(InputIPCMessage& msg) this->onModelUpdateEvent(msg); {% endif %} } - +{% if proxyType and proxyType == "DBus" %} const QList& {{className}}::getSignals() const { static QList allSignals{ @@ -129,7 +129,7 @@ const QList& {{className}}::getSignals() const return allSignals; } - +{% endif %} {% if interface.hasModelProperty %} void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) { @@ -145,24 +145,24 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) } {% endif %} -void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedProperties) +void {{className}}::unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) { {% if interface.properties %} - for (const QString &propertyName: changedProperties.keys()) { + for (const QString &propertyName: dirtyProperties.keys()) { {% for property in interface.properties %} if (propertyName == QLatin1String("{{property.name}}")) { {% if property.type.is_model %} - int {{property.name}}Size = castFromQVariant(changedProperties[propertyName]); + int {{property.name}}Size = castFromQVariant(dirtyProperties[propertyName]); m_{{property.name}}.beginResetModel(); m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); m_{{property.name}}.endResetModel(); {% else %} - m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(dirtyProperties[propertyName]); {% endif %} } {% endfor %} } - for (const QString &propertyName: changedProperties.keys()) { + for (const QString &propertyName: dirtyProperties.keys()) { {% for property in interface.properties %} if (propertyName == QLatin1String("{{property.name}}")) { {% if not property.type.is_model %} @@ -172,7 +172,7 @@ void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedPropert {% endfor %} } {% else %} - Q_UNUSED(changedProperties); + Q_UNUSED(dirtyProperties); {% endif %} } diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index 5431d646..22a4c38d 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -86,9 +86,11 @@ class {{classExport}} {{className}} : public {{baseClass}} void handleSignals(InputIPCMessage& msg) override; + {% if proxyType and proxyType == "DBus" %} const QList& getSignals() const override; + {% endif %} - void unmarshalPropertiesChanged(const QVariantMap& changedProperties) override; + void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) override; {% for operation in interface.operations %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 26b24032..836691fd 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -96,7 +96,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa return facelift::IPCHandlingResult::OK; } - +{% if proxyType and proxyType == "DBus" %} void {{className}}::appendDBUSIntrospectionData(QTextStream &s) const { Q_UNUSED(s) // For empty interfaces @@ -136,7 +136,7 @@ void {{className}}::appendDBUSIntrospectionData(QTextStream &s) const facelift::appendDBusModelSignals(s); {% endif %} } - +{% endif %} void {{className}}::connectSignals() { auto theService = service(); @@ -155,13 +155,13 @@ void {{className}}::connectSignals() {% for property in interface.properties %} {% if (not property.type.is_model) %} QObject::connect(theService, &ServiceType::{{property.name}}Changed, this, [this, theService] () { - this->sendPropertiesChanged(changedProperties()); + this->sendPropertiesChanged(dirtyProperties()); }); {% endif %} {% endfor %} QObject::connect(theService, &ServiceType::readyChanged, this, [this, theService] () { - this->sendPropertiesChanged(changedProperties()); + this->sendPropertiesChanged(dirtyProperties()); }); // Signals @@ -170,7 +170,7 @@ void {{className}}::connectSignals() {% endfor %} } -QVariantMap {{className}}::changedProperties() +QVariantMap {{className}}::dirtyProperties() { QMap ret; auto theService = service(); diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index 36383456..534e96f6 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -74,15 +74,15 @@ class {{classExport}} {{className}}: public {{baseClass}} {% endfor %} { } - + {% if proxyType and proxyType == "DBus" %} void appendDBUSIntrospectionData(QTextStream &s) const override; - + {% endif %} ::facelift::IPCHandlingResult handleMethodCallMessage(InputIPCMessage &requestMessage, OutputIPCMessage &replyMessage) override; void connectSignals() override; - QVariantMap changedProperties(); + QVariantMap dirtyProperties(); QVariantMap marshalProperties() override; diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 6f62ff5d..c3db4890 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -73,8 +73,8 @@ void DBusIPCProxyBinder::onPropertiesChanged(const QDBusMessage &dbusMessage) QListIterator argumentsIterator(msg.arguments()); QString interfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); if (interfaceName == m_interfaceName) { - QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QVariantMap()); - m_serviceObject->unmarshalPropertiesChanged(changedProperties); + QVariantMap dirtyProperties = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(dirtyProperties); } } diff --git a/src/ipc/dbus/DBusRequestHandler.h b/src/ipc/dbus/DBusRequestHandler.h index 4588ab16..3d038dc0 100644 --- a/src/ipc/dbus/DBusRequestHandler.h +++ b/src/ipc/dbus/DBusRequestHandler.h @@ -45,8 +45,8 @@ class FaceliftIPCLibDBus_EXPORT DBusRequestHandler { public: - virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; - virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; + virtual void unmarshalProperties(const QVariantMap& properties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) = 0; virtual void handleSignals(DBusIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 789de167..ce997e70 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -90,7 +90,7 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool handleMessage(const QDBusMessage &dbusMsg); - inline void sendPropertiesChanged(const QVariantMap& changedProperties); + inline void sendPropertiesChanged(const QVariantMap& dirtyProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -242,13 +242,13 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } }; -inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties) +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QVariantMap &dirtyProperties) { DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); QMap convertedToDBusVariant; - for (const QString& key: changedProperties.keys()) { - convertedToDBusVariant[key] = QDBusVariant(changedProperties[key]); + for (const QString& key: dirtyProperties.keys()) { + convertedToDBusVariant[key] = QDBusVariant(dirtyProperties[key]); } reply << QVariant::fromValue(convertedToDBusVariant); this->send(reply); diff --git a/src/ipc/local/LocalIPCProxyBinder.cpp b/src/ipc/local/LocalIPCProxyBinder.cpp index f593061e..74905f22 100644 --- a/src/ipc/local/LocalIPCProxyBinder.cpp +++ b/src/ipc/local/LocalIPCProxyBinder.cpp @@ -129,8 +129,8 @@ void LocalIPCProxyBinder::onPropertiesChanged(LocalIPCMessage &msg) QListIterator argumentsIterator(msg.arguments()); QString interfaceName = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QString()); if (interfaceName == m_interfaceName) { - QVariantMap changedProperties = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QVariantMap()); - m_serviceObject->unmarshalPropertiesChanged(changedProperties); + QVariantMap dirtyProperties = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(dirtyProperties); } } diff --git a/src/ipc/local/LocalIPCRequestHandler.h b/src/ipc/local/LocalIPCRequestHandler.h index 0f336439..6f648e01 100644 --- a/src/ipc/local/LocalIPCRequestHandler.h +++ b/src/ipc/local/LocalIPCRequestHandler.h @@ -60,10 +60,9 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCRequestHandler { public: - virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; - virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; + virtual void unmarshalProperties(const QVariantMap& properties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) = 0; virtual void handleSignals(LocalIPCMessage& msg) = 0; - virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; }; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.cpp b/src/ipc/local/LocalIPCServiceAdapterBase.cpp index 1157e8c8..80591718 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.cpp +++ b/src/ipc/local/LocalIPCServiceAdapterBase.cpp @@ -105,12 +105,6 @@ LocalIPCServiceAdapterBase::~LocalIPCServiceAdapterBase() unregisterService(); } -QString LocalIPCServiceAdapterBase::introspect(const QString &path) const -{ - Q_UNUSED(path); - return QString(); -} - void LocalIPCServiceAdapterBase::unregisterService() { if (m_alreadyInitialized) { diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 9f09527c..5511b0fa 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -62,7 +62,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA IPCHandlingResult handleMessage(LocalIPCMessage &message); - inline void sendPropertiesChanged(const QVariantMap &changedProperties); + inline void sendPropertiesChanged(const QVariantMap &dirtyProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -90,10 +90,6 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA void sendReply(LocalIPCMessage &message); - virtual void appendDBUSIntrospectionData(QTextStream &s) const = 0; - - QString introspect(const QString &path) const; - template MemberIDType memberID(T member, MemberIDType memberName) const { @@ -149,11 +145,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA bool m_alreadyInitialized = false; }; -inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties ) +inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QVariantMap &dirtyProperties ) { LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariant::fromValue(changedProperties); + reply << QVariant::fromValue(dirtyProperties); this->send(reply); } diff --git a/tests/combined/client.cpp b/tests/combined/client.cpp new file mode 100644 index 00000000..e69de29b From b359770940d26664d508b9f5fcfe6b561f009199 Mon Sep 17 00:00:00 2001 From: Mostafa Date: Sun, 1 Nov 2020 20:54:31 +0100 Subject: [PATCH 12/12] Unify PropertiesChanged routines --- .../templates/IPCProxyAdapter.template.cpp | 31 ------------------- .../templates/IPCProxyAdapter.template.h | 2 -- src/ipc/dbus/DBusIPCProxyBinder.cpp | 2 +- src/ipc/dbus/DBusRequestHandler.h | 1 - src/ipc/local/LocalIPCProxyBinder.cpp | 2 +- src/ipc/local/LocalIPCRequestHandler.h | 1 - 6 files changed, 2 insertions(+), 37 deletions(-) diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index e992b1f3..73c3aedf 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -145,37 +145,6 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) } {% endif %} -void {{className}}::unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) -{ - {% if interface.properties %} - for (const QString &propertyName: dirtyProperties.keys()) { - {% for property in interface.properties %} - if (propertyName == QLatin1String("{{property.name}}")) { - {% if property.type.is_model %} - int {{property.name}}Size = castFromQVariant(dirtyProperties[propertyName]); - m_{{property.name}}.beginResetModel(); - m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); - m_{{property.name}}.endResetModel(); - {% else %} - m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(dirtyProperties[propertyName]); - {% endif %} - } - {% endfor %} - } - for (const QString &propertyName: dirtyProperties.keys()) { - {% for property in interface.properties %} - if (propertyName == QLatin1String("{{property.name}}")) { - {% if not property.type.is_model %} - emit {{property.name}}Changed(); - {% endif %} - } - {% endfor %} - } - {% else %} - Q_UNUSED(dirtyProperties); - {% endif %} -} - {% for property in interface.properties %} {% if (not property.readonly) %} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index 53736f74..662fd570 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -88,8 +88,6 @@ class {{className}} : public {{baseClass}} const QList& getSignals() const override; {% endif %} - void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) override; - {% for operation in interface.operations %} {% if operation.isAsync %} diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index c3db4890..87ed3e42 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -74,7 +74,7 @@ void DBusIPCProxyBinder::onPropertiesChanged(const QDBusMessage &dbusMessage) QString interfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); if (interfaceName == m_interfaceName) { QVariantMap dirtyProperties = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QVariantMap()); - m_serviceObject->unmarshalPropertiesChanged(dirtyProperties); + m_serviceObject->unmarshalProperties(dirtyProperties); } } diff --git a/src/ipc/dbus/DBusRequestHandler.h b/src/ipc/dbus/DBusRequestHandler.h index 1c3979d7..d5c116ce 100644 --- a/src/ipc/dbus/DBusRequestHandler.h +++ b/src/ipc/dbus/DBusRequestHandler.h @@ -40,7 +40,6 @@ class DBusRequestHandler public: virtual void unmarshalProperties(const QVariantMap& properties) = 0; - virtual void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) = 0; virtual void handleSignals(DBusIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/local/LocalIPCProxyBinder.cpp b/src/ipc/local/LocalIPCProxyBinder.cpp index 74905f22..556ffd41 100644 --- a/src/ipc/local/LocalIPCProxyBinder.cpp +++ b/src/ipc/local/LocalIPCProxyBinder.cpp @@ -130,7 +130,7 @@ void LocalIPCProxyBinder::onPropertiesChanged(LocalIPCMessage &msg) QString interfaceName = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QString()); if (interfaceName == m_interfaceName) { QVariantMap dirtyProperties = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QVariantMap()); - m_serviceObject->unmarshalPropertiesChanged(dirtyProperties); + m_serviceObject->unmarshalProperties(dirtyProperties); } } diff --git a/src/ipc/local/LocalIPCRequestHandler.h b/src/ipc/local/LocalIPCRequestHandler.h index 5d029172..166a2ec0 100644 --- a/src/ipc/local/LocalIPCRequestHandler.h +++ b/src/ipc/local/LocalIPCRequestHandler.h @@ -55,7 +55,6 @@ class LocalIPCRequestHandler public: virtual void unmarshalProperties(const QVariantMap& properties) = 0; - virtual void unmarshalPropertiesChanged(const QVariantMap& dirtyProperties) = 0; virtual void handleSignals(LocalIPCMessage& msg) = 0; virtual void setServiceRegistered(bool isRegistered) = 0;