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..a7aec2f4 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 = qdbus_cast>(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 = qdbus_cast(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 = qdbus_cast(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}} = qdbus_cast(values[propertyName]); + {% else %} + m_{{property.name}} = qdbus_cast<{{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 = qdbus_cast(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() ? qdbusToValue<{{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() ? qdbus_cast(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() ? qdbus_cast(argumentsIterator.next()): QString()); + QVariantMap changedProperties = (argumentsIterator.hasNext() ? qdbus_cast(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}} = qdbusToValue(changedProperties[propertyName]); + {% else %} + m_{{property.name}} = qdbusToValue<{{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() ? qdbusToValue<{{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..29ed10b1 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..a10b13f3 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() ? qdbusToValue<{{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(QDBusMetaType::typeToSignature(qMetaTypeId<{{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() ? qdbus_cast(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() ? qdbus_cast(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? qdbus_cast(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() ? qdbus_cast(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? qdbus_cast(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}}(qvariant_cast<{{property.cppType}}>(qdbus_cast(argumentsIterator.next()).variant())); + } + {% 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..788ba35d 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -36,15 +36,27 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif +#include + +template +T qdbusToValue(const QVariant& arg) { + return qdbus_cast(arg); +} + +template<> +inline QList qdbusToValue(const QVariant& arg) { + return qdbus_cast(arg); // workaround to use QList since its signature matches the QStringList +} + 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..2236adef 100644 --- a/src/ipc/dbus/DBusIPCProxy.h +++ b/src/ipc/dbus/DBusIPCProxy.h @@ -78,42 +78,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(); diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 636fbb0b..36ebcda4 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 char* signalEntry: m_serviceObject->getSignals()) { + auto signalConnected = connection.connect(m_serviceName, + objectPath(), interfaceName(), signalEntry, this, SLOT(handleGenericSignals(const QDBusMessage&))); + Q_UNUSED(signalConnected); // 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 char* 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..a725e96f 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,8 +74,6 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase Q_SLOT void onPropertiesChanged(const QDBusMessage &dbusMessage); - Q_SLOT void onSignalTriggered(const QDBusMessage &dbusMessage); - void bindToIPC() override; void onServiceNameKnown(); @@ -91,16 +91,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,13 +105,14 @@ 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); private: void checkRegistry(); + void handleGenericSignals(const QDBusMessage &msg); QString m_interfaceName; QDBusServiceWatcher m_busWatcher; @@ -127,29 +122,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 +140,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 +157,53 @@ 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 +QDBusVariant toDBusVariant(const PropertyType& value) +{ + return QDBusVariant(QVariant::fromValue(value)); } +template<> +inline QDBusVariant toDBusVariant(const QList& value) +{ + return QDBusVariant(QVariant::fromValue(QStringList(value))); +} + 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..9b36cdab 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/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..e8fb6ca1 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() ? qdbus_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(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/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..40abead7 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/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 {