def write_param_validation(self,
                            param,
                            param_name,
                            fail_statement,
                            out,
                            level=0):
     if not param.mandatory and (
             param.restricted or param.restrictedArray or
         (param.struct and any(
             map(lambda x: x.restricted, self.structs[param.fulltype])))):
         out.write("if (%s.presence) {\n" % param_name)
         param_copy = copy(param)
         param_copy.mandatory = True
         with CodeBlock(out) as out:
             self.write_param_validation(param_copy, param_name + ".val",
                                         fail_statement, out, level + 1)
         out.write("}\n")
     elif param.array:
         if param.minSize > 0:
             out.write("if ({0}.count() < {1}) {{ {2}; }}\n".format(
                 param_name, param.minSize, fail_statement))
         if param.maxSize != None:
             out.write("if ({0}.count() > {1}) {{ {2}; }}\n".format(
                 param_name, param.maxSize, fail_statement))
         if param.restricted:
             out.write(
                 'for ({0}::const_iterator it_{2} = {1}.begin(); it_{2} != {1}.end(); ++it_{2}) {{\n'
                 .format(self.qt_param_type(param), param_name, level))
             with CodeBlock(out) as out:
                 param_copy = copy(param)
                 param_copy.array = False
                 self.write_param_validation(param_copy,
                                             "(*it_{0})".format(level),
                                             fail_statement, out, level + 1)
             out.write("}\n")
     elif param.struct:
         for p in self.structs[param.fulltype]:
             self.write_param_validation(
                 p, "{0}.{1}".format(param_name, p.name), fail_statement,
                 out, level + 1)
     elif param.type == "Integer" or param.type == "Float":
         conditions = []
         if (param.minValue != None):
             conditions.append("(%s < %s)" % (param_name, param.minValue))
         if (param.maxValue != None):
             conditions.append("(%s > %s)" % (param_name, param.maxValue))
         if conditions:
             out.write('if (%s) { %s; }\n' %
                       (' || '.join(conditions), fail_statement))
     elif param.type == "String":
         conditions = []
         if (param.minLength > 0):
             conditions.append("(%s.size() < %s)" %
                               (param_name, param.minLength))
         if (param.maxLength > 0):
             conditions.append("(%s.size() > %s)" %
                               (param_name, param.maxLength))
         if conditions:
             out.write('if (%s) { %s; }\n' %
                       (' || '.join(conditions), fail_statement))
Beispiel #2
0
 def make_requests_for_source(self, out):
     for interface_el in self.el_tree.findall('interface'):
         request_responses = self.find_request_response_pairs_by_provider(interface_el, "sdl")
         for (request, response) in request_responses:
             request_name = request.get('name')
             iface_name = interface_el.get('name')
             request_full_name = iface_name + '_' + request_name
             out.write('bool RequestToSDL::' + request_full_name + '(')
             for param_el in request.findall('param'):                    
                 out.write('QVariant %s, ' % (param_el.get('name')))
             out.write('Q%sValue hmi_callback) {\n' % prefix_class_item)
             with CodeBlock(out) as output:
                 output.write('LOG4CXX_TRACE(logger_, "ENTER");\n')
                 output.write('QList<QVariant> args;\n')           
                 for param_el in request.findall('param'):
                     param = self.make_param_desc(param_el, iface_name)
                     output.write('%s %s;\n' % (impl.qt_param_type(param), param.name + "_tmp"))
                     output.write('if (VariantToValue(%s, %s)) {\n' % (param.name, param.name + '_tmp'))
                     with CodeBlock(output) as out:
                         self.write_param_validation(param, param.name + "_tmp",
                             "\nLOG4CXX_ERROR(logger_, \"%s in %s out of bounds\");\nreturn false" % (param.name, request_full_name),
                             out)
                         out.write('args << QVariant::fromValue(%s);\n' % (param.name + '_tmp'))
                     output.write('} else {\n')
                     with CodeBlock(output) as out:
                         out.write('LOG4CXX_ERROR(logger_, "%s in %s is NOT valid");\n' % (param.name, request_full_name))
                         out.write('return false;\n')
                     out.write('}\n')
                 output.write('new requests::' + request_full_name + '(hmi_callback, ' + interface_el.get('name') + ' , args, '
                               + '"' + request_name + '");\n')
                 output.write('LOG4CXX_TRACE(logger_, "EXIT");\n')
                 output.write('return true;\n')
             out.write('}\n\n')
 def make_header_file(self, out):
     out.write("class RequestToSDL : public QObject\n")
     out.write("{\n")
     out.write(" public:\n")
     with CodeBlock(out) as output:
         output.write("explicit RequestToSDL(QObject *parent = 0);\n")
         output.write("~RequestToSDL();\n")
     impl.make_requests_for_header(out)
     out.write(" private:\n")
     with CodeBlock(out) as output:
         for interface_el in self.el_tree.findall('interface'):
             output.write('QDBusInterface *' + interface_el.get('name') +
                          ';\n')
     out.write("};\n")
