From 164a6b9ab8821a67d58dc1fc62abbf6d8c856c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=98=8E=20Mostafa=20Emami?= Date: Sun, 20 Sep 2020 23:09:14 +0200 Subject: [PATCH] Fix review comments --- codegen/facelift/facelift-codegen.py | 23 +- .../templates/IPCAdapter.template.cpp | 46 --- .../IPCDBusServiceAdapter.template.h | 9 +- .../facelift/templates/IPCProxy.template.cpp | 25 -- .../templates/IPCProxyAdapter.template.cpp | 100 ++++--- .../templates/IPCProxyAdapter.template.h | 5 +- .../templates/IPCServiceAdapter.template.cpp | 137 +++++---- .../templates/IPCServiceAdapter.template.h | 9 +- .../templates/ImplementationBase.template.h | 1 - .../facelift/templates/Service.template.cpp | 1 - .../facelift/templates/Struct.template.cpp | 84 +----- codegen/facelift/templates/Struct.template.h | 14 +- doc/page-annotations.h | 2 +- src/ipc/dbus/CMakeLists.txt | 1 + src/ipc/dbus/DBusIPCCommon.h | 13 +- src/ipc/dbus/DBusIPCMessage.cpp | 13 +- src/ipc/dbus/DBusIPCMessage.h | 2 +- src/ipc/dbus/DBusIPCProxy.h | 9 +- src/ipc/dbus/DBusIPCProxyBinder.cpp | 13 +- src/ipc/dbus/DBusIPCProxyBinder.h | 115 ++++---- src/ipc/dbus/DBusObjectRegistry.cpp | 2 +- src/ipc/dbus/DBusRequestHandler.h | 4 +- src/ipc/dbus/FaceliftDBusMarshaller.h | 268 ++++++++++++++++++ src/ipc/dbus/IPCDBusServiceAdapter.h | 56 +++- src/ipc/dbus/IPCDBusServiceAdapterBase.cpp | 50 +++- src/ipc/dbus/IPCDBusServiceAdapterBase.h | 111 ++++---- .../IPCAdapterModelPropertyHandler.h | 20 +- src/ipc/ipc-common/IPCProxyModelProperty.h | 46 +-- src/ipc/ipc-common/IPCServiceAdapterBase.h | 57 ---- src/ipc/ipc-common/ipc-common.h | 11 + src/ipc/local/FaceliftIPCCommon.h | 11 +- src/ipc/local/LocalIPC-serialization.h | 7 +- src/ipc/local/LocalIPCProxy.h | 43 ++- src/ipc/local/LocalIPCProxyBase.h | 1 - src/ipc/local/LocalIPCProxyBinder.cpp | 13 +- src/ipc/local/LocalIPCRequestHandler.h | 4 +- src/ipc/local/LocalIPCServiceAdapter.h | 6 + src/ipc/local/LocalIPCServiceAdapterBase.cpp | 25 +- src/ipc/local/LocalIPCServiceAdapterBase.h | 62 ++-- src/model/CMakeLists.txt | 7 - src/model/FaceliftEnum.h | 72 ----- tests/combined/check_combined.js | 11 + .../impl/cpp/CombinedTestsCppImplementation.h | 19 ++ .../qml/CombinedTestsQmlImplementation.qml | 7 + tests/combined/interface/another.qface | 37 +++ tests/combined/interface/combined.qface | 55 +++- tests/combined/interface/other.qface | 3 + tests/models/interface/models.qface | 2 +- tests/objectregistry/client.cpp | 2 +- 49 files changed, 931 insertions(+), 703 deletions(-) create mode 100644 src/ipc/dbus/FaceliftDBusMarshaller.h create mode 100644 tests/combined/interface/another.qface diff --git a/codegen/facelift/facelift-codegen.py b/codegen/facelift/facelift-codegen.py index e35890a4..7e5e28ab 100755 --- a/codegen/facelift/facelift-codegen.py +++ b/codegen/facelift/facelift-codegen.py @@ -132,7 +132,7 @@ def requiredIncludeFromType(symbol, suffix): def insertUniqueType(symbol, unique_types): type = symbol.type.nested if symbol.type.nested else symbol.type - if type not in (t.name for t in unique_types): + if type.name not in (t.name for t in unique_types): unique_types.append(type) def referencedTypes(self): @@ -149,21 +149,23 @@ def referencedTypes(self): insertUniqueType(param, types) return types -def appendTypeIfStructure(symbol, list): +def appendTypeIfStructureAndUnique(symbol, unique_list): type = symbol.type.nested if symbol.type.nested else symbol.type - if type.is_struct: - list.append(type) + if type.is_struct and type.name not in (t.name for t in unique_list): + unique_list.append(type) def referencedStructureTypes(self): interfaces = [] for property in self.properties: - appendTypeIfStructure(property, interfaces) + appendTypeIfStructureAndUnique(property, interfaces) for m in self.operations: for param in m.parameters: - appendTypeIfStructure(param, interfaces) + appendTypeIfStructureAndUnique(param, interfaces) + if m.hasReturnValue: + appendTypeIfStructureAndUnique(m.type, interfaces) for m in self.signals: for param in m.parameters: - appendTypeIfStructure(param, interfaces) + appendTypeIfStructureAndUnique(param, interfaces) return interfaces def appendTypeIfInterface(symbol, list): @@ -211,8 +213,8 @@ def isQMLImplementationEnabled(self): def isSerializable(self): return True if self.tags.get('serializable') else generateAll -def serializeOverIPC(self): - return True if self.tags.get('serializeOverIPC') else generateAll +def toByteArrayOverDBus(self): + return True if self.tags.get('toByteArrayOverDBus') else generateAll def isQObjectWrapperEnabled(self): return True if self.tags.get('qml-component') else False @@ -312,7 +314,7 @@ def cppMethodArgumentType(self): setattr(qface.idl.domain.Struct, 'verifyStruct', property(verifyStruct)) setattr(qface.idl.domain.Struct, 'isSerializable', property(isSerializable)) -setattr(qface.idl.domain.Struct, 'serializeOverIPC', property(serializeOverIPC)) +setattr(qface.idl.domain.Struct, 'toByteArrayOverDBus', property(toByteArrayOverDBus)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperEnabled', property(isQObjectWrapperEnabled)) setattr(qface.idl.domain.Struct, 'isQObjectWrapperDeprecated', property(isQObjectWrapperDeprecated)) @@ -371,6 +373,7 @@ def run_generation(input, output, dependency, libraryName, all): generateFile(generator, 'module/{{path}}/Module.cpp', 'Module.template.cpp', ctx, libraryName, "") generateFile(generator, 'ipc/{{path}}/ModuleIPC.h', 'ModuleIPC.template.h', ctx, libraryName, "") generateFile(generator, 'ipc/{{path}}/ModuleIPC.cpp', 'ModuleIPC.template.cpp', ctx, libraryName, "") + for interface in module.interfaces: log.debug('process interface %s' % interface) ctx.update({'interface': interface}) diff --git a/codegen/facelift/templates/IPCAdapter.template.cpp b/codegen/facelift/templates/IPCAdapter.template.cpp index e7dfd617..331dacf7 100644 --- a/codegen/facelift/templates/IPCAdapter.template.cpp +++ b/codegen/facelift/templates/IPCAdapter.template.cpp @@ -39,31 +39,10 @@ #include "InterfaceManager.h" #ifdef DBUS_IPC_ENABLED -#include #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusAdapter.h" -{% for struct in module.structs %} -#include "{{struct.fullyQualifiedPath}}.h" -{% endfor %} - -{% for enum in module.enums %} -#include "{{enum.fullyQualifiedPath}}.h" -{% endfor %} - {% for property in interface.referencedInterfaceTypes %} #include "{{property.fullyQualifiedPath}}{% if generateAsyncProxy %}Async{% endif %}IPCDBusAdapter.h" {% endfor %} - -#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255 - -{% for type in interface.referencedTypes %} -{% if (not type.is_primitive) %} -{% if (not type.is_model) %} -{% if (not type.is_interface) %} -{{type.requiredInclude}} -{% endif %} -{% endif %} -{% endif %} -{% endfor %} #endif {{module.namespaceCppOpen}} @@ -101,31 +80,6 @@ struct {{interfaceName}}IPCAdapter::Impl { {{interfaceName}}IPCAdapter::{{interfaceName}}IPCAdapter(QObject* parent) : BaseType(facelift::InterfaceManager::instance(), parent) { -#ifdef DBUS_IPC_ENABLED - {% for type in interface.referencedTypes %} - {% if (not type.is_primitive) %} - {% if (not type.is_enum) %} - {% if (not type.is_model) %} - {% if (not type.is_interface) %} - qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); - qDBusRegisterMetaType>(); - qDBusRegisterMetaType>(); - {% if type.is_struct %} - {{type.fullyQualifiedCppType}}::registerDBusTypes(); - Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", - "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to byte array stream of the struct over dbus, but yet better rethink your structure!"); - {% endif %} - {% if type.nested.is_struct %} - {{type.nested.fullyQualifiedCppType}}::registerDBusTypes(); - Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId<{{type.fullyQualifiedCppType}}>())) < DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", - "Struct's signature exceeds dbus limit, annonate @serializeOverIPC to switch to binary array stream of the struct over dbus, but yet better rethink your structure!"); - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} -#endif } {{interfaceName}}IPCAdapter::~{{interfaceName}}IPCAdapter() { diff --git a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h index feffd8a6..3d5f0cf5 100644 --- a/codegen/facelift/templates/IPCDBusServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCDBusServiceAdapter.template.h @@ -44,6 +44,7 @@ #include "IPCDBusServiceAdapter.h" #include "IPCAdapterModelPropertyHandler.h" #include "DBusManager.h" +#include "FaceliftDBusMarshaller.h" #include "{{module.fullyQualifiedPath}}/{{interfaceName}}.h" #include "{{module.fullyQualifiedPath}}/{{interfaceName}}QMLAdapter.h" @@ -86,13 +87,13 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - QMap changedProperties(); + QVariantMap changedProperties(); - void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + QVariantMap marshalProperties() override; - void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + QVariant marshalProperty(const QString& propertyName) override; - void setProperty(const QList& arguments) override; + void setProperty(const QString& propertyName, const QVariant& value) override; {% for event in interface.signals %} void {{event}}( diff --git a/codegen/facelift/templates/IPCProxy.template.cpp b/codegen/facelift/templates/IPCProxy.template.cpp index c9178172..5d100338 100644 --- a/codegen/facelift/templates/IPCProxy.template.cpp +++ b/codegen/facelift/templates/IPCProxy.template.cpp @@ -39,15 +39,6 @@ #ifdef DBUS_IPC_ENABLED #include "{{module.fullyQualifiedPath}}/{{interfaceName}}IPCDBusProxy.h" -{% for type in interface.referencedTypes %} -{% if (not type.is_primitive) %} -{% if (not type.is_model) %} -{% if (not type.is_interface) %} -{{type.requiredInclude}} -{% endif %} -{% endif %} -{% endif %} -{% endfor %} #endif {% set className = interfaceName + "IPCProxy" %} @@ -90,22 +81,6 @@ struct {{className}}::Impl { {{className}}::{{className}}(QObject *parent) : BaseType(facelift::InterfaceManager::instance(), parent), m_impl(std::make_unique()) { -#ifdef DBUS_IPC_ENABLED - {% for type in interface.referencedTypes %} - {% if (not type.is_primitive) %} - {% if (not type.is_enum) %} - {% if (not type.is_model) %} - {% if (not type.is_interface) %} - qDBusRegisterMetaType<{{type.fullyQualifiedCppType}}>(); - qDBusRegisterMetaType>(); - qDBusRegisterMetaType>(); - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} -#endif - ipc()->setObjectPath(SINGLETON_OBJECT_PATH); {% if generateAsyncProxy %} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.cpp b/codegen/facelift/templates/IPCProxyAdapter.template.cpp index 69bf72c9..34929979 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.cpp +++ b/codegen/facelift/templates/IPCProxyAdapter.template.cpp @@ -36,8 +36,6 @@ {% set className = interfaceName + proxyTypeNameSuffix %} #include "{{className}}.h" -#include "FaceliftEnum.h" - {{module.namespaceCppOpen}} {{className}}::{{className}}(QObject *parent) : BaseType(parent) @@ -53,53 +51,56 @@ {% endif %} } -void {{className}}::unmarshalPropertyValues(InputIPCMessage &msg) +void {{className}}::unmarshalProperties(const QVariantMap& values) { - QListIterator argumentsIterator(msg.arguments()); - if (argumentsIterator.hasNext()) { - QMap values = castFromVariant>(argumentsIterator.next()); - for (const QString &propertyName: values.keys()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_interface %} - const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); - bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% elif property.type.is_model %} - bool emit_{{property.name}}ChangeSignal = true; - int {{property.name}}Size = castFromDBusVariant(values[propertyName]); - m_{{property.name}}.beginResetModel(); - m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); - m_{{property.name}}.endResetModel(); - {% else %} - const auto previous_{{property.name}}_Value = m_{{property.name}}; - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(values[propertyName]); - bool emit_{{property.name}}ChangeSignal = ((previous_{{property.name}}_Value != m_{{property.name}})); - {% endif %} - if (emit_{{property.name}}ChangeSignal) - emit {{property.name}}Changed(); - } - {% endfor %} - if (propertyName == QStringLiteral("ready")) { - bool previousIsReady = this->ready(); - m_serviceReady = castFromDBusVariant(values[propertyName]); - bool emit_ReadyChangeSignal = (previousIsReady != m_serviceReady); - if (emit_ReadyChangeSignal) - emit readyChanged(); - } + QMap emitChangeSignal; + for (const QString &propertyName: values.keys()) { + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_interface %} + const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); + emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% elif property.type.is_model %} + emitChangeSignal[QStringLiteral("{{property.name}}")] = true; + int {{property.name}}Size = castFromQVariant(values[propertyName]); + m_{{property.name}}.beginResetModel(); + m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); + m_{{property.name}}.endResetModel(); + {% else %} + const auto previous_{{property.name}}_Value = m_{{property.name}}; + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); + emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); + {% endif %} + } + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + bool previousIsReady = this->ready(); + m_serviceReady = castFromQVariant(values[propertyName]); + emitChangeSignal[QStringLiteral("ready")] = (previousIsReady != m_serviceReady); + } + } + for (const QString &propertyName: emitChangeSignal.keys()) { + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}") && emitChangeSignal[propertyName]) { + emit {{property.name}}Changed(); + } + {% endfor %} + if (propertyName == QStringLiteral("ready") && emitChangeSignal[propertyName]) { + emit readyChanged(); } } } void {{className}}::handleSignals(InputIPCMessage& msg) { - Q_UNUSED(msg); + Q_UNUSED(msg) {% for event in interface.signals %} if (msg.member() == QStringLiteral("{{event}}")) { QListIterator argumentsIterator(msg.arguments()); {% for parameter in event.parameters %} {{parameter.interfaceCppType}} param_{{parameter.name}}; - param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); + param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromQVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); {% endfor %} emit {{event}}( {%- set comma = joiner(", ") -%} @@ -121,11 +122,11 @@ const QList& {{className}}::getSignals() const "{{event}}", {% endfor %} {% if interface.hasModelProperty %} - "ModelUpdateEventDataChanged", - "ModelUpdateEventInsert", - "ModelUpdateEventRemove", - "ModelUpdateEventMove", - "ModelUpdateEventReset" + facelift::IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME, + facelift::IPCCommon::MODEL_INSERT_MESSAGE_NAME, + facelift::IPCCommon::MODEL_REMOVE_MESSAGE_NAME, + facelift::IPCCommon::MODEL_MOVE_MESSAGE_NAME, + facelift::IPCCommon::MODEL_RESET_MESSAGE_NAME, {% endif %} }; @@ -136,7 +137,7 @@ const QList& {{className}}::getSignals() const void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) { QListIterator argumentsIterator(msg.arguments()); - const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); {% for property in interface.properties %} {% if property.type.is_model %} if (modelPropertyName == QStringLiteral("{{property.name}}")) { @@ -147,22 +148,19 @@ void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) } {% endif %} -void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) +void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedProperties) { {% if interface.properties %} - QListIterator argumentsIterator(msg.arguments()); - QString interfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QVariantMap()); for (const QString &propertyName: changedProperties.keys()) { {% for property in interface.properties %} if (propertyName == QStringLiteral("{{property.name}}")) { {% if property.type.is_model %} - int {{property.name}}Size = castFromDBusVariant(changedProperties[propertyName]); + int {{property.name}}Size = castFromQVariant(changedProperties[propertyName]); m_{{property.name}}.beginResetModel(); m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); m_{{property.name}}.endResetModel(); {% else %} - m_{{property.name}} = castFromDBusVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); + m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); {% endif %} } {% endfor %} @@ -177,7 +175,7 @@ void {{className}}::unmarshalPropertiesChanged(InputIPCMessage &msg) {% endfor %} } {% else %} - Q_UNUSED(msg); + Q_UNUSED(changedProperties); {% endif %} } @@ -226,7 +224,7 @@ void {{className}}::{{operation.name}}( {%- for parameter in operation.parameters -%} , {{parameter.name}} {%- endfor -%} ); - return (!args.isEmpty() ? castFromVariant<{{operation.interfaceCppType}}>(args[0]):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); + return (!args.isEmpty() ? castFromQVariant<{{operation.interfaceCppType}}>(args.first()):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); {% else %} ipc()->sendMethodCall(memberID(MethodID::{{operation.name}}, "{{operation.name}}") {%- for parameter in operation.parameters -%} diff --git a/codegen/facelift/templates/IPCProxyAdapter.template.h b/codegen/facelift/templates/IPCProxyAdapter.template.h index b3d321fc..5431d646 100644 --- a/codegen/facelift/templates/IPCProxyAdapter.template.h +++ b/codegen/facelift/templates/IPCProxyAdapter.template.h @@ -67,7 +67,7 @@ class {{classExport}} {{className}} : public {{baseClass}} {{className}}(QObject *parent = nullptr); - void unmarshalPropertyValues(InputIPCMessage &msg) override; + void unmarshalProperties(const QVariantMap& values) override; {% if interface.hasModelProperty %} void setServiceRegistered(bool isRegistered) override @@ -85,9 +85,10 @@ class {{classExport}} {{className}} : public {{baseClass}} {% endif %} void handleSignals(InputIPCMessage& msg) override; + const QList& getSignals() const override; - void unmarshalPropertiesChanged(InputIPCMessage &msg) override; + void unmarshalPropertiesChanged(const QVariantMap& changedProperties) override; {% for operation in interface.operations %} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.cpp b/codegen/facelift/templates/IPCServiceAdapter.template.cpp index 4f7ecbbe..9b2b6af1 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.cpp +++ b/codegen/facelift/templates/IPCServiceAdapter.template.cpp @@ -35,7 +35,7 @@ {% set className = interfaceName + proxyTypeNameSuffix %} -#include +#include "ipc-common.h" #include "{{className}}.h" {{module.namespaceCppOpen}} @@ -56,7 +56,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for operation in interface.operations %} if (member == memberID(MethodID::{{operation.name}}, "{{operation.name}}")) { {% for parameter in operation.parameters %} - {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromVariant<{{parameter.cppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.cppType}}(){% else %}nullptr{% endif %}); + {{parameter.cppType}} param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromQVariant<{{parameter.cppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.cppType}}(){% else %}nullptr{% endif %}); {% endfor %} {% if operation.isAsync %} theService->{{operation.name}}({% for parameter in operation.parameters %} param_{{parameter.name}}, {%- endfor -%} @@ -74,7 +74,7 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {{ comma() }}param_{{parameter.name}} {%- endfor -%}); {% if operation.hasReturnValue %} - replyMessage << castToVariant(returnValue); + replyMessage << castToQVariant(returnValue); {% endif %} {% endif %} } else @@ -82,7 +82,10 @@ facelift::IPCHandlingResult {{className}}::handleMethodCallMessage(InputIPCMessa {% for property in interface.properties %} {% if property.type.is_model %} if (member == memberID(MethodID::{{property.name}}, "{{property.name}}")) { - m_{{property.name}}Handler.handleModelRequest(requestMessage, replyMessage); + QListIterator argumentsIterator(requestMessage.arguments()); + int first = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): int()); + m_{{property.name}}Handler.handleModelRequest(first, last, replyMessage); } else {% endif %} {% endfor %} @@ -134,11 +137,31 @@ void {{className}}::appendDBUSIntrospectionData(QTextStream &s) const {% endfor %} {% if interface.hasModelProperty %} - s << ""; + s << ""; s << ""; s << ""; s << ""; s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; + s << ""; {% endif %} } @@ -154,6 +177,7 @@ void {{className}}::connectSignals() m_previous{{property.name}} = theService->{{property.name}}(); {% endif %} {% endfor %} + m_previousReadyState = theService->ready(); // Properties {% for property in interface.properties %} @@ -165,7 +189,7 @@ void {{className}}::connectSignals() {% endfor %} QObject::connect(theService, &ServiceType::readyChanged, this, [this, theService] () { - this->sendPropertiesChanged(QMap{ {"ready", castToDBusVariant(theService->ready())} }); + this->sendPropertiesChanged(changedProperties()); }); // Signals @@ -174,86 +198,77 @@ void {{className}}::connectSignals() {% endfor %} } -QMap {{className}}::changedProperties() +QVariantMap {{className}}::changedProperties() { - QMap ret; + QMap ret; auto theService = service(); Q_UNUSED(theService); {% for property in interface.properties %} {% if not property.type.is_model %} if (m_previous{{property.name}} != theService->{{property.name}}()) { - ret[QStringLiteral("{{property.name}}")] = castToDBusVariant(theService->{{property.name}}()); + ret[QStringLiteral("{{property.name}}")] = castToQVariant(theService->{{property.name}}()); m_previous{{property.name}} = theService->{{property.name}}(); } {% endif %} {% endfor %} + if (m_previousReadyState != theService->ready()) { + ret[QStringLiteral("ready")] = castToQVariant(theService->ready()); + m_previousReadyState = theService->ready(); + } return ret; } -void {{className}}::marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) +QVariantMap {{className}}::marshalProperties() { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto theService = service(); - QMap ret; - {#% if (not interface.properties) %#} - Q_UNUSED(theService); - {#% endif %#} + QVariantMap ret; + auto theService = service(); + {#% if (not interface.properties) %#} + Q_UNUSED(theService); + {#% endif %#} - {% for property in interface.properties %} - {% if property.type.is_model %} - ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}().size()); - {% else %} - ret["{{property.name}}"] = castToDBusVariant(theService->{{property.name}}()); - {% endif %} - {% endfor %} - ret["ready"] = castToDBusVariant(theService->ready()); - msg << castToVariant(ret); - } + {% for property in interface.properties %} + {% if property.type.is_model %} + ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}().size()); + {% else %} + ret["{{property.name}}"] = castToQVariant(theService->{{property.name}}()); + {% endif %} + {% endfor %} + ret["ready"] = castToQVariant(theService->ready()); + return ret; } -void {{className}}::marshalProperty(const QList& arguments, OutputIPCMessage& msg) +QVariant {{className}}::marshalProperty(const QString& propertyName) { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_model %} + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_model %} - {% else %} - msg << castToVariant(service()->{{property.name}}()); - {% endif %} - } - {% endfor %} - if (propertyName == QStringLiteral("ready")) { - msg << castToVariant(service()->ready()); - } + {% else %} + return castToQVariant(service()->{{property.name}}()); + {% endif %} } + {% endfor %} + if (propertyName == QStringLiteral("ready")) { + return castToQVariant(service()->ready()); + } +return QVariant(); } -void {{className}}::setProperty(const QList& arguments) +void {{className}}::setProperty(const QString& propertyName, const QVariant& value) { - QListIterator argumentsIterator(arguments); - auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (msgInterfaceName == interfaceName()) { - auto propertyName = (argumentsIterator.hasNext() ? castFromVariant(argumentsIterator.next()): QString()); - if (argumentsIterator.hasNext()) { - {% for property in interface.properties %} - if (propertyName == QStringLiteral("{{property.name}}")) { - {% if property.type.is_interface %} - Q_ASSERT(false); // Writable interface properties are unsupported - {% elif property.type.is_model %} + Q_UNUSED(propertyName) + Q_UNUSED(value) + {% for property in interface.properties %} + if (propertyName == QStringLiteral("{{property.name}}")) { + {% if property.type.is_interface %} + Q_ASSERT(false); // Writable interface properties are unsupported + {% elif property.type.is_model %} - {% elif (not property.readonly) %} - service()->set{{property.name}}(castFromDBusVariant<{{property.cppType}}>(argumentsIterator.next())); - {% endif %} - } - {% endfor %} - } + {% elif (not property.readonly) %} + service()->set{{property.name}}(castFromQVariant<{{property.cppType}}>(value)); + {% endif %} } + {% endfor %} } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/IPCServiceAdapter.template.h b/codegen/facelift/templates/IPCServiceAdapter.template.h index d2f0bc0b..0caf13f1 100644 --- a/codegen/facelift/templates/IPCServiceAdapter.template.h +++ b/codegen/facelift/templates/IPCServiceAdapter.template.h @@ -82,13 +82,13 @@ class {{classExport}} {{className}}: public {{baseClass}} void connectSignals() override; - QMap changedProperties(); + QVariantMap changedProperties(); - void marshalPropertyValues(const QList& arguments, OutputIPCMessage& msg) override; + QVariantMap marshalProperties() override; - void marshalProperty(const QList& arguments, OutputIPCMessage& msg) override; + QVariant marshalProperty(const QString& propertyName) override; - void setProperty(const QList& arguments) override; + void setProperty(const QString& propertyName, const QVariant& value) override; {% for event in interface.signals %} void {{event}}( @@ -112,6 +112,7 @@ class {{classExport}} {{className}}: public {{baseClass}} {{property.interfaceCppType}} m_previous{{property.name}} {}; {% endif %} {% endfor %} + bool m_previousReadyState = false; }; {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/ImplementationBase.template.h b/codegen/facelift/templates/ImplementationBase.template.h index 9ee36edb..6f9a23e5 100644 --- a/codegen/facelift/templates/ImplementationBase.template.h +++ b/codegen/facelift/templates/ImplementationBase.template.h @@ -91,7 +91,6 @@ class {{classExport}} {{interfaceName}}ImplementationBase : public {{interfaceNa {% endif %} {% endfor %} - Q_PROPERTY(bool ready READ ready) bool ready() const override { return m_ready.value(); diff --git a/codegen/facelift/templates/Service.template.cpp b/codegen/facelift/templates/Service.template.cpp index 82728d66..23b1a86b 100644 --- a/codegen/facelift/templates/Service.template.cpp +++ b/codegen/facelift/templates/Service.template.cpp @@ -58,7 +58,6 @@ constexpr const char* {{interfaceName}}::FULLY_QUALIFIED_INTERFACE_NAME; }); } #endif - registerTypes(""); } {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Struct.template.cpp b/codegen/facelift/templates/Struct.template.cpp index 60dc0e05..75649dcf 100644 --- a/codegen/facelift/templates/Struct.template.cpp +++ b/codegen/facelift/templates/Struct.template.cpp @@ -36,12 +36,7 @@ ****************************************************************************/ #include "{{struct}}.h" -#ifdef DBUS_IPC_ENABLED -#include -#include -#endif #include "FaceliftConversion.h" -#include "FaceliftEnum.h" {{module.namespaceCppOpen}} @@ -100,6 +95,12 @@ void {{struct.name}}::deserialize(const QByteArray &array) {% endif %} +{% if struct.toByteArrayOverDBus %} +bool {{struct.name}}::toByteArrayOverDBus() +{ + return true; +} +{% endif %} const {{struct}}::FieldNames {{struct}}::FIELD_NAMES = { { {%- for field in struct.fields -%} @@ -131,77 +132,4 @@ QString {{struct.name}}::toString() const return toStringWithFields(CLASS_ID, FIELD_NAMES); } -#ifdef DBUS_IPC_ENABLED -void {{struct.name}}::registerDBusTypes() -{ - {% for field in struct.fields %} - {% if field.type.is_struct %} - {{field.type.cppType}}::registerDBusTypes(); - {% endif %} - {% if field.type.nested.is_struct %} - {{field.type.nested.cppType}}::registerDBusTypes(); - {% endif %} - {% if (not field.type.is_primitive and not field.type.is_enum and not field.type.is_model and not field.type.is_interface and not field.type.is_list and not field.type.is_map) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - {% endif %} - {% if (field.type.is_list or field.type.is_map) %} - {% if (not field.type.nested.is_primitive) or (not field.type.nested.is_enum) %} - qDBusRegisterMetaType<{{field.cppType}}>(); - qDBusRegisterMetaType<{{field.type.nested.cppType}}>(); - {% endif %} - {% endif %} - {% endfor %} -} - -QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% if not struct.serializeOverIPC %} - {% for field in struct.fields %} - argument << {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - {% else %} - QByteArray byteArray; - QDataStream dataStream(&byteArray, QIODevice::WriteOnly); - dataStream << {{struct.name|lower}}; - argument << byteArray; - {% endif %} - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}) -{ - argument.beginStructure(); - {% if not struct.serializeOverIPC %} - {% for field in struct.fields %} - argument >> {{struct.name|lower}}.m_{{field}}; - {% endfor -%} - {% else %} - QByteArray byteArray; - QDataStream dataStream(&byteArray, QIODevice::ReadOnly); - argument >> byteArray; - dataStream >> {{struct.name|lower}}; - {% endif %} - argument.endStructure(); - - return argument; -} - -QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ) -{ - {% for field in struct.fields %} - dataStream << {{struct.name|lower}}.m_{{field}}; - {% endfor %} - return dataStream; -} - -QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ) -{ - {% for field in struct.fields %} - dataStream >> {{struct.name|lower}}.m_{{field}}; - {% endfor %} - return dataStream; -} -#endif {{module.namespaceCppClose}} diff --git a/codegen/facelift/templates/Struct.template.h b/codegen/facelift/templates/Struct.template.h index 4f0439e4..8b604db7 100644 --- a/codegen/facelift/templates/Struct.template.h +++ b/codegen/facelift/templates/Struct.template.h @@ -47,7 +47,6 @@ {{field.type.requiredInclude}} {% endfor %} -class QDBusArgument; {{module.namespaceCppOpen}} {% if struct.isQObjectWrapperEnabled %} @@ -85,15 +84,6 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {{struct.name}}& operator=(const {{struct.name}} &right); - friend QDBusArgument &operator<<(QDBusArgument &argument, const {{struct.name}} &{{struct.name|lower}}); - friend const QDBusArgument &operator>>(const QDBusArgument &argument, {{struct.name}} &{{struct.name|lower}}); - - - friend QDataStream& operator<<( QDataStream& dataStream, const {{struct.name}} &{{struct.name|lower}} ); - friend QDataStream& operator>>( QDataStream& dataStream, {{struct.name}} &{{struct.name|lower}} ); - - static void registerDBusTypes(); - Q_INVOKABLE {{struct.fullyQualifiedCppType}} clone() const; {% if struct.isSerializable %} @@ -106,6 +96,10 @@ class {{classExport}} {{struct.name}} : public facelift::Structure< {% endif %} + {% if struct.toByteArrayOverDBus %} + static bool toByteArrayOverDBus(); + {% endif %} + QString toString() const; {% for field in struct.fields %} diff --git a/doc/page-annotations.h b/doc/page-annotations.h index 334a8f3c..03a6f8ee 100644 --- a/doc/page-annotations.h +++ b/doc/page-annotations.h @@ -39,7 +39,7 @@ The following annotations can be used in structure definitions: |Annotation | Description | Supported over IPC | |-------------------------------|-------------------------------------------------------------|--------------------| -|\@serializeOverIPC: true | Treat the whole structure as byte array over IPC reducing structure signature only to DBUS Type BYTE | Yes | +|\@toByteArrayOverDBus: true | Serialize the whole structure as one byte array over IPC reducing structure signature only to DBUS Type ARRAY OF BYTE | Yes | |\@serializable: true | Adds serialization/deserialization capability to the structure | Yes | |\@qml-component: true | Enables the creation and registration of a creatable QML component for the corresponding structure | Yes | diff --git a/src/ipc/dbus/CMakeLists.txt b/src/ipc/dbus/CMakeLists.txt index e865445a..cbc9cf9a 100644 --- a/src/ipc/dbus/CMakeLists.txt +++ b/src/ipc/dbus/CMakeLists.txt @@ -25,6 +25,7 @@ if(Qt5DBus_FOUND) DBusManager.h DBusManagerInterface.h DBusIPCProxy.h + FaceliftDBusMarshaller.h IPCDBusServiceAdapter.h DBusObjectRegistry.h DBusIPCMessage.h diff --git a/src/ipc/dbus/DBusIPCCommon.h b/src/ipc/dbus/DBusIPCCommon.h index 676a0bdc..f39a1561 100644 --- a/src/ipc/dbus/DBusIPCCommon.h +++ b/src/ipc/dbus/DBusIPCCommon.h @@ -36,20 +36,19 @@ # define FaceliftIPCLibDBus_EXPORT Q_DECL_IMPORT #endif - namespace facelift { namespace dbus { using namespace facelift; - struct FaceliftIPCLibDBus_EXPORT DBusIPCCommon { - static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; - static constexpr const char *GET_PROPERTY = "Get"; - static constexpr const char *SET_PROPERTY = "Set"; + static constexpr const char *DEFAULT_SERVICE_NAME = "facelift.registry"; + static constexpr const char *GET_ALL_PROPERTIES_MESSAGE_NAME = "GetAll"; + static constexpr const char *GET_PROPERTY_MESSAGE_NAME = "Get"; + static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "Set"; static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; - static constexpr const char *DEFAULT_SERVICE_NAME = "facelift.registry"; + static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; + static constexpr const int FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH = 255; }; } diff --git a/src/ipc/dbus/DBusIPCMessage.cpp b/src/ipc/dbus/DBusIPCMessage.cpp index 77bc35f8..f259afa4 100644 --- a/src/ipc/dbus/DBusIPCMessage.cpp +++ b/src/ipc/dbus/DBusIPCMessage.cpp @@ -74,14 +74,7 @@ QList DBusIPCMessage::arguments() const DBusIPCMessage &DBusIPCMessage::operator<<(const QVariant &arg) { - static int qListStringTypeId = qMetaTypeId>(); - if (arg.userType() != qListStringTypeId) { // workaround to use QList since its signature matches the QStringList - m_message << arg; - } - else { - QStringList stringList(arg.value>()); - m_message << stringList; - } + m_message << arg; return *this; } @@ -117,9 +110,9 @@ DBusIPCMessage DBusIPCMessage::createReply() return DBusIPCMessage(m_message.createReply()); } -DBusIPCMessage DBusIPCMessage::createErrorReply(const QString &msg, const QString &member) +DBusIPCMessage DBusIPCMessage::createErrorReply(const QString &name, const QString &msg) { - return DBusIPCMessage(m_message.createErrorReply(msg, member)); + return DBusIPCMessage(m_message.createErrorReply(name, msg)); } QString DBusIPCMessage::signature() const diff --git a/src/ipc/dbus/DBusIPCMessage.h b/src/ipc/dbus/DBusIPCMessage.h index e517d322..b8f07b26 100644 --- a/src/ipc/dbus/DBusIPCMessage.h +++ b/src/ipc/dbus/DBusIPCMessage.h @@ -63,7 +63,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCMessage QList arguments() const; DBusIPCMessage &operator<<(const QVariant &arg); DBusIPCMessage createReply(); - DBusIPCMessage createErrorReply(const QString &msg, const QString &member); + DBusIPCMessage createErrorReply(const QString &name, const QString &msg); QString signature() const; bool isReplyMessage() const; bool isErrorMessage() const; diff --git a/src/ipc/dbus/DBusIPCProxy.h b/src/ipc/dbus/DBusIPCProxy.h index 1d29e475..e09c675c 100644 --- a/src/ipc/dbus/DBusIPCProxy.h +++ b/src/ipc/dbus/DBusIPCProxy.h @@ -106,13 +106,8 @@ class DBusIPCProxy : public IPCProxyBase, protected DBusRequestHa } template - T castFromVariant(const QVariant& value) { - return m_ipcBinder.castFromVariant(value); - } - - template - T castFromDBusVariant(const QVariant& value) { - return m_ipcBinder.castFromDBusVariant(value); + T castFromQVariant(const QVariant& value) { + return m_ipcBinder.castFromQVariant(value); } protected: diff --git a/src/ipc/dbus/DBusIPCProxyBinder.cpp b/src/ipc/dbus/DBusIPCProxyBinder.cpp index 97355801..6f62ff5d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.cpp +++ b/src/ipc/dbus/DBusIPCProxyBinder.cpp @@ -32,7 +32,6 @@ #include "DBusIPCProxyBinder.h" #include "DBusManagerInterface.h" #include "DBusRequestHandler.h" -#include "DBusIPCCommon.h" #include "DBusObjectRegistry.h" namespace facelift { @@ -71,7 +70,12 @@ void DBusIPCProxyBinder::onServerNotAvailableError(const QString &propertyName) void DBusIPCProxyBinder::onPropertiesChanged(const QDBusMessage &dbusMessage) { DBusIPCMessage msg(dbusMessage); - m_serviceObject->unmarshalPropertiesChanged(msg); + QListIterator argumentsIterator(msg.arguments()); + QString interfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (interfaceName == m_interfaceName) { + QVariantMap changedProperties = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(changedProperties); + } } void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) @@ -83,11 +87,12 @@ void DBusIPCProxyBinder::setHandler(DBusRequestHandler *handler) void DBusIPCProxyBinder::requestPropertyValues() { - DBusIPCMessage msg(serviceName(), objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::GET_ALL_PROPERTIES); + DBusIPCMessage msg(serviceName(), objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME); msg << QVariant::fromValue(interfaceName()); auto replyHandler = [this](DBusIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->unmarshalPropertyValues(replyMessage); + QVariantMap values = (!replyMessage.arguments().isEmpty() ? castFromQVariant(replyMessage.arguments().first()): QVariantMap()); + m_serviceObject->unmarshalProperties(values); m_serviceObject->setServiceRegistered(true); } else { qCDebug(LogIpc) << "Service not yet available : " << objectPath(); diff --git a/src/ipc/dbus/DBusIPCProxyBinder.h b/src/ipc/dbus/DBusIPCProxyBinder.h index 3e52e732..c10fd53d 100644 --- a/src/ipc/dbus/DBusIPCProxyBinder.h +++ b/src/ipc/dbus/DBusIPCProxyBinder.h @@ -40,8 +40,9 @@ #include #include "IPCProxyBinderBase.h" #include "DBusIPCMessage.h" -#include "FaceliftUtils.h" #include "DBusIPCCommon.h" +#include "FaceliftUtils.h" +#include "FaceliftDBusMarshaller.h" #include "DBusManagerInterface.h" #include "IPCServiceAdapterBase.h" @@ -100,7 +101,7 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendSetterCall(const QString& property, const PropertyType &value); template - DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args); + DBusIPCMessage sendMethodCall(const char *methodName, Args && ... args) const; template void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); @@ -109,95 +110,107 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase void sendAsyncMethodCall(const char *methodName, facelift::AsyncAnswer answer, Args && ... args); template - QList sendMethodCallWithReturn(const char *methodName, Args && ... args); + QList sendMethodCallWithReturn(const char *methodName, Args && ... args) const; void setHandler(DBusRequestHandler *handler); template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); + T castFromQVariant(const QVariant& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castFromQVariantSpecialized(HelperType(), value); } template - T castFromDBusVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); - } - - template - QVariant castToVariant(const T& value) { - return castToVariantSpecialized(HelperType(), value); - } - - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); + QVariant castToQVariant(const T& value) const { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castToQVariantSpecialized(HelperType(), value); } private: void checkRegistry(); - template struct HelperType { }; - template::value && !std::is_enum::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qdbus_cast(value); } + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + } + template::value && std::is_enum::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return static_cast(qdbus_cast(value)); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList + template::value && std::is_enum::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + QList tmp = qdbus_cast>(value); + std::transform(tmp.begin(), tmp.end(), std::back_inserter(ret), [](const int entry){return static_cast(entry);}); + return ret; + } + + template::value && std::is_enum::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + QMap tmp = qdbus_cast>(value); + for (const QString& key: tmp.keys()) { + ret[key] = static_cast(tmp[key]); + } + return ret; } template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { - return getOrCreateSubProxy::type::IPCDBusProxyType>(qdbus_cast(value)); + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCDBusProxyType>(qdbus_cast(value)); } - template - QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { - QMap ret; - auto objectPaths = qdbus_cast>(value); + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qdbus_cast>(value); for (const QString& key: objectPaths.keys()) { - ret[key] = getOrCreateSubProxy(objectPaths[key]); + ret[key] = getOrCreateSubProxy::type::IPCDBusProxyType>(objectPaths[key]); } return ret; } - template - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - QList ret; - auto objectPaths = qdbus_cast*/>(value); - for (const DBusObjectPath& objectPath: objectPaths) { - ret.append(getOrCreateSubProxy(objectPath)); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qdbus_cast(value); + for (const QString& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy::type::IPCDBusProxyType>(objectPath)); } return ret; } template::value && !std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) const { return QVariant::fromValue(value); } - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) const { return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } template::value && std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) const { return QVariant::fromValue(static_cast(value)); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QList& value) { - return QVariant::fromValue(static_cast>(value)); + QVariant castToQVariantSpecialized(HelperType>, const QList& value) const { + QList ret; + std::transform(value.begin(), value.end(), std::back_inserter(ret), [](const T entry){return static_cast(entry);}); + return QVariant::fromValue(ret); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) const { QMap ret; for (const QString& key: value.keys()) { ret[key] = static_cast(value[key]); @@ -214,12 +227,12 @@ class FaceliftIPCLibDBus_EXPORT DBusIPCProxyBinder : public IPCProxyBinderBase template -inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) +inline DBusIPCMessage DBusIPCProxyBinder::sendMethodCall(const char *methodName, Args && ... args) const { DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; auto replyMessage = this->call(msg); if (replyMessage.isErrorMessage()) { @@ -234,13 +247,13 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [this, answer](DBusIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { if (!msg.arguments().isEmpty()) { - returnValue = castFromVariant(msg.arguments()[0]); + returnValue = castFromQVariant(msg.arguments().first()); } answer(returnValue); } else { @@ -255,7 +268,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face DBusIPCMessage msg(m_serviceName, objectPath(), m_interfaceName, methodName); using expander = int[]; (void)expander{0, - (void(msg << castToVariant(std::forward(args))), 0)... + (void(msg << castToQVariant(std::forward(args))), 0)... }; asyncCall(msg, this, [answer](DBusIPCMessage &msg) { Q_UNUSED(msg) @@ -264,7 +277,7 @@ inline void DBusIPCProxyBinder::sendAsyncMethodCall(const char *methodName, face } template -inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) +inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char *methodName, Args && ... args) const { DBusIPCMessage msg = sendMethodCall(methodName, args ...); QList ret; @@ -277,10 +290,10 @@ inline QList DBusIPCProxyBinder::sendMethodCallWithReturn(const char * template inline void DBusIPCProxyBinder::sendSetterCall(const QString &property, const PropertyType &value) { - DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY); + DBusIPCMessage msg(m_serviceName, objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::SET_PROPERTY_MESSAGE_NAME); msg << QVariant::fromValue(m_interfaceName); - msg << castToVariant(property); - msg << QVariant::fromValue(castToDBusVariant(value)); + msg << castToQVariant(property); + msg << QVariant::fromValue(QDBusVariant(castToQVariant(value))); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { diff --git a/src/ipc/dbus/DBusObjectRegistry.cpp b/src/ipc/dbus/DBusObjectRegistry.cpp index d07c490f..d91a4ccc 100644 --- a/src/ipc/dbus/DBusObjectRegistry.cpp +++ b/src/ipc/dbus/DBusObjectRegistry.cpp @@ -122,7 +122,7 @@ void DBusObjectRegistry::syncObjects() ObjectRegistryIPCDBusProxy objectRegistryProxy; objectRegistryProxy.ipc()->setServiceName(m_serviceName); objectRegistryProxy.connectToServer(); - // Q_ASSERT(objectRegistryProxy.ready()); + Q_ASSERT(objectRegistryProxy.ready()); updateObjects(objectRegistryProxy.getObjects()); } diff --git a/src/ipc/dbus/DBusRequestHandler.h b/src/ipc/dbus/DBusRequestHandler.h index a72f0af7..4588ab16 100644 --- a/src/ipc/dbus/DBusRequestHandler.h +++ b/src/ipc/dbus/DBusRequestHandler.h @@ -45,8 +45,8 @@ class FaceliftIPCLibDBus_EXPORT DBusRequestHandler { public: - virtual void unmarshalPropertyValues(DBusIPCMessage &msg) = 0; - virtual void unmarshalPropertiesChanged(DBusIPCMessage &msg) = 0; + virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; virtual void handleSignals(DBusIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/dbus/FaceliftDBusMarshaller.h b/src/ipc/dbus/FaceliftDBusMarshaller.h new file mode 100644 index 00000000..8ec14318 --- /dev/null +++ b/src/ipc/dbus/FaceliftDBusMarshaller.h @@ -0,0 +1,268 @@ +/********************************************************************** +** +** Copyright (C) 2018 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +#pragma once + +#include +#include "FaceliftUtils.h" +#include "StructureBase.h" +#include "DBusIPCCommon.h" + +template struct HelperType { }; + +template::value && !std::is_enum::value, int> = 0> +void registerDBusType(HelperType) +{ + // DO NOTHIG FOR BUILTIN TYPES +} + +template::value && std::is_enum::value, int> = 0> +void registerDBusType(HelperType) +{ + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround is to handle in castToQVariant the conversion + //qDBusRegisterMetaType(); +} + +template::value, int> = 0> +void registerDBusType(HelperType) +{ + qDBusRegisterMetaType(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} +template::value, int> = 0> +void registerDBusType(HelperType>) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId>())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} + +template::value, int> = 0> +void registerDBusType(HelperType>) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType>(); + Q_ASSERT_X(strlen(QDBusMetaType::typeToSignature(qMetaTypeId>())) < facelift::dbus::DBusIPCCommon::FACELIFT_DBUS_MAXIMUM_SIGNATURE_LENGTH, "Signature overflow", + "Struct's signature exceeds dbus limit, annonate @toByteArrayOverDBus to switch to byte array stream of the struct over dbus, better yet rethink your structure!"); +} + +struct ToQDBusArgument +{ + ToQDBusArgument(QDBusArgument& argument): m_argument(argument) + {} + template + void operator()(T &&value) + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType::type>());}); + m_argument << value; + } + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround to convert enum to int + template::type>::value, int> = 0> + void operator()(const QList &value) + { + QList tmp; + std::transform(value.begin(), value.end(), std::back_inserter(tmp), [](const T entry){return static_cast(entry);}); + m_argument << tmp; + } + template::type>::value, int> = 0> + void operator()(const QMap &value) + { + QMap tmp; + for (const QString key: value.keys()) { + tmp[key] = static_cast(value[key]); + } + m_argument << tmp; + } + QDBusArgument m_argument; +}; + +struct FromQDBusArgument +{ + FromQDBusArgument(const QDBusArgument& argument): m_argument(argument) + {} + template + void operator()(T &&value) + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType::type>());}); + m_argument >> value; + } + // Can't register an enum to have basic DBus types (int) in QtDBus -> Bug ticket QTBUG-86867 + // workaround to convert enum to int + template::type>::value, int> = 0> + void operator()(const QList &value) + { + QList tmp; + m_argument >> tmp; + std::transform(tmp.begin(), tmp.end(), std::back_inserter(value), [](const int entry){return static_cast(entry);}); + } + template::type>::value, int> = 0> + void operator()(const QMap &value) + { + QMap tmp; + m_argument >> tmp; + for (const QString& key: tmp.keys()) { + value[key] = static_cast(tmp[key]); + } + } + const QDBusArgument& m_argument; +}; + +struct FromQDataStream +{ + FromQDataStream(QDataStream& dataStream): m_dataStream(dataStream) + {} + template + void operator()(T &&value) + { + m_dataStream >> value; + } + QDataStream& m_dataStream; +}; + +struct ToQDataStream +{ + ToQDataStream(QDataStream& dataStream): m_dataStream(dataStream) + {} + template + void operator()(T &&value) + { + m_dataStream << value; + } + QDataStream& m_dataStream; +}; + +template +class ToByteArrayOverDBus +{ +private: + typedef char YesType[1]; + typedef char NoType[2]; + + template static YesType& test( decltype(&C::toByteArrayOverDBus) ) ; + template static NoType& test(...); +public: + enum { value = sizeof(test(0)) == sizeof(YesType) }; +}; + + +template::value, int> = 0> +inline QDataStream& operator<<(QDataStream &dataStream, const T& source) +{ + dataStream << static_cast(source); + return dataStream; +} + +template::value, int> = 0> +inline const QDataStream& operator>>(QDataStream &dataStream, T &source) +{ + int value; + dataStream >> value; + source = static_cast(value); + return dataStream; +} + +template::value, int> = 0> +inline QDataStream& operator<<( QDataStream& dataStream, const T &structure) +{ + facelift::for_each_in_tuple_const(structure.asTuple(), ToQDataStream(dataStream)); + return dataStream; +} + +template::value, int> = 0> +inline QDataStream& operator>>( QDataStream& dataStream, T &structure) +{ + facelift::for_each_in_tuple(structure.asTuple(), FromQDataStream(dataStream)); + return dataStream; +} + +// not neccessary if Qt allows defining Enum as INT +template::value, int> = 0> +inline QDBusArgument& operator<<(QDBusArgument &argument, const T& source) +{ + argument << static_cast(source); + return argument; +} + +template::value, int> = 0> +inline const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) +{ + int tmp; + argument >> tmp; + source = static_cast(tmp); + return argument; +} + +template::value && !ToByteArrayOverDBus::value, int> = 0> +inline QDBusArgument &operator<<(QDBusArgument &argument, const T &structure) +{ + argument.beginStructure(); + facelift::for_each_in_tuple_const(structure.asTuple(), ToQDBusArgument(argument)); + argument.endStructure(); + return argument; +} + +template::value && ToByteArrayOverDBus::value, int> = 0> +inline QDBusArgument &operator<<(QDBusArgument &argument, const T &structure) +{ + argument.beginStructure(); + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::WriteOnly); + dataStream << structure; + argument << byteArray; + argument.endStructure(); + return argument; +} + +template::value && !ToByteArrayOverDBus::value, int> = 0> +inline const QDBusArgument &operator>>(const QDBusArgument &argument, T &structure) +{ + argument.beginStructure(); + facelift::for_each_in_tuple(structure.asTuple(), FromQDBusArgument(argument)); + argument.endStructure(); + return argument; +} + +template::value && ToByteArrayOverDBus::value, int> = 0> +inline const QDBusArgument &operator>>(const QDBusArgument &argument, T &structure) +{ + argument.beginStructure(); + QByteArray byteArray; + QDataStream dataStream(&byteArray, QIODevice::ReadOnly); + argument >> byteArray; + dataStream >> structure; + argument.endStructure(); + return argument; +} diff --git a/src/ipc/dbus/IPCDBusServiceAdapter.h b/src/ipc/dbus/IPCDBusServiceAdapter.h index 4a65cb27..0447b6dd 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapter.h +++ b/src/ipc/dbus/IPCDBusServiceAdapter.h @@ -90,9 +90,63 @@ class IPCDBusServiceAdapter : public IPCDBusServiceAdapterBase Q_ASSERT(qobject_cast(serverObject) != nullptr); registerService(objectPath, static_cast(serverObject)); } + + template + const char* typeToSignature() const + { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return typeToSignatureSpecialized(HelperType()); + } protected: - QPointer m_service; + template::value && !std::is_enum::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value && std::is_enum::value, int> = 0> + const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + + template::value, int> = 0> + inline const char* typeToSignatureSpecialized(HelperType>) const + { + return QDBusMetaType::typeToSignature(qMetaTypeId>()); + } + QPointer m_service; }; } diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp index 616dffb5..6e65a310 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.cpp @@ -51,7 +51,6 @@ #include "DBusIPCProxy.h" #include "DBusObjectRegistry.h" -#include "DBusIPCCommon.h" #include "IPCDBusServiceAdapterBase.h" namespace facelift { @@ -60,8 +59,8 @@ namespace dbus { bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) { DBusIPCMessage requestMessage(dbusMsg); - DBusIPCMessage replyMessage = requestMessage.createReply(); + bool retVal = false; qCDebug(LogIpc) << "Handling incoming message: " << requestMessage.toString(); @@ -73,16 +72,43 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) qCDebug(LogIpc) << "Enabling IPCDBusServiceAdapter for" << this->service(); connectSignals(); } - if (dbusMsg.member() == DBusIPCCommon::GET_ALL_PROPERTIES) { - marshalPropertyValues(dbusMsg.arguments(), replyMessage); - send(replyMessage); + if (dbusMsg.member() == DBusIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME) { + QListIterator argumentsIterator(dbusMsg.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QVariantMap ret = marshalProperties(); + QMap convertedToDBusVariant; + for (const QString& key: ret.keys()) { + convertedToDBusVariant[key] = QDBusVariant(ret[key]); + } + replyMessage << QVariant::fromValue(convertedToDBusVariant); + send(replyMessage); + retVal = true; + } } - else if (dbusMsg.member() == DBusIPCCommon::GET_PROPERTY) { - marshalProperty(dbusMsg.arguments(), replyMessage); - send(replyMessage); + else if (dbusMsg.member() == DBusIPCCommon::GET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(dbusMsg.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + auto propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + QVariant value = marshalProperty(propertyName); + if (value.isValid()) { + replyMessage << QVariant::fromValue(QDBusVariant(value)); + send(replyMessage); + retVal = true; + } + } } - else if (dbusMsg.member() == DBusIPCCommon::SET_PROPERTY) { - setProperty(dbusMsg.arguments()); + else if (dbusMsg.member() == DBusIPCCommon::SET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QString propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (argumentsIterator.hasNext()) { + setProperty(propertyName, qdbus_cast(argumentsIterator.next()).variant()); + retVal = true; + } + } send(replyMessage); } } else if (dbusMsg.interface() == interfaceName()) { @@ -97,13 +123,13 @@ bool IPCDBusServiceAdapterBase::handleMessage(const QDBusMessage &dbusMsg) if (sendReply) { send(replyMessage); } - return true; + retVal = true; } else { qCWarning(LogIpc) << "DBus request received for object which has been destroyed" << this; } } - return false; + return retVal; } IPCDBusServiceAdapterBase::IPCDBusServiceAdapterBase(DBusManagerInterface& dbusManager, QObject *parent) : diff --git a/src/ipc/dbus/IPCDBusServiceAdapterBase.h b/src/ipc/dbus/IPCDBusServiceAdapterBase.h index 740874e9..789de167 100644 --- a/src/ipc/dbus/IPCDBusServiceAdapterBase.h +++ b/src/ipc/dbus/IPCDBusServiceAdapterBase.h @@ -37,12 +37,14 @@ #endif #include +#include #include "IPCServiceAdapterBase.h" #include "DBusIPCMessage.h" #include "DBusIPCCommon.h" #include "ipc-common.h" #include "FaceliftUtils.h" #include "DBusManagerInterface.h" +#include "FaceliftDBusMarshaller.h" namespace facelift { @@ -88,7 +90,7 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda bool handleMessage(const QDBusMessage &dbusMsg); - inline void sendPropertiesChanged(const QMap& changedProperties); + inline void sendPropertiesChanged(const QVariantMap& changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -102,11 +104,11 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda virtual IPCHandlingResult handleMethodCallMessage(DBusIPCMessage &requestMessage, DBusIPCMessage &replyMessage) = 0; - virtual void marshalPropertyValues(const QList& arguments, DBusIPCMessage &msg) = 0; + virtual QVariantMap marshalProperties() = 0; - virtual void marshalProperty(const QList& arguments, DBusIPCMessage &msg) = 0; + virtual QVariant marshalProperty(const QString& propertyName) = 0; - virtual void setProperty(const QList& arguments) = 0; + virtual void setProperty(const QString& propertyName, const QVariant& value) = 0; void registerService() override; @@ -125,23 +127,17 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); + T castFromQVariant(const QVariant& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castFromQVariantSpecialized(HelperType(), value); } template - T castFromDBusVariant(const QVariant& value) { - return castFromDBusVariantSpecialized(HelperType(), value); - } - - template - QVariant castToVariant(const T& value) { - return castToVariantSpecialized(HelperType(), value); - } - - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); + QVariant castToQVariant(const T& value) { + static std::once_flag registerFlag; + std::call_once(registerFlag, [](){registerDBusType(HelperType());}); + return castToQVariantSpecialized(HelperType(), value); } protected: @@ -156,75 +152,88 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda DBusManagerInterface& m_dbusManager; private: - template struct HelperType { }; - template - T castFromVariantSpecialized(HelperType, const QVariant& value) { + template::value, int> = 0> + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qdbus_cast(value); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { return qdbus_cast(value); // workaround to use QList since its signature matches the QStringList } - template - T castFromDBusVariantSpecialized(HelperType, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); + template::value, int> = 0> + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return static_cast(qdbus_cast(value)); } - QList castFromDBusVariantSpecialized(HelperType>, const QVariant& value) { - return qvariant_cast(qdbus_cast(value).variant()); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList tmp = qdbus_cast>(value); + QList ret; + std::transform(tmp.begin(), tmp.end(), std::back_inserter(ret), [](const int entry){return static_cast(entry);}); + return ret; + } + + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + QMap tmp = qdbus_cast>(value); + for (const QString& key: tmp.keys()) { + ret[key] = static_cast(tmp[key]); + } + return ret; } template::value && !std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) { return QVariant::fromValue(value); } template::value && std::is_enum::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { + QVariant castToQVariantSpecialized(HelperType, const T& value) { return QVariant::fromValue(static_cast(value)); } - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType, const T& value) { - DBusObjectPath dbusObjectPath; + QVariant castToQVariantSpecialized(HelperType, const T& value) { + QString objectPath; if (value != nullptr) { - dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCDBusAdapterType>(value)->objectPath()); + objectPath = getOrCreateAdapter::type::IPCDBusAdapterType>(value)->objectPath(); } - return QVariant::fromValue(dbusObjectPath); + return QVariant::fromValue(objectPath); } - template - QVariant castToVariantSpecialized(HelperType>, const QList& value) { - QStringList /*QList*/ objectPathes; - for (T* service: value) { - objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + template::value, int> = 0> + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { + QStringList objectPathes; + for (T service: value) { + objectPathes.append(getOrCreateAdapter::type::IPCDBusAdapterType>(service)->objectPath()); } return QVariant::fromValue(objectPathes); } - template - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { - QMap objectPathesMap; + template::value, int> = 0> + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) { + QMap objectPathesMap; for (const QString& key: value.keys()) { - objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + objectPathesMap[key] = getOrCreateAdapter::type::IPCDBusAdapterType>(value[key])->objectPath(); } return QVariant::fromValue(objectPathesMap); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QList& value) { + QVariant castToQVariantSpecialized(HelperType>, const QList& value) { QList ret; std::transform(value.begin(), value.end(), std::back_inserter(ret), [](const T& entry){return static_cast(entry);}); return QVariant::fromValue(ret); } template::value, int> = 0> - QVariant castToVariantSpecialized(HelperType>, const QMap& value) { + QVariant castToQVariantSpecialized(HelperType>, const QMap& value) { QMap ret; for (const QString& key: value.keys()) { ret[key] = static_cast(value[key]); @@ -233,11 +242,15 @@ class FaceliftIPCLibDBus_EXPORT IPCDBusServiceAdapterBase : public IPCServiceAda } }; -inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties) +inline void IPCDBusServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties) { DBusIPCMessage reply(objectPath(), DBusIPCCommon::PROPERTIES_INTERFACE_NAME, DBusIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); - reply << QVariant::fromValue(changedProperties); + QMap convertedToDBusVariant; + for (const QString& key: changedProperties.keys()) { + convertedToDBusVariant[key] = QDBusVariant(changedProperties[key]); + } + reply << QVariant::fromValue(convertedToDBusVariant); this->send(reply); } @@ -247,7 +260,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg DBusIPCMessage signal(objectPath(), interfaceName(), signalName); using expander = int[]; (void)expander{0, - (void(signal << castToVariant(std::forward(args))), 0)... + (void(signal << castToQVariant(std::forward(args))), 0)... }; this->send(signal); } @@ -255,7 +268,7 @@ inline void IPCDBusServiceAdapterBase::sendSignal(const QString& signalName, Arg template inline void IPCDBusServiceAdapterBase::sendAsyncCallAnswer(DBusIPCMessage &replyMessage, const ReturnType returnValue) { - replyMessage << castToVariant(returnValue); + replyMessage << castToQVariant(returnValue); send(replyMessage); } diff --git a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h index bae9eca0..d172b171 100644 --- a/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h +++ b/src/ipc/ipc-common/IPCAdapterModelPropertyHandler.h @@ -30,7 +30,6 @@ #pragma once #include -#include #include "ipc-common.h" #if defined(FaceliftIPCCommonLib_LIBRARY) @@ -60,7 +59,7 @@ class IPCAdapterModelPropertyHandler for (int i = first ; i <= last ; i++) { changedItems.append(m_model->elementAt(i)); } - m_adapter.sendSignal("ModelUpdateEventDataChanged", modelPropertyName, first, changedItems); + m_adapter.sendSignal(IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME, modelPropertyName, first, changedItems); }); QObject::connect(m_model, &facelift::ModelBase::beginRemoveElements, &m_adapter, [this] (int first, int last) { m_removeFirst = first; @@ -69,7 +68,7 @@ class IPCAdapterModelPropertyHandler QObject::connect(m_model, &facelift::ModelBase::endRemoveElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_removeFirst != UNDEFINED); Q_ASSERT(m_removeLast != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventRemove", modelPropertyName, m_removeFirst, m_removeLast); + m_adapter.sendSignal(IPCCommon::MODEL_REMOVE_MESSAGE_NAME, modelPropertyName, m_removeFirst, m_removeLast); m_removeFirst = UNDEFINED; m_removeLast = UNDEFINED; }); @@ -82,7 +81,7 @@ class IPCAdapterModelPropertyHandler Q_ASSERT(m_moveSourceFirstIndex != UNDEFINED); Q_ASSERT(m_moveSourceLastIndex != UNDEFINED); Q_ASSERT(m_moveDestinationIndex != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventMove", modelPropertyName, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); + m_adapter.sendSignal(IPCCommon::MODEL_MOVE_MESSAGE_NAME, modelPropertyName, m_moveSourceFirstIndex, m_moveSourceLastIndex, m_moveDestinationIndex); m_moveSourceFirstIndex = UNDEFINED; m_moveSourceLastIndex = UNDEFINED; m_moveDestinationIndex = UNDEFINED; @@ -94,7 +93,7 @@ class IPCAdapterModelPropertyHandler QObject::connect(m_model, &facelift::ModelBase::endInsertElements, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_insertFirst != UNDEFINED); Q_ASSERT(m_insertLast != UNDEFINED); - m_adapter.sendSignal("ModelUpdateEventInsert", modelPropertyName, m_insertFirst, m_insertLast); + m_adapter.sendSignal(IPCCommon::MODEL_INSERT_MESSAGE_NAME, modelPropertyName, m_insertFirst, m_insertLast); m_insertFirst = UNDEFINED; m_insertLast = UNDEFINED; }); @@ -103,16 +102,13 @@ class IPCAdapterModelPropertyHandler }); QObject::connect(m_model, &facelift::ModelBase::endResetModel, &m_adapter, [this, modelPropertyName] () { Q_ASSERT(m_resettingModel); - m_adapter.sendSignal("ModelUpdateEventReset", modelPropertyName, m_model->size()); + m_adapter.sendSignal(IPCCommon::MODEL_RESET_MESSAGE_NAME, modelPropertyName, m_model->size()); m_resettingModel = false; }); } - void handleModelRequest(typename IPCAdapterType::InputIPCMessage &requestMessage, typename IPCAdapterType::OutputIPCMessage &replyMessage) + void handleModelRequest(int first, int last, typename IPCAdapterType::OutputIPCMessage &replyMessage) { - QListIterator argumentsIterator(requestMessage.arguments()); - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); QList list; // Make sure we do not request items which are out of range @@ -123,8 +119,8 @@ class IPCAdapterModelPropertyHandler list.append(m_model->elementAt(i)); } - replyMessage << QVariant::fromValue(first); - replyMessage << QVariant::fromValue(list); + replyMessage << m_adapter.template castToQVariant(first); + replyMessage << m_adapter.template castToQVariant(list); } private: diff --git a/src/ipc/ipc-common/IPCProxyModelProperty.h b/src/ipc/ipc-common/IPCProxyModelProperty.h index c0457ac1..34de15d8 100644 --- a/src/ipc/ipc-common/IPCProxyModelProperty.h +++ b/src/ipc/ipc-common/IPCProxyModelProperty.h @@ -30,9 +30,9 @@ #pragma once #include -#include #include "FaceliftUtils.h" #include "ModelProperty.h" +#include "ipc-common.h" #if defined(FaceliftIPCCommonLib_LIBRARY) # define FaceliftIPCCommonLib_EXPORT Q_DECL_EXPORT @@ -56,14 +56,14 @@ class IPCProxyModelProperty : public facelift::ModelProperty void handleSignal(const typename IPCProxyType::InputIPCMessage &msg) { QListIterator argumentsIterator(msg.arguments()); - const QString& modelPropertyName = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): QString()); + const QString& modelPropertyName = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): QString()); Q_ASSERT(!modelPropertyName.isEmpty()); - const QString& eventName = msg.member(); + const QString& messageName = msg.member(); - if (eventName == QStringLiteral("ModelUpdateEventDataChanged")) + if (messageName == IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); int last = first + list.size() - 1; for (int i = first; i <= last; ++i) { @@ -71,38 +71,38 @@ class IPCProxyModelProperty : public facelift::ModelProperty } emit this->dataChanged(first, last); } - else if (eventName == QStringLiteral("ModelUpdateEventInsert")) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + else if (messageName == IPCCommon::MODEL_INSERT_MESSAGE_NAME) { + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginInsertElements(first, last); clear(); // TODO: insert elements in cache without clear() emit this->endInsertElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventRemove")) + else if (messageName == IPCCommon::MODEL_REMOVE_MESSAGE_NAME) { - int first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int last = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int last = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginRemoveElements(first, last); m_cache.clear(); // TODO: remove elements from cache without clear() emit this->endRemoveElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventMove")) { - int sourceFirstIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int sourceLastIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - int destinationIndex = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + else if (messageName == IPCCommon::MODEL_MOVE_MESSAGE_NAME) { + int sourceFirstIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int sourceLastIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + int destinationIndex = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); emit this->beginMoveElements(sourceFirstIndex, sourceLastIndex, destinationIndex); m_cache.clear(); // TODO: move elements in cache without clear() emit this->endMoveElements(); } - else if (eventName == QStringLiteral("ModelUpdateEventReset")) { + else if (messageName == IPCCommon::MODEL_RESET_MESSAGE_NAME) { emit this->beginResetModel(); - int size = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); + int size = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); this->setSize(size); clear(); emit this->endResetModel(); } else { - qCWarning(LogIpc) << "Unhandled event for model property" << eventName; + qCCritical(LogIpc) << "Unhandled event for model property" << messageName; } } @@ -130,8 +130,8 @@ class IPCProxyModelProperty : public facelift::ModelProperty QList args = m_proxy.ipc()->sendMethodCallWithReturn(requestMemberID, first, last); QListIterator argumentsIterator(args); - first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - QList list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + QList list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); last = first + list.size() - 1; for (int i = first; i <= last; ++i) { @@ -182,8 +182,8 @@ class IPCProxyModelProperty : public facelift::ModelProperty m_proxy.ipc()->sendAsyncMethodCall(requestMemberID, facelift::AsyncAnswer>(&m_proxy, [this](QList arguments) { // qCDebug(LogIpc) << "Received model items " << first << "-" << last; QListIterator argumentsIterator(arguments); - auto first = (argumentsIterator.hasNext() ? qdbus_cast(argumentsIterator.next()): int()); - auto list = (argumentsIterator.hasNext() ? qdbus_cast>(argumentsIterator.next()): QList()); + auto first = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant(argumentsIterator.next()): int()); + auto list = (argumentsIterator.hasNext() ? m_proxy.template castFromQVariant>(argumentsIterator.next()): QList()); auto last = first + list.size() - 1; for (int i = first; i <= last; ++i) { auto &newItem = list[i - first]; diff --git a/src/ipc/ipc-common/IPCServiceAdapterBase.h b/src/ipc/ipc-common/IPCServiceAdapterBase.h index 436e0985..cd7c84c3 100644 --- a/src/ipc/ipc-common/IPCServiceAdapterBase.h +++ b/src/ipc/ipc-common/IPCServiceAdapterBase.h @@ -30,7 +30,6 @@ #pragma once #include -#include #include "FaceliftModel.h" @@ -42,8 +41,6 @@ namespace facelift { -typedef QString DBusObjectPath; // potentially could be QDBusObjectPath but no empty QDBusObjectPath is allowed - class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject { Q_OBJECT @@ -110,61 +107,7 @@ class FaceliftIPCCommonLib_EXPORT IPCServiceAdapterBase : public QObject return serviceAdapter; } - - template - const char* typeToSignature() const - { - return typeToSignatureSpecialized(HelperType()); - } private: - template struct HelperType { }; - template::value && !std::is_enum::value, int> = 0> - const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template::value && std::is_enum::value, int> = 0> - const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId()); - } - - template - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - - template::value, int> = 0> - inline const char* typeToSignatureSpecialized(HelperType>) const - { - return QDBusMetaType::typeToSignature(qMetaTypeId>()); - } - QList > m_subAdapters; QString m_objectPath; QString m_interfaceName; diff --git a/src/ipc/ipc-common/ipc-common.h b/src/ipc/ipc-common/ipc-common.h index 809fed4e..d77c8b29 100644 --- a/src/ipc/ipc-common/ipc-common.h +++ b/src/ipc/ipc-common/ipc-common.h @@ -52,5 +52,16 @@ enum class IPCHandlingResult { INVALID, // Message is invalid and could not be handled }; +struct FaceliftIPCCommonLib_EXPORT IPCCommon +{ + static constexpr const char *MODEL_DATA_CHANGED_MESSAGE_NAME = "ModelUpdateEventDataChanged"; + static constexpr const char *MODEL_INSERT_MESSAGE_NAME = "ModelUpdateEventInsert"; + static constexpr const char *MODEL_REMOVE_MESSAGE_NAME = "ModelUpdateEventRemove"; + static constexpr const char *MODEL_MOVE_MESSAGE_NAME = "ModelUpdateEventMove"; + static constexpr const char *MODEL_RESET_MESSAGE_NAME = "ModelUpdateEventReset"; +}; + + + } diff --git a/src/ipc/local/FaceliftIPCCommon.h b/src/ipc/local/FaceliftIPCCommon.h index 9c121c28..3d0b5d36 100644 --- a/src/ipc/local/FaceliftIPCCommon.h +++ b/src/ipc/local/FaceliftIPCCommon.h @@ -42,11 +42,12 @@ namespace local { struct FaceliftIPCLocalLib_EXPORT FaceliftIPCCommon { - static constexpr const char *GET_ALL_PROPERTIES = "GetAll"; - static constexpr const char *GET_PROPERTY = "Get"; - static constexpr const char *SET_PROPERTY = "Set"; - static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; - static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static constexpr const char *GET_ALL_PROPERTIES_MESSAGE_NAME = "GetAll"; + static constexpr const char *GET_PROPERTY_MESSAGE_NAME = "Get"; + static constexpr const char *SET_PROPERTY_MESSAGE_NAME = "Set"; + static constexpr const char *PROPERTIES_CHANGED_SIGNAL_NAME = "PropertiesChanged"; + static constexpr const char *PROPERTIES_INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + static constexpr const char *INTROSPECTABLE_INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; }; } diff --git a/src/ipc/local/LocalIPC-serialization.h b/src/ipc/local/LocalIPC-serialization.h index 3a3c7d28..848f3cde 100644 --- a/src/ipc/local/LocalIPC-serialization.h +++ b/src/ipc/local/LocalIPC-serialization.h @@ -36,7 +36,6 @@ # define FaceliftIPCLocalLib_EXPORT Q_DECL_IMPORT #endif -#include #include "LocalIPCMessage.h" #include "LocalIPCProxy.h" #include "LocalIPCServiceAdapter.h" @@ -72,7 +71,7 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac asyncCall(msg, this, [this, answer](LocalIPCMessage &msg) { ReturnType returnValue; if (msg.isReplyMessage()) { - returnValue = (!msg.arguments().isEmpty() ? qvariant_cast(msg.arguments()[0]): ReturnType()); + returnValue = (!msg.arguments().isEmpty() ? qvariant_cast(msg.arguments().first()): ReturnType()); answer(returnValue); } else { qCWarning(LogIpc) << "Error received" << msg.toString(); @@ -97,10 +96,10 @@ inline void LocalIPCProxyBinder::sendAsyncMethodCall(const char *methodName, fac template inline void LocalIPCProxyBinder::sendSetterCall(const QString& property, const PropertyType &value) { - LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::SET_PROPERTY); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::SET_PROPERTY_MESSAGE_NAME); msg << QVariant::fromValue(m_interfaceName); msg << QVariant::fromValue(property); - msg << QVariant::fromValue(QDBusVariant(QVariant::fromValue(value))); + msg << QVariant::fromValue(QVariant::fromValue(value)); if (isSynchronous()) { auto replyMessage = call(msg); if (replyMessage.isErrorMessage()) { diff --git a/src/ipc/local/LocalIPCProxy.h b/src/ipc/local/LocalIPCProxy.h index 9ecd9353..49057cb9 100644 --- a/src/ipc/local/LocalIPCProxy.h +++ b/src/ipc/local/LocalIPCProxy.h @@ -42,8 +42,6 @@ namespace facelift { -typedef QString DBusObjectPath; - namespace local { using namespace facelift; @@ -105,47 +103,38 @@ class LocalIPCProxy : public IPCProxyBase, protected LocalIPCProx } template - T castFromVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), value); - } - - template - T castFromDBusVariant(const QVariant& value) { - return castFromVariantSpecialized(HelperType(), qvariant_cast(value).variant()); + T castFromQVariant(const QVariant& value) { + return castFromQVariantSpecialized(HelperType(), value); } private: template struct HelperType { }; template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { + T castFromQVariantSpecialized(HelperType, const QVariant& value) { return qvariant_cast(value); } - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - return qvariant_cast(value); // workaround to use QList since its signature matches the QStringList - } - template::value, int> = 0> - T castFromVariantSpecialized(HelperType, const QVariant& value) { - return getOrCreateSubProxy::type::IPCLocalProxyType>(qvariant_cast(value)); + T castFromQVariantSpecialized(HelperType, const QVariant& value) { + return getOrCreateSubProxy::type::IPCLocalProxyType>(qvariant_cast(value)); } - template - QMap castFromVariantSpecialized(HelperType>, const QVariant& value) { - QMap ret; - auto objectPaths = qvariant_cast>(value); + template::value, int> = 0> + QMap castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QMap ret; + auto objectPaths = qvariant_cast>(value); for (const QString& key: objectPaths.keys()) { - ret[key] = getOrCreateSubProxy(objectPaths[key]); + ret[key] = getOrCreateSubProxy::type::IPCLocalProxyType>(objectPaths[key]); } return ret; } - template - QList castFromVariantSpecialized(HelperType>, const QVariant& value) { - QList ret; - auto objectPaths = qvariant_cast*/>(value); - for (const DBusObjectPath& objectPath: objectPaths) { - ret.append(getOrCreateSubProxy(objectPath)); + template::value, int> = 0> + QList castFromQVariantSpecialized(HelperType>, const QVariant& value) { + QList ret; + auto objectPaths = qvariant_cast(value); + for (const QString& objectPath: objectPaths) { + ret.append(getOrCreateSubProxy::type::IPCLocalProxyType>(objectPath)); } return ret; } diff --git a/src/ipc/local/LocalIPCProxyBase.h b/src/ipc/local/LocalIPCProxyBase.h index a0e0f426..d8476c6d 100644 --- a/src/ipc/local/LocalIPCProxyBase.h +++ b/src/ipc/local/LocalIPCProxyBase.h @@ -34,7 +34,6 @@ #include "IPCProxyBase.h" #include "LocalIPCRequestHandler.h" #include "LocalIPCProxyBinder.h" -#include #if defined(FaceliftIPCLocalLib_LIBRARY) # define FaceliftIPCLocalLib_EXPORT Q_DECL_EXPORT diff --git a/src/ipc/local/LocalIPCProxyBinder.cpp b/src/ipc/local/LocalIPCProxyBinder.cpp index 87e4db32..f593061e 100644 --- a/src/ipc/local/LocalIPCProxyBinder.cpp +++ b/src/ipc/local/LocalIPCProxyBinder.cpp @@ -37,7 +37,6 @@ #include "LocalIPCProxy.h" #include "LocalIPC-serialization.h" #include "LocalIPCRegistry.h" -#include "FaceliftIPCCommon.h" namespace facelift { @@ -127,7 +126,12 @@ void LocalIPCProxyBinder::onServerNotAvailableError(const QString& methodName) c void LocalIPCProxyBinder::onPropertiesChanged(LocalIPCMessage &msg) { - m_serviceObject->unmarshalPropertiesChanged(msg); + QListIterator argumentsIterator(msg.arguments()); + QString interfaceName = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QString()); + if (interfaceName == m_interfaceName) { + QVariantMap changedProperties = (argumentsIterator.hasNext() ? qvariant_cast(argumentsIterator.next()): QVariantMap()); + m_serviceObject->unmarshalPropertiesChanged(changedProperties); + } } LocalIPCMessage LocalIPCProxyBinder::call(LocalIPCMessage &message) const @@ -151,12 +155,13 @@ void LocalIPCProxyBinder::asyncCall(LocalIPCMessage &requestMessage, QObject *co void LocalIPCProxyBinder::requestPropertyValues() { - LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::GET_ALL_PROPERTIES); + LocalIPCMessage msg(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME); msg << interfaceName(); auto replyHandler = [this](LocalIPCMessage &replyMessage) { if (replyMessage.isReplyMessage()) { - m_serviceObject->unmarshalPropertyValues(replyMessage); + QVariantMap values = (!replyMessage.arguments().isEmpty() ? qvariant_cast(replyMessage.arguments().first()): QVariantMap()); + m_serviceObject->unmarshalProperties(values); m_serviceObject->setServiceRegistered(true); emit serviceAvailableChanged(); } else { diff --git a/src/ipc/local/LocalIPCRequestHandler.h b/src/ipc/local/LocalIPCRequestHandler.h index 3bed1008..0f336439 100644 --- a/src/ipc/local/LocalIPCRequestHandler.h +++ b/src/ipc/local/LocalIPCRequestHandler.h @@ -60,8 +60,8 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCRequestHandler { public: - virtual void unmarshalPropertyValues(LocalIPCMessage &msg) = 0; - virtual void unmarshalPropertiesChanged(LocalIPCMessage &msg) = 0; + virtual void unmarshalProperties(const QVariantMap& changedProperties) = 0; + virtual void unmarshalPropertiesChanged(const QVariantMap& changedProperties) = 0; virtual void handleSignals(LocalIPCMessage& msg) = 0; virtual const QList& getSignals() const = 0; virtual void setServiceRegistered(bool isRegistered) = 0; diff --git a/src/ipc/local/LocalIPCServiceAdapter.h b/src/ipc/local/LocalIPCServiceAdapter.h index 004439d8..742d3728 100644 --- a/src/ipc/local/LocalIPCServiceAdapter.h +++ b/src/ipc/local/LocalIPCServiceAdapter.h @@ -91,6 +91,12 @@ class LocalIPCServiceAdapter : public LocalIPCServiceAdapterBase registerService(objectPath, static_cast(serverObject)); // TODO: get rid of that cast } + template + const char* typeToSignature() const + { + return ""; + } + protected: QPointer m_service; }; diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.cpp b/src/ipc/local/LocalIPCServiceAdapterBase.cpp index 3b5987a8..1157e8c8 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.cpp +++ b/src/ipc/local/LocalIPCServiceAdapterBase.cpp @@ -50,14 +50,27 @@ IPCHandlingResult LocalIPCServiceAdapterBase::handleMessage(LocalIPCMessage &req bool sendReply = true; if (requestMessage.interface() == FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME) { - if (requestMessage.member() == FaceliftIPCCommon::GET_ALL_PROPERTIES) { - marshalPropertyValues(requestMessage.arguments(), replyMessage); + if (requestMessage.member() == FaceliftIPCCommon::GET_ALL_PROPERTIES_MESSAGE_NAME) { + replyMessage << QVariant::fromValue(marshalProperties()); } - else if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTY) { - marshalProperty(requestMessage.arguments(), replyMessage); + else if (requestMessage.member() == FaceliftIPCCommon::GET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + // no need to check interface name in local variant + auto propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + QVariant value = marshalProperty(propertyName); + replyMessage << value; + send(replyMessage); } - else if (requestMessage.member() == FaceliftIPCCommon::SET_PROPERTY) { - setProperty(requestMessage.arguments()); + else if (requestMessage.member() == FaceliftIPCCommon::SET_PROPERTY_MESSAGE_NAME) { + QListIterator argumentsIterator(requestMessage.arguments()); + auto msgInterfaceName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (msgInterfaceName == interfaceName()) { + QString propertyName = (argumentsIterator.hasNext() ? castFromQVariant(argumentsIterator.next()): QString()); + if (argumentsIterator.hasNext()) { + setProperty(propertyName, argumentsIterator.next()); + } + } } } else { diff --git a/src/ipc/local/LocalIPCServiceAdapterBase.h b/src/ipc/local/LocalIPCServiceAdapterBase.h index 0d9f7e43..9f09527c 100644 --- a/src/ipc/local/LocalIPCServiceAdapterBase.h +++ b/src/ipc/local/LocalIPCServiceAdapterBase.h @@ -30,7 +30,6 @@ #pragma once -#include #include "LocalIPCMessage.h" #include "IPCServiceAdapterBase.h" #include "FaceliftIPCCommon.h" @@ -63,7 +62,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA IPCHandlingResult handleMessage(LocalIPCMessage &message); - inline void sendPropertiesChanged(const QMap &changedProperties); + inline void sendPropertiesChanged(const QVariantMap &changedProperties); template void sendSignal(const QString& signalName, Args && ... args); @@ -75,11 +74,11 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA virtual IPCHandlingResult handleMethodCallMessage(LocalIPCMessage &requestMessage, LocalIPCMessage &replyMessage) = 0; - virtual void marshalPropertyValues(const QList& arguments, LocalIPCMessage &msg) = 0; + virtual QVariantMap marshalProperties() = 0; - virtual void marshalProperty(const QList& arguments, LocalIPCMessage &msg) = 0; + virtual QVariant marshalProperty(const QString& propertyName) = 0; - virtual void setProperty(const QList& arguments) = 0; + virtual void setProperty(const QString& propertyName, const QVariant& value) = 0; void registerService() override; @@ -104,61 +103,42 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA } template - T castFromVariant(const QVariant& value) { + T castFromQVariant(const QVariant& value) { return qvariant_cast(value); } - template - T castFromDBusVariant(const QVariant& value) { - return qvariant_cast(qvariant_cast(value).variant()); - } - - template::value && !std::is_enum::value, int> = 0> - QVariant castToVariant(const T& value) { + template::value, int> = 0> + QVariant castToQVariant(const T& value) { return QVariant::fromValue(value); } - QVariant castToVariant(const QList& value) { - return QVariant::fromValue(QStringList(value)); // workaround to use QList since its signature matches the QStringList - } - - template::value && std::is_enum::value, int> = 0> - QVariant castToVariant(const T& value) { - return QVariant::fromValue(static_cast(value)); - } - template::value, int> = 0> - QVariant castToVariant(const T& value) { - DBusObjectPath dbusObjectPath; + QVariant castToQVariant(const T& value) { + QString objectPath; if (value != nullptr) { - dbusObjectPath = DBusObjectPath (getOrCreateAdapter::type::IPCLocalAdapterType>(value)->objectPath()); + objectPath = getOrCreateAdapter::type::IPCLocalAdapterType>(value)->objectPath(); } - return QVariant::fromValue(dbusObjectPath); + return QVariant::fromValue(objectPath); } - template - QVariant castToVariant(const QList& value) { - QStringList /*QList*/ objectPathes; - for (T* service: value) { - objectPathes.append(DBusObjectPath (getOrCreateAdapter(service)->objectPath())); + template::value, int> = 0> + QVariant castToQVariant(const QList& value) { + QStringList objectPathes; + for (T service: value) { + objectPathes.append(getOrCreateAdapter::type::IPCLocalAdapterType>(service)->objectPath()); } return QVariant::fromValue(objectPathes); } - template - QVariant castToVariant(const QMap& value) { - QMap objectPathesMap; + template::value, int> = 0> + QVariant castToQVariant(const QMap& value) { + QMap objectPathesMap; for (const QString& key: value.keys()) { - objectPathesMap[key] = DBusObjectPath(getOrCreateAdapter(value[key])->objectPath()); + objectPathesMap[key] = getOrCreateAdapter::type::IPCLocalAdapterType>(value[key])->objectPath(); } return QVariant::fromValue(objectPathesMap); } - template - QDBusVariant castToDBusVariant(const T& value) { - return QDBusVariant(castToVariant(value)); - } - protected: QString m_introspectionData; @@ -169,7 +149,7 @@ class FaceliftIPCLocalLib_EXPORT LocalIPCServiceAdapterBase : public IPCServiceA bool m_alreadyInitialized = false; }; -inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QMap &changedProperties ) +inline void LocalIPCServiceAdapterBase::sendPropertiesChanged(const QVariantMap &changedProperties ) { LocalIPCMessage reply(FaceliftIPCCommon::PROPERTIES_INTERFACE_NAME, FaceliftIPCCommon::PROPERTIES_CHANGED_SIGNAL_NAME); reply << interfaceName(); diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index 65325977..83131aeb 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -1,10 +1,4 @@ -set(QtDBusDependency "") -if(FACELIFT_DBUS_IPC_ENABLED) -find_package(Qt5DBus REQUIRED) -set(QtDBusDependency "Qt5::DBus") -endif() - facelift_add_library(FaceliftModelLib SOURCES StructureBase.cpp @@ -87,7 +81,6 @@ facelift_add_library(FaceliftModelLib LINK_LIBRARIES Qt5::Qml Qt5::Quick - ${QtDBusDependency} FaceliftCommonLib MONOLITHIC_SUPPORTED ) diff --git a/src/model/FaceliftEnum.h b/src/model/FaceliftEnum.h index c581ff20..df45946d 100644 --- a/src/model/FaceliftEnum.h +++ b/src/model/FaceliftEnum.h @@ -39,78 +39,6 @@ #include "FaceliftCommon.h" #include #include -#include -#ifdef DBUS_IPC_ENABLED -#include - -template -class QDBusEnumMarshal; - -template -class QDBusEnumMarshal::value>::type> -{ -public: - static QDBusArgument& marshal(QDBusArgument &argument, const T& source) - { - argument << static_cast(source); - return argument; - } - - static const QDBusArgument& unmarshal(const QDBusArgument &argument, T &source) - { - int tmp; - argument >> tmp; - source = static_cast(tmp); - return argument; - } -}; - -template -QDBusArgument& operator<<(QDBusArgument &argument, const T& source) -{ - return QDBusEnumMarshal::marshal(argument, source); -} - -template -const QDBusArgument& operator>>(const QDBusArgument &argument, T &source) -{ - return QDBusEnumMarshal::unmarshal(argument, source); -} -#endif - -template -class QDataStreamMarshal; - -template -class QDataStreamMarshal::value>::type> -{ -public: - static QDataStream& marshal(QDataStream &dataStream, const T& source) - { - dataStream << static_cast(source); - return dataStream; - } - - static const QDataStream& unmarshal(QDataStream &dataStream, T &source) - { - int value; - dataStream >> value; - source = static_cast(value); - return dataStream; - } -}; - -template -inline QDataStream& operator<<(QDataStream &dataStream, const T& source) -{ - return QDataStreamMarshal::marshal(dataStream, source); -} - -template -inline const QDataStream& operator>>(QDataStream &dataStream, T &source) -{ - return QDataStreamMarshal::unmarshal(dataStream, source); -} namespace facelift { diff --git a/tests/combined/check_combined.js b/tests/combined/check_combined.js index c93e9c9a..460dcb30 100644 --- a/tests/combined/check_combined.js +++ b/tests/combined/check_combined.js @@ -42,6 +42,8 @@ function defaults() { compare(api.structProperty2.cs.aString, ""); compare(api.structProperty2.e, 0); + compare(api.structWithExtDependency.otherEnums, []); + compare(api.intListProperty, []); compare(api.boolListProperty.length, 0); compare(api.enumListProperty.length, 0); @@ -66,6 +68,8 @@ function initialized() { compare(api.structProperty2.cs.aString, "ok"); compare(api.structProperty2.e, 1); + compare(api.structWithExtDependency.otherEnums[0], 1); + compare(api.intListProperty.length, 5); compare(api.intListProperty[2], 3); compare(api.boolListProperty.length, 3); @@ -85,6 +89,8 @@ function initialized() { compare(api.intMapProperty.one, 1); compare(api.intMapProperty.two, 2); + + compare(api.emptyString, ""); } function methods() { @@ -119,6 +125,8 @@ function methods() { os.ival = 101; compare(api.method7(os), OtherEnum.O3); + compare(api.listOfAnotherEnums()[0], OtherEnum.O2); + if (!api.qmlImplementationUsed) { api.interfaceProperty.doSomething(); compare(api.otherInterfaceProperty.otherMethod(OtherEnum.O3), "O3"); @@ -128,6 +136,9 @@ function methods() { asyncResult.answer = result; }); tryCompare(asyncResult, "answer", 42); + + api.interfaceMapProperty["key1"].doSomething(); + api.interfaceListProperty[0].doSomething(); } } diff --git a/tests/combined/impl/cpp/CombinedTestsCppImplementation.h b/tests/combined/impl/cpp/CombinedTestsCppImplementation.h index b14c4c9b..a62cd4c1 100644 --- a/tests/combined/impl/cpp/CombinedTestsCppImplementation.h +++ b/tests/combined/impl/cpp/CombinedTestsCppImplementation.h @@ -100,9 +100,17 @@ class CombinedInterfaceImplementation : public CombinedInterfaceImplementationBa s2.sete(CombiEnum::E2); m_structProperty2 = s2; + StructWithExtDependency structWithExtDep; + structWithExtDep.setotherEnums({OtherEnum::O2}); + structWithExtDep.setotherEnumMap({{"O1", OtherEnum::O1}, {"O2", OtherEnum::O2}}); + m_structWithExtDependency.setValue(structWithExtDep); + m_interfaceProperty.setValue(new CombinedInterface2Implementation(this, "#7")); m_otherInterfaceProperty.setValue(new OtherInterfaceImplementation(this)); + m_interfaceListProperty.addElement(new CombinedInterface2Implementation(this, "")); + m_interfaceMapProperty = facelift::Map({{"key1", new CombinedInterface2Implementation(this, "blabla")}}); + m_intListProperty = { 1, 2, 3, 5, 8 }; m_boolListProperty = { false, true, true }; m_enumListProperty = { CombiEnum::E2 }; @@ -239,4 +247,15 @@ class CombinedInterfaceImplementation : public CombinedInterfaceImplementationBa return OtherEnum::O3; return OtherEnum::O1; } + + HugeStruct hungryBeast(const tests::combined::HugeStruct& hugeStruct) override + { + return hugeStruct; + } + + QList listOfAnotherEnums() override + { + QList anotherEnums{tests::combined::another::AnotherEnum::O2}; + return anotherEnums; + } }; diff --git a/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml b/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml index a520400d..ce075e33 100644 --- a/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml +++ b/tests/combined/impl/qml/CombinedTestsQmlImplementation.qml @@ -100,6 +100,10 @@ CombinedInterfaceImplementationBase { return OtherEnum.O1; } + listOfAnotherEnums: function() { + return [OtherEnum.O2]; + } + initialize: function() { enumProperty = CombiEnum.E2; @@ -112,6 +116,9 @@ CombinedInterfaceImplementationBase { structProperty2.cs.aString = "ok"; structProperty2.e = CombiEnum.E2; + structWithExtDependency.otherEnums = [OtherEnum.O2]; + structWithExtDependency.otherEnumMap = {"O1": OtherEnum.O1, "O2": OtherEnum.O2}; + intListProperty = [ 1, 2, 3, 5, 8 ]; boolListProperty = [ false, true, true ]; enumListProperty = [ CombiEnum.E2 ]; diff --git a/tests/combined/interface/another.qface b/tests/combined/interface/another.qface new file mode 100644 index 00000000..aa9ef41f --- /dev/null +++ b/tests/combined/interface/another.qface @@ -0,0 +1,37 @@ +/********************************************************************** +** +** Copyright (C) 2018 Luxoft Sweden AB +** +** This file is part of the FaceLift project +** +** Permission is hereby granted, free of charge, to any person +** obtaining a copy of this software and associated documentation files +** (the "Software"), to deal in the Software without restriction, +** including without limitation the rights to use, copy, modify, merge, +** publish, distribute, sublicense, and/or sell copies of the Software, +** and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +** ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +** SPDX-License-Identifier: MIT +** +**********************************************************************/ + +module tests.combined.another 1.0 + +enum AnotherEnum { + O1, + O2, + O3 +} diff --git a/tests/combined/interface/combined.qface b/tests/combined/interface/combined.qface index 1ae09edc..af4a77fa 100644 --- a/tests/combined/interface/combined.qface +++ b/tests/combined/interface/combined.qface @@ -30,6 +30,7 @@ module tests.combined 1.0 import tests.combined.other 1.0 +import tests.combined.another 1.0 @ipc-async: true @ipc-sync: true @@ -45,6 +46,7 @@ interface CombinedInterface { int intProperty; CombiStruct structProperty; CombiStruct2 structProperty2; + StructWithExtDependency structWithExtDependency; readonly CombinedInterface2 interfaceProperty; readonly list interfaceListProperty; @@ -79,7 +81,15 @@ interface CombinedInterface { signal eventBoolAndCombiStruct(bool p, CombiStruct q); signal eventWithList(list p, bool q); signal eventWithMap(map p); - signal eventWithStructWithList(StructWithList p) + signal eventWithStructWithList(StructWithList p); + + list listOfAnotherEnums(); + + readonly string emptyString; // check QVariant delivery + + OversizedStruct oversizedStruct; + HugeStruct hugeStruct; + HugeStruct hungryBeast(HugeStruct hugeStruct); } @ipc-async: true @@ -98,6 +108,14 @@ struct CombiStruct2 { CombiEnum e; } +struct StructWithExtDependency { + string aString; + int anInt; + tests.combined.other.OtherStruct otherStruct; + list otherEnums; + map otherEnumMap; +} + struct StructWithList { list listOfInts; list listOfStructs; @@ -109,3 +127,38 @@ enum CombiEnum { E2, E3, } + +struct FirstLevel { +string someString; +int someInt; +bool someBool; +string someOtherString; +int someOtherInt; +bool someOtherBool; +} + +struct SecondLevel { +FirstLevel firstLevel; +FirstLevel anotherfirstLevel; +FirstLevel yetAnotherFirstLevel; +} + +struct ThirdLevel { +SecondLevel secondLevel; +SecondLevel anotherSecondLevel; +SecondLevel yetAnotherSecondLevel; +} + +struct HugeStruct { + ThirdLevel thirdLevel; + ThirdLevel anotherThirdLevel; + ThirdLevel yetAnotherThirdLevel; +} + +@toByteArrayOverDBus: true +struct OversizedStruct { +ThirdLevel thirdLevel; +ThirdLevel anotherThirdLevel; +ThirdLevel yetAnotherThirdLevel; +ThirdLevel theKiller; +} diff --git a/tests/combined/interface/other.qface b/tests/combined/interface/other.qface index 512461b2..2e78260d 100644 --- a/tests/combined/interface/other.qface +++ b/tests/combined/interface/other.qface @@ -29,6 +29,7 @@ **********************************************************************/ module tests.combined.other 1.0 +import tests.combined.another 1.0 @ipc-async: true @ipc-sync: true @@ -44,6 +45,8 @@ interface OtherInterface { struct OtherStruct { string str; int ival; + tests.combined.another.AnotherEnum anotherenum; + OtherEnum otherEnum; } enum OtherEnum { diff --git a/tests/models/interface/models.qface b/tests/models/interface/models.qface index c183c520..2ce5297a 100644 --- a/tests/models/interface/models.qface +++ b/tests/models/interface/models.qface @@ -76,7 +76,7 @@ struct HugeStruct { ThirdLevel yetAnotherThirdLevel; } -@serializeOverIPC: true +@toByteArrayOverDBus: true struct OversizedStruct { ThirdLevel thirdLevel; ThirdLevel anotherThirdLevel; diff --git a/tests/objectregistry/client.cpp b/tests/objectregistry/client.cpp index 30d94104..b224e4ac 100644 --- a/tests/objectregistry/client.cpp +++ b/tests/objectregistry/client.cpp @@ -30,8 +30,8 @@ #include "client.h" #include #include "DBusManager.h" -#include "DBusIPCMessage.h" #include "DBusIPCCommon.h" +#include "DBusIPCMessage.h" #include void tests::ipc::Tester::registerAnotherAdapter()