Beispiel #4
0
 def make_source_file(self, out):
     out.write('RequestToSDL::RequestToSDL(QObject *parent) {\n')
     with CodeBlock(out) as output:
         output.write('QDBusConnection bus = QDBusConnection::sessionBus();\n')
         for interface_el in self.el_tree.findall('interface'):
             iface_name = interface_el.get('name') 
             output.write(iface_name + ' = new QDBusInterface("com.ford.sdl.core", "/", "com.ford.sdl.core.' + iface_name + '", bus, this);\n')
     out.write('}\n\n')      
     out.write('RequestToSDL::~RequestToSDL() {\n')
     with CodeBlock(out) as output:
         for interface_el in self.el_tree.findall('interface'):
             iface_name = interface_el.get('name')
             output.write(iface_name + '->deleteLater();\n')
         output.write('this->deleteLater();\n')
     out.write('}\n\n')
     impl.make_requests_for_source(out)
Beispiel #5
0
class Impl(FordXmlParser):
    def make_dbus_type_declarations(self, out):
        for struct in self.structs.items():
            self.write_struct_declaration(struct, out)

    def make_dbus_metatype_declarations(self, out):
        for struct in self.structs.items():
            self.write_struct_metatype_declaration(struct, out)


    def write_struct_declaration(self, ((iface, name), params), out):
        struct_name = "{0}_{1}".format(iface, name)
        out.write("struct {0} {{\n".format(struct_name))
        with CodeBlock(out) as out:
            for param in params:
                out.write("{0} {1};\n".format(self.qt_param_type(param), param.name))
            out.write("{0}()\n".format(struct_name))
            initializersList = map(lambda x: "{0}({1})".format(x.name, defaultValue(x)), [p for p in params if p.type != "String" and not p.struct and not p.array])
            if initializersList:
                out.write(": " + ",\n    ".join(initializersList))

            out.write("{ }\n")

        out.write("};\n")
        out.write('QDBusArgument& operator << (QDBusArgument&, const ' + struct_name + "&);\n")
        out.write('const QDBusArgument& operator >> (const QDBusArgument&, ' + struct_name + "&);\n")
        out.write('void PutArgToMap(QVariantMap& map, const char* name, const ' + struct_name + "& v);\n")
        out.write('QVariant ValueToVariant(const ' + struct_name + "& v);\n")
        out.write('QVariant ValueToVariant(const QList<' + struct_name + " >& v);\n")
        out.write('bool GetArgFromMap(const QVariantMap& map, const char* name, ' + struct_name + "& v);\n")
        out.write('bool VariantToValue(const QVariant& variant, ' + struct_name + "& v);\n")
        out.write('bool VariantToValue(const QVariant& variant, QList<' + struct_name + " >& v);\n")
Beispiel #6
0
 def make_requests_for_header(self, out):
     for interface_el in self.el_tree.findall('interface'):
         request_responses = self.find_request_response_pairs_by_provider(interface_el, "sdl")            
         for (request, response) in request_responses:
             all_params = list()
             for param_el in request.findall('param'):
                 all_params.append(param_el)                    
             with CodeBlock(out) as output:
                 output.write("Q_INVOKABLE bool %s_%s(" % (interface_el.get('name'), request.get('name')))
             impl.args_for_function_definition(all_params, interface_el.get('name'), out)
             output.write(");\n")
 def make_requests_classes_header(self, out):
     for interface_el in self.el_tree.findall('interface'):
         request_responses = self.find_request_response_pairs_by_provider(
             interface_el, "sdl")
         for (request, response) in request_responses:
             request_full_name = interface_el.get(
                 'name') + '_' + request.get('name')
             out.write('class ' + request_full_name +
                       ': public HMIRequest {\n')
             with CodeBlock(out) as output:
                 output.write('Q_OBJECT\n')
             out.write(' public:\n')
             with CodeBlock(out) as output:
                 output.write(
                     request_full_name +
                     '(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name):\n'
                 )
                 output.write(
                     '  HMIRequest(hmi_callback, interface, args, name) {}\n'
                 )
             out.write(' private:\n')
             with CodeBlock(out) as output:
                 output.write('QJSValueList fillArgsList();\n};\n\n')
    def make_source_file(self, out):
        out.write("namespace requests {\n")
        for interface_el in self.el_tree.findall('interface'):
            for struct_el in interface_el.findall('struct'):
                out.write('template<>\n')
                out.write('QJSValue HMIRequest::CreateQJSValue(Common_' +
                          struct_el.get('name') + ' value){\n')
                with CodeBlock(out) as output:
                    output.write(
                        'QJSValue object = hmi_callback_.engine()->newObject();\n'
                    )
                for param_el in struct_el.findall('param'):
                    param_name = param_el.get('name')
                    if param_el.get('mandatory') == 'true':
                        with CodeBlock(out) as output:
                            output.write('object.setProperty("' + param_name +
                                         '", CreateQJSValue(value.' +
                                         param_name + '));\n')
                    elif param_el.get('mandatory') == 'false':
                        with CodeBlock(out) as output:
                            output.write('object.setProperty("' + param_name +
                                         '", value.' + param_name +
                                         '.presence ? CreateQJSValue(value.' +
                                         param_name + '.val) : QJSValue());\n')
                out.write('return object;\n')
                out.write('}\n\n')

        out.write(
            'HMIRequest::HMIRequest(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name) :\n'
        )
        out.write(
            '      hmi_callback_(hmi_callback), interface_(interface), args_(args) {\n'
        )
        with CodeBlock(out) as output:
            output.write(
                'QDBusPendingCall pcall = interface->asyncCallWithArgumentList(name, args);\n'
            )
            output.write('watcher_ = new QDBusPendingCallWatcher(pcall);\n')
            output.write(
                'QObject::connect(watcher_, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(invokeCallback()));\n}\n\n'
            )
        out.write('void HMIRequest::invokeCallback() {\n')
        with CodeBlock(out) as output:
            output.write('if (!hmi_callback_.isUndefined()) {\n')
            with CodeBlock(output) as output:
                output.write('QJSValueList qjsValueList;\n')
                output.write('qjsValueList = this->fillArgsList();\n')
                output.write('hmi_callback_.call(qjsValueList);\n')
            output.write('}\n')
            output.write('watcher_->deleteLater();\n')
            output.write('this->deleteLater();\n}\n\n')
        impl.make_requests_methods_source(out)
        out.write("}  // namespace requests\n")
 def make_requests_for_source(self, out):
     for interface_el in self.el_tree.findall('interface'):
         request_responses = self.find_request_response_pairs_by_provider(
             interface_el, "sdl")
         for (request, response) in request_responses:
             out.write('void RequestToSDL::' + request.get('name') +
                       '(QString name, ')
             for param_el in request.findall('param'):
                 out.write('QVariant ' + param_el.get('name') + ', ')
             out.write('QJSValue hmi_callback) {\n')
             with CodeBlock(out) as output:
                 output.write('QList<QVariant> args;\n')
                 for param_el in request.findall('param'):
                     output.write('args << ' + param_el.get('name') + ';\n')
                 output.write('new ' + interface_el.get('name') + '_' +
                              request.get('name') + '(' +
                              interface_el.get('name') +
                              ', name, args, hmi_callback);\n}\n')
    def make_requests_methods_source(self, out):
        for interface_el in self.el_tree.findall('interface'):
            request_responses = self.find_request_response_pairs_by_provider(
                interface_el, "sdl")
            for (request, response) in request_responses:
                iface_name = interface_el.get('name')
                request_full_name = iface_name + '_' + request.get('name')
                out.write('QJSValueList ' + request_full_name +
                          '::fillArgsList() {\n')
                out.write('  QDBusPendingReply< ')
                count = 0
                for param_el in response.findall('param'):
                    param = self.make_param_desc(param_el, iface_name)
                    out.write(self.qt_param_type(param))
                    count += 1
                    if count < len(response.findall('param')):
                        out.write(',')
                out.write(' > reply = *watcher_;\n')

                with CodeBlock(out) as out:
                    out.write('QJSValueList qjsValueList;\n\n')
                    out.write('QJSValue param;\n\n')
                    count = 0
                    for param_el in response.findall('param'):
                        if param_el.get('mandatory') == 'false':
                            out.write('if (reply.argumentAt<' + str(count) +
                                      '>().presence) {\n')
                            out.write(
                                '  param = CreateQJSValue(reply.argumentAt<' +
                                str(count) + '>().val);\n')
                            out.write('} else {\n')
                            out.write('  param = QJSValue();\n')
                            out.write('}\n')
                            out.write('qjsValueList.append(param);\n')
                        else:
                            out.write(
                                'param = CreateQJSValue(reply.argumentAt<' +
                                str(count) + '>());\n')
                            out.write('qjsValueList.append(param);\n')
                        count += 1
                    out.write('return qjsValueList;\n')
                out.write('}\n\n')
 def make_header_file(self, out):
     out.write("namespace requests {\n")
     out.write("class HMIRequest: public QObject {\n")
     with CodeBlock(out) as output:
         output.write('Q_OBJECT\n')
     out.write('public:\n')
     with CodeBlock(out) as output:
         output.write(
             'HMIRequest(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name );\n'
         )
     out.write('protected:\n')
     with CodeBlock(out) as output:
         output.write('virtual QJSValueList fillArgsList() = 0;\n')
         output.write('QDBusPendingCallWatcher *watcher_;\n')
         output.write('QJSValue hmi_callback_;\n\n')
         output.write('template<typename T>\n')
         output.write('QJSValue CreateQJSValue(T value) {\n')
         output.write('  return QJSValue(value);\n')
         output.write('}\n\n')
         output.write('template<typename T>\n')
         output.write('QJSValue CreateQJSValue(QList<T> value) {\n')
         with CodeBlock(output) as output:
             output.write(
                 'QJSValue array = hmi_callback_.engine()->newArray();\n')
             output.write('int i = 0;\n')
             output.write('foreach (T item, value) {\n')
             output.write('  QJSValue value = CreateQJSValue(item);\n')
             output.write('  array.setProperty(i, value);\n')
             output.write('  ++i;\n')
             output.write('}\n')
             output.write('return array;\n')
         output.write('}\n')
     out.write('private:\n')
     with CodeBlock(out) as output:
         output.write('QDBusInterface *interface_;\n')
         output.write('QList<QVariant> args_;\n')
     out.write('public slots:\n')
     with CodeBlock(out) as output:
         output.write('void invokeCallback();\n')
     out.write('};\n\n')
     output.write('template<>\n')
     output.write(
         'QJSValue HMIRequest::CreateQJSValue(QStringList value);\n')
     for (interface_name, struct_name) in self.structs:
         out.write('template<>\n')
         out.write('QJSValue HMIRequest::CreateQJSValue(Common_' +
                   struct_name + ' value);\n\n')
     impl.make_requests_classes_header(out)
     out.write("}  // namespace requests\n")
    def write_adaptor_definition(self, interface_el, notifications,
                                 request_responses, out):
        global prefix_class_item
        iface_name = interface_el.get('name')
        classname = iface_name + 'Adaptor'
        out.write(
            "{0}::{0}(QObject* parent) : QDBusAbstractAdaptor(parent) {{}}\n".
            format(classname))

        out.write("void {0}::SetApi(Q{1}Item* api) {{\n".format(
            classname, prefix_class_item))
        with CodeBlock(out) as out:
            out.write("api_ = api;\n")
            for n in notifications:
                signame = n.get('name')
                signame = signame[:1].lower() + signame[1:]
                slotname = n.get('name') + '_qml'
                sig_signature = self.make_qml_signal_signature(
                    n, iface_name, signame, True)
                slot_signature = self.make_qml_signal_signature(
                    n, iface_name, slotname, True)
                out.write("connect(api_, SIGNAL(" + sig_signature +
                          "), this, SLOT(" + slot_signature + "));\n")
            out.write(
                "LOG4CXX_TRACE(logger_, \"CONNECT SIGNALS: \" << __PRETTY_FUNCTION__ );\n"
            )
        out.write("}\n\n")

        for (request, response) in request_responses:
            in_params = [
                self.make_param_desc(x, iface_name)
                for x in request.findall('param')
            ]
            out_params = [
                self.make_param_desc(x, iface_name)
                for x in response.findall('param')
            ]

            out.write(
                "bool fill{0}{1}Reply(QDBusMessage& message, const QVariantMap& map) {{\n"
                .format(classname, request.get('name')))
            with CodeBlock(out) as out:
                out.write("int retCode_out = 0;\n")
                out.write("GetArgFromMap(map, \"__retCode\", retCode_out);\n")
                out.write(
                    "QVariant retCode_arg = QVariant::fromValue(retCode_out);\n"
                )
                out.write("message << retCode_arg;\n")
                out.write("QString userMessage_out;\n")
                out.write(
                    "GetArgFromMap(map, \"__message\", userMessage_out);\n")
                out.write(
                    "QVariant userMessage_arg = QVariant::fromValue(userMessage_out);\n"
                )
                out.write("message << userMessage_arg;\n")
                for p in out_params:
                    param_name = p.name
                    param_type = self.qt_param_type(p)
                    out.write("%s %s_out;\n" % (param_type, p.name))
                    out.write(
                        "if (!GetArgFromMap(map, \"{0}\", {0}_out)) {{ return false; }}\n"
                        .format(p.name))
                    self.write_param_validation(p, p.name + "_out",
                                                "return false", out)
                    out.write("QVariant {0}_arg;\n".format(p.name))
                    out.write("{0}_arg.setValue({0}_out);\n".format(p.name))
                    out.write("message << {0}_arg;\n".format(p.name))
                    out.write(
                        "LOG4CXX_DEBUG(logger_, \"Output arguments:\\n\" << QVariant(map));\n"
                    )
                out.write(
                    "LOG4CXX_TRACE(logger_, \"REPLY ASYNC: \" << __PRETTY_FUNCTION__ );\n"
                )
                out.write("return true;\n")
            out.write("}\n\n")

            out.write("{0} {{\n".format(
                self.make_method_signature(request, response, iface_name,
                                           True)))
            with CodeBlock(out) as out:
                out.write(
                    "LOG4CXX_TRACE(logger_, \"ENTER: \" << __PRETTY_FUNCTION__ );\n"
                )
                out.write("int ret = 0;\n")
                return_statement = "return ret;\n"
                out.write("QVariantMap in_arg;\n")
                out.write("QVariant out_arg_v;\n")
                for param in in_params:
                    self.write_param_validation(
                        param, param.name + "_in",
                        "RaiseDbusError(this, InvalidData); return ret", out)
                    out.write("PutArgToMap(in_arg, \"" + param.name + "\", " +
                              param.name + "_in);\n")
                out.write(
                    "LOG4CXX_DEBUG(logger_, \"Input arguments:\\n\" << in_arg);\n"
                )
                method_name = request.get('name')[:1].lower() + request.get(
                    'name')[1:]

                out.write("dbusController->message = &message;\n")
                out.write("dbusController->fill = &fill{0}{1}Reply;\n".format(
                    classname, request.get("name")))

                out.write(
                    """if (!QMetaObject::invokeMethod(api_, "{0}", Qt::{1}Connection, Q_RETURN_ARG(QVariant, out_arg_v), Q_ARG(QVariant, QVariant(in_arg)))) {{\n"""
                    .format(method_name, invoke_type_connection))
                with CodeBlock(out) as out:
                    out.write("RaiseDbusError(this, InvalidData);\n")
                    out.write("LOG4CXX_ERROR(logger_, \"Can't invoke method " +
                              method_name + "\");\n    ")
                    out.write("return ret;\n")
                out.write("}\n")

                out.write("dbusController->message = NULL;\n")
                out.write("dbusController->fill = NULL;\n")
                out.write("if (message.isDelayedReply()) {\n")
                with CodeBlock(out) as out:
                    out.write("return ret;\n")
                out.write("}\n")

                out.write("QVariantMap out_arg;\n")
                out.write("if (out_arg_v.type() == QVariant::Map) {\n")
                with CodeBlock(out) as out:
                    out.write("out_arg = out_arg_v.toMap();\n")
                out.write("};\n")

                out.write("int err;\n")
                out.write(
                    """if (GetArgFromMap(out_arg, "__errno", err)) { RaiseDbusError(this, err); return ret; }\n"""
                )

                out.write("int async_uid;\n")
                out.write(
                    "if (GetArgFromMap(out_arg, \"__async_uid\", async_uid)) {\n"
                )
                with CodeBlock(out) as out:
                    out.write("message.setDelayedReply(true);\n")
                    out.write(
                        "dbusController->addMessage(message, &fill%s%sReply, async_uid);\n"
                        % (classname, request.get('name')))
                    out.write(
                        "LOG4CXX_TRACE(logger_, \"EXIT ASYNC: \" << __PRETTY_FUNCTION__ );\n"
                    )
                    out.write("return ret;\n")
                out.write("}\n\n")

                for param in out_params:
                    out.write(
                        "if (!GetArgFromMap(out_arg, \"{0}\", {0}_out)) {{ RaiseDbusError(this, InvalidData); return ret; }}\n"
                        .format(param.name))
                    self.write_param_validation(
                        param, param.name + "_out",
                        "RaiseDbusError(this, InvalidData); return ret", out)

                out.write("GetArgFromMap(out_arg, \"__retCode\", ret);\n")
                out.write(
                    "GetArgFromMap(out_arg, \"__message\", userMessage_out);\n"
                )
                out.write(
                    "LOG4CXX_DEBUG(logger_, \"Output arguments:\\n\" << QVariant(out_arg));\n"
                )
                out.write(
                    "LOG4CXX_TRACE(logger_, \"EXIT: \" << __PRETTY_FUNCTION__ );\n"
                )
                out.write("return ret;\n")
            out.write("}\n\n")

        for n in notifications:
            slotname = n.get('name') + '_qml'
            slot_signature = self.make_qml_signal_signature(
                n, iface_name, slotname, False, True)
            out.write(slot_signature + " {\n")
            params = n.findall('param')
            out.write(
                "  LOG4CXX_TRACE(logger_, \"EMIT SIGNAL: \" << __PRETTY_FUNCTION__ );\n"
            )
            out.write("  LOG4CXX_DEBUG(logger_, \"Arguments:\\n{\"")
            for p in params[0:-1]:
                param = self.make_param_desc(p, iface_name)
                out.write(" << \" " + param.name + ":\" << " + param.name +
                          " << \",\"")
            for p in params[-1:]:  # last param without comma in end line
                p = params[-1]
                param = self.make_param_desc(p, iface_name)
                out.write(" << \" " + param.name + ":\" << " + param.name)
            out.write(" << \" }\");\n")
            for p in params:
                param = self.make_param_desc(p, iface_name)
                param_type = self.qt_param_type(param)
                param_name = 'p_' + param.name
                if param.mandatory:
                    if param.array or (param.type not in [
                            'Integer', 'String', 'Float', 'Boolean'
                    ] and not param.enum):
                        out.write('  ' + param_type + ' ' + param_name + ";\n")
                        out.write('  if (!VariantToValue(' + param.name +
                                  ', ' + param_name + ")) {\n")
                        out.write(
                            "    LOG4CXX_ERROR(logger_, \"Can't convert variant to value\");\n"
                        )
                        out.write("  return;}\n")
                else:
                    out.write('  ' + param_type + ' ' + param_name + ";\n")
                    out.write('  ' + param_name + '.presence = !' +
                              param.name + ".isNull();\n")
                    out.write('  if (' + param_name + ".presence) {\n")
                    out.write('    if (!VariantToValue(' + param.name + ', ' +
                              param_name + ".val)) {\n")
                    out.write(
                        "      LOG4CXX_ERROR(logger_, \"Can't convert variant to value\");\n"
                    )
                    out.write("      return;\n    }\n")
                    out.write("  }\n")
            out.write('  emit ' + n.get('name') + '(')
            for i in range(len(params)):
                param = self.make_param_desc(params[i], iface_name)
                basic_type = (param.type in [
                    'Integer', 'String', 'Float', 'Boolean'
                ]) or param.enum
                if param.array or (not param.mandatory) or (not basic_type):
                    param_name = 'p_' + param.name
                else:
                    param_name = param.name
                out.write(param_name)
                if i != len(params) - 1: out.write(', ')
            out.write(");\n")
            out.write("}\n\n")
        out.write('Q_DECLARE_METATYPE(OptionalArgument<' + struct_name +
                  ">)\n")
        out.write('Q_DECLARE_METATYPE(QList<' + struct_name + ">)\n")
        out.write('Q_DECLARE_METATYPE(OptionalArgument<QList<' + struct_name +
                  "> >)\n\n")

    def make_dbus_type_definitions(self, out):
        for struct in self.structs.items():
            self.write_struct_definition(struct, out)

    def write_struct_definition(self, ((iface, name), params), out):
        struct_name = iface + '_' + name

        out.write('QDBusArgument& operator << (QDBusArgument& arg, const ' +
                  struct_name + "& v) {\n")
        with CodeBlock(out) as out:
            out.write("arg.beginStructure();\n")
            for param in params:
                out.write("arg << v.{0};\n".format(param.name))
            out.write("arg.endStructure();\n")
            out.write("return arg;\n")
        out.write("}\n\n")

        out.write(
            'const QDBusArgument& operator >> (const QDBusArgument& arg, ' +
            struct_name + "& v) {\n")
        with CodeBlock(out) as out:
            out.write("arg.beginStructure();\n")
            for param in params:
                out.write("arg >> v.{0};\n".format(param.name))
            out.write("arg.endStructure();\n")