File indexing completed on 2024-04-28 12:45:43
0001 #!/usr/bin/python 0002 # 0003 # Copyright (C) 2012 Collabora Limited <http://www.collabora.co.uk> 0004 # Copyright (C) 2012 Nokia Corporation 0005 # 0006 # This library is free software; you can redistribute it and/or 0007 # modify it under the terms of the GNU Lesser General Public 0008 # License as published by the Free Software Foundation; either 0009 # version 2.1 of the License, or (at your option) any later version. 0010 # 0011 # This library is distributed in the hope that it will be useful, 0012 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 # Lesser General Public License for more details. 0015 # 0016 # You should have received a copy of the GNU Lesser General Public 0017 # License along with this library; if not, write to the Free Software 0018 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 0020 from sys import argv 0021 import xml.dom.minidom 0022 import codecs 0023 from getopt import gnu_getopt 0024 import functools 0025 0026 from libtpcodegen import NS_TP, get_descendant_text, get_by_path 0027 from libqtcodegen import binding_from_usage, extract_arg_or_member_info, format_docstring, gather_externals, gather_custom_lists, get_headerfile_cmd, get_qt_name, qt_identifier_escape, RefRegistry 0028 0029 # TODO generate docstrings 0030 0031 def to_lower_camel_case(s): 0032 if len(s) <= 1: 0033 return s.lower() 0034 0035 i = 0 0036 for c in s: 0037 if c == '_': 0038 break 0039 i += 1 0040 0041 ret = s 0042 if i == len(s): 0043 return s.lower() 0044 else: 0045 ret = s[0:i].lower() + s[i:] 0046 ret = ret.replace('_', '') 0047 return ret 0048 0049 class Generator(object): 0050 def __init__(self, opts): 0051 try: 0052 self.group = opts.get('--group', '') 0053 self.headerfile = opts['--headerfile'] 0054 self.implfile = opts['--implfile'] 0055 self.namespace = opts['--namespace'] 0056 self.typesnamespace = opts['--typesnamespace'] 0057 self.realinclude = opts.get('--realinclude', None) 0058 self.mocinclude = opts.get('--mocinclude', None) 0059 self.prettyinclude = opts.get('--prettyinclude') 0060 self.extraincludes = opts.get('--extraincludes', None) 0061 self.must_define = opts.get('--must-define', None) 0062 self.visibility = opts.get('--visibility', '') 0063 ifacedom = xml.dom.minidom.parse(opts['--ifacexml']) 0064 specdom = xml.dom.minidom.parse(opts['--specxml']) 0065 except KeyError as k: 0066 assert False, 'Missing required parameter %s' % k.args[0] 0067 0068 if not self.realinclude: 0069 self.realinclude = self.headerfile 0070 0071 self.hs = [] 0072 self.bs = [] 0073 self.ifacenodes = ifacedom.getElementsByTagName('node') 0074 self.spec, = get_by_path(specdom, "spec") 0075 self.custom_lists = gather_custom_lists(self.spec, self.typesnamespace) 0076 self.externals = gather_externals(self.spec) 0077 self.refs = RefRegistry(self.spec) 0078 0079 def __call__(self): 0080 # Output info header and includes 0081 self.h("""\ 0082 /* 0083 * This file contains D-Bus adaptor classes generated by qt-svc-gen.py. 0084 * 0085 * This file can be distributed under the same terms as the specification from 0086 * which it was generated. 0087 */ 0088 """) 0089 0090 if self.must_define: 0091 self.h('\n') 0092 self.h('#ifndef %s\n' % self.must_define) 0093 self.h('#error %s\n' % self.must_define) 0094 self.h('#endif\n') 0095 0096 self.h('\n') 0097 0098 if self.extraincludes: 0099 for include in self.extraincludes.split(','): 0100 self.h('#include %s\n' % include) 0101 0102 self.h("""\ 0103 #include <TelepathyQt/AbstractAdaptor> 0104 #include <TelepathyQt/Global> 0105 #include <TelepathyQt/Types> 0106 0107 #include <QObject> 0108 #include <QtDBus> 0109 0110 """) 0111 0112 if self.must_define: 0113 self.b("""#define %s\n""" % (self.must_define)) 0114 0115 self.b("""#include "%s" 0116 0117 """ % self.realinclude) 0118 0119 if self.mocinclude: 0120 self.b("""#include "%s" 0121 0122 """ % self.mocinclude) 0123 0124 self.b("""\ 0125 #include <TelepathyQt/Constants> 0126 #include <TelepathyQt/MethodInvocationContext> 0127 0128 """) 0129 0130 # Begin namespace 0131 for ns in self.namespace.split('::'): 0132 self.hb("""\ 0133 namespace %s 0134 { 0135 """ % ns) 0136 0137 # Output interface proxies 0138 def ifacenodecmp(x, y): 0139 xname, yname = [self.namespace + '::' + node.getAttribute('name').replace('/', '').replace('_', '') + 'Adaptor' for node in (x, y)] 0140 0141 return (xname > yname) - (xname < yname) 0142 0143 self.ifacenodes.sort(key=functools.cmp_to_key(ifacenodecmp)) 0144 for ifacenode in self.ifacenodes: 0145 self.do_ifacenode(ifacenode) 0146 0147 # End namespace 0148 self.hb(''.join(['\n}' for ns in self.namespace.split('::')])) 0149 0150 # Write output to files 0151 (codecs.getwriter('utf-8')(open(self.headerfile, 'wb'))).write(''.join(self.hs)) 0152 (codecs.getwriter('utf-8')(open(self.implfile, 'wb'))).write(''.join(self.bs)) 0153 0154 def do_ifacenode(self, ifacenode): 0155 # Extract info 0156 name = ifacenode.getAttribute('name').replace('/', '').replace('_', '') + 'Adaptor' 0157 iface, = get_by_path(ifacenode, 'interface') 0158 dbusname = iface.getAttribute('name') 0159 props = get_by_path(iface, 'property') 0160 methods = get_by_path(iface, 'method') 0161 signals = get_by_path(iface, 'signal') 0162 0163 # Begin class, constructors 0164 self.h(""" 0165 /** 0166 * \\class %(name)s 0167 %(headercmd)s\ 0168 %(groupcmd)s\ 0169 * 0170 * Adaptor class providing a 1:1 mapping of the D-Bus interface "%(dbusname)s". 0171 */ 0172 class %(visibility)s %(name)s : public Tp::AbstractAdaptor 0173 { 0174 Q_OBJECT 0175 Q_CLASSINFO("D-Bus Interface", "%(dbusname)s") 0176 Q_CLASSINFO("D-Bus Introspection", "" 0177 " <interface name=\\"%(dbusname)s\\">\\n" 0178 """ % {'name': name, 0179 'headercmd': get_headerfile_cmd(self.realinclude, self.prettyinclude), 0180 'groupcmd': self.group and (' * \\ingroup %s\n' % self.group), 0181 'dbusname': dbusname, 0182 'visibility': self.visibility, 0183 }) 0184 0185 self.do_introspection(props, methods, signals) 0186 0187 self.h("""\ 0188 " </interface>\\n" 0189 "") 0190 """) 0191 0192 self.do_qprops(props) 0193 0194 self.h(""" 0195 public: 0196 %(name)s(const QDBusConnection& dbusConnection, QObject* adaptee, QObject* parent); 0197 virtual ~%(name)s(); 0198 0199 """ % {'name': name}) 0200 0201 self.do_mic_typedefs(methods) 0202 0203 self.b(""" 0204 %(name)s::%(name)s(const QDBusConnection& bus, QObject* adaptee, QObject* parent) 0205 : Tp::AbstractAdaptor(bus, adaptee, parent) 0206 { 0207 """ % {'name': name}) 0208 0209 self.do_signals_connect(signals) 0210 0211 self.b("""\ 0212 } 0213 0214 %(name)s::~%(name)s() 0215 { 0216 } 0217 """ % {'name': name}) 0218 0219 # Properties 0220 has_props = False 0221 if props: 0222 self.h(""" 0223 public: // PROPERTIES 0224 """) 0225 0226 for prop in props: 0227 # Skip tp:properties 0228 if not prop.namespaceURI: 0229 self.do_prop(name, prop) 0230 has_props = True 0231 0232 # Methods 0233 if methods: 0234 self.h(""" 0235 public Q_SLOTS: // METHODS 0236 """) 0237 0238 for method in methods: 0239 self.do_method(name, method) 0240 0241 # Signals 0242 if signals: 0243 self.h(""" 0244 Q_SIGNALS: // SIGNALS 0245 """) 0246 0247 for signal in signals: 0248 self.do_signal(signal) 0249 0250 # Close class 0251 self.h("""\ 0252 }; 0253 """) 0254 0255 def do_introspection(self, props, methods, signals): 0256 self.do_prop_introspection(props) 0257 self.do_method_introspection(methods) 0258 self.do_signal_introspection(signals) 0259 0260 def do_prop_introspection(self, props): 0261 for prop in props: 0262 if prop.namespaceURI: 0263 continue 0264 0265 name = prop.getAttribute('name') 0266 access = prop.getAttribute('access') 0267 sig = prop.getAttribute('type') 0268 tptype = prop.getAttributeNS(NS_TP, 'type') 0269 binding = binding_from_usage(sig, tptype, self.custom_lists, (sig, tptype) in self.externals, self.typesnamespace) 0270 0271 if not binding.custom_type: 0272 self.h("""\ 0273 " <property access=\\"%(access)s\\" type=\\"%(sig)s\\" name=\\"%(name)s\\"/>\\n" 0274 """ % {'access': access, 0275 'sig': sig, 0276 'name': name, 0277 }) 0278 else: 0279 self.h("""\ 0280 " <property access=\\"%(access)s\\" type=\\"%(sig)s\\" name=\\"%(name)s\\">\\n" 0281 " <annotation value=\\"%(type)s\\" name=\\"com.trolltech.QtDBus.QtTypeName\\"/>\\n" 0282 " </property>\\n" 0283 """ % {'access': access, 0284 'sig': sig, 0285 'name': name, 0286 'type': binding.val, 0287 }) 0288 0289 def do_method_introspection(self, methods): 0290 for method in methods: 0291 name = method.getAttribute('name') 0292 args = get_by_path(method, 'arg') 0293 argnames, argdocstrings, argbindings = extract_arg_or_member_info(args, 0294 self.custom_lists, self.externals, self.typesnamespace, self.refs, ' * ') 0295 0296 if not argnames: 0297 self.h("""\ 0298 " <method name=\\"%(name)s\\"/>\\n" 0299 """ % {'name': name}) 0300 else: 0301 self.h("""\ 0302 " <method name=\\"%(name)s\\">\\n" 0303 """ % {'name': name}) 0304 0305 outindex = 0 0306 inindex = 0 0307 for i in range(len(argnames)): 0308 assert argnames[i] != None, 'Name missing from argument at index %d for signal %s' % (i, name) 0309 0310 argbinding = argbindings[i] 0311 argname = argnames[i] 0312 argsig = args[i].getAttribute('type') 0313 argdirection = args[i].getAttribute('direction') 0314 0315 # QtDBus requires annotating a{sv} 0316 if argsig == 'a{sv}': 0317 argbinding.custom_type = True 0318 0319 if not argbinding.custom_type: 0320 self.h("""\ 0321 " <arg direction=\\"%(direction)s\\" type=\\"%(sig)s\\" name=\\"%(name)s\\"/>\\n" 0322 """ % {'direction': argdirection, 0323 'sig': argsig, 0324 'name': argname}) 0325 else: 0326 self.h("""\ 0327 " <arg direction=\\"%(direction)s\\" type=\\"%(sig)s\\" name=\\"%(name)s\\">\\n" 0328 " <annotation value=\\"%(type)s\\" name=\\"com.trolltech.QtDBus.QtTypeName.%(index)s\\"/>\\n" 0329 " </arg>\\n" 0330 """ % {'direction': argdirection, 0331 'sig': argsig, 0332 'name': argname, 0333 'type': argbinding.val, 0334 'index': 'In' + str(inindex) if argdirection == 'in' else 'Out' + str(outindex), 0335 }) 0336 0337 if argdirection == 'out': 0338 outindex += 1 0339 else: 0340 inindex += 1 0341 0342 self.h("""\ 0343 " </method>\\n" 0344 """) 0345 0346 def do_signal_introspection(self, signals): 0347 for signal in signals: 0348 name = signal.getAttribute('name') 0349 args = get_by_path(signal, 'arg') 0350 argnames, argdocstrings, argbindings = extract_arg_or_member_info(args, 0351 self.custom_lists, self.externals, self.typesnamespace, self.refs, ' * ') 0352 0353 if not argnames: 0354 self.h("""\ 0355 " <signal name=\\"%(name)s\\"/>\\n" 0356 """ % {'name': name}) 0357 else: 0358 self.h("""\ 0359 " <signal name=\\"%(name)s\\">\\n" 0360 """ % {'name': name}) 0361 0362 for i in range(len(argnames)): 0363 assert argnames[i] != None, 'Name missing from argument at index %d for signal %s' % (i, name) 0364 0365 argbinding = argbindings[i] 0366 argname = argnames[i] 0367 argsig = args[i].getAttribute('type') 0368 0369 if not argbinding.custom_type: 0370 self.h("""\ 0371 " <arg type=\\"%(sig)s\\" name=\\"%(name)s\\"/>\\n" 0372 """ % {'sig': argsig, 0373 'name': argname}) 0374 else: 0375 self.h("""\ 0376 " <arg type=\\"%(sig)s\\" name=\\"%(name)s\\">\\n" 0377 " <annotation value=\\"%(type)s\\" name=\\"com.trolltech.QtDBus.QtTypeName.In%(index)d\\"/>\\n" 0378 " </arg>\\n" 0379 """ % {'sig': argsig, 0380 'name': argname, 0381 'type': argbinding.val, 0382 'index': i, 0383 }) 0384 0385 self.h("""\ 0386 " </signal>\\n" 0387 """) 0388 0389 def do_mic_typedefs(self, methods): 0390 for method in methods: 0391 name = method.getAttribute('name') 0392 args = get_by_path(method, 'arg') 0393 argnames, argdocstrings, argbindings = extract_arg_or_member_info(args, self.custom_lists, 0394 self.externals, self.typesnamespace, self.refs, ' * ') 0395 0396 outargs = [] 0397 for i in range(len(args)): 0398 if args[i].getAttribute('direction') == 'out': 0399 outargs.append(i) 0400 0401 if outargs: 0402 outargtypes = ', '.join([argbindings[i].val for i in outargs]) 0403 else: 0404 outargtypes = '' 0405 0406 self.h("""\ 0407 typedef Tp::MethodInvocationContextPtr< %(outargtypes)s > %(name)sContextPtr; 0408 """ % {'name': name, 0409 'outargtypes': outargtypes, 0410 }) 0411 0412 def do_qprops(self, props): 0413 for prop in props: 0414 # Skip tp:properties 0415 if not prop.namespaceURI: 0416 self.do_qprop(prop) 0417 0418 def do_qprop(self, prop): 0419 name = prop.getAttribute('name') 0420 access = prop.getAttribute('access') 0421 gettername = name 0422 settername = None 0423 if 'write' in access: 0424 settername = 'Set' + name 0425 0426 sig = prop.getAttribute('type') 0427 tptype = prop.getAttributeNS(NS_TP, 'type') 0428 binding = binding_from_usage(sig, tptype, self.custom_lists, (sig, tptype) in self.externals, self.typesnamespace) 0429 0430 self.h("""\ 0431 Q_PROPERTY(%(type)s %(name)s %(getter)s %(setter)s) 0432 """ % {'type': binding.val, 0433 'name': name, 0434 'getter': 'READ ' + gettername if ('read' in access) else '', 0435 'setter': 'WRITE ' + settername if ('write' in access) else '', 0436 }) 0437 0438 def do_prop(self, ifacename, prop): 0439 name = prop.getAttribute('name') 0440 adaptee_name = to_lower_camel_case(prop.getAttribute('tp:name-for-bindings')) 0441 access = prop.getAttribute('access') 0442 gettername = name 0443 settername = None 0444 if 'write' in access: 0445 settername = 'Set' + name 0446 docstring = format_docstring(prop, self.refs, ' * ').replace('*/', '*/') 0447 0448 sig = prop.getAttribute('type') 0449 tptype = prop.getAttributeNS(NS_TP, 'type') 0450 binding = binding_from_usage(sig, tptype, self.custom_lists, (sig, tptype) in self.externals, self.typesnamespace) 0451 0452 if 'read' in access: 0453 self.h("""\ 0454 /** 0455 * Return the value of the exported D-Bus object property \\c %(name)s of type \\c %(type)s. 0456 * 0457 * Adaptees should export this property as a Qt property named 0458 * '%(adaptee_name)s' with type %(type)s. 0459 * 0460 %(docstring)s\ 0461 * 0462 * \\return The value of exported property \\c %(name)s. 0463 */ 0464 %(type)s %(gettername)s() const; 0465 """ % {'name': name, 0466 'adaptee_name': adaptee_name, 0467 'docstring': docstring, 0468 'type': binding.val, 0469 'gettername': gettername, 0470 }) 0471 0472 self.b(""" 0473 %(type)s %(ifacename)s::%(gettername)s() const 0474 { 0475 return qvariant_cast< %(type)s >(adaptee()->property("%(adaptee_name)s")); 0476 } 0477 """ % {'type': binding.val, 0478 'ifacename': ifacename, 0479 'gettername': gettername, 0480 'adaptee_name': adaptee_name, 0481 }) 0482 0483 if 'write' in access: 0484 self.h("""\ 0485 /** 0486 * Set the value of the exported D-Bus object property \\c %(name)s of type \\c %(type)s. 0487 * 0488 * Adaptees should export this property as a writable Qt property named 0489 * '%(adaptee_name)s' with type %(type)s. 0490 * 0491 %(docstring)s\ 0492 */ 0493 void %(settername)s(const %(type)s &newValue); 0494 """ % {'name': name, 0495 'adaptee_name': adaptee_name, 0496 'docstring': docstring, 0497 'settername': settername, 0498 'type': binding.val, 0499 }) 0500 0501 self.b(""" 0502 void %(ifacename)s::%(settername)s(const %(type)s &newValue) 0503 { 0504 adaptee()->setProperty("%(adaptee_name)s", qVariantFromValue(newValue)); 0505 } 0506 """ % {'ifacename': ifacename, 0507 'settername': settername, 0508 'type': binding.val, 0509 'adaptee_name': adaptee_name, 0510 }) 0511 0512 def do_method(self, ifacename, method): 0513 name = method.getAttribute('name') 0514 adaptee_name = to_lower_camel_case(method.getAttribute('tp:name-for-bindings')) 0515 args = get_by_path(method, 'arg') 0516 argnames, argdocstrings, argbindings = extract_arg_or_member_info(args, self.custom_lists, 0517 self.externals, self.typesnamespace, self.refs, ' * ') 0518 docstring = format_docstring(method, self.refs, ' * ').replace('*/', '*/') 0519 0520 inargs = [] 0521 outargs = [] 0522 0523 for i in range(len(args)): 0524 if args[i].getAttribute('direction') == 'out': 0525 outargs.append(i) 0526 else: 0527 inargs.append(i) 0528 assert argnames[i] != None, 'No argument name for input argument at index %d for method %s' % (i, name) 0529 0530 if outargs: 0531 rettype = argbindings[outargs[0]].val 0532 else: 0533 rettype = 'void' 0534 0535 params = [argbindings[i].inarg + ' ' + argnames[i] for i in inargs] 0536 params.append('const QDBusMessage& dbusMessage') 0537 params += [argbindings[i].outarg + ' ' + argnames[i] for i in outargs[1:]] 0538 params = ', '.join(params) 0539 0540 if outargs: 0541 outargtypes = ', '.join([argbindings[i].val for i in outargs]) 0542 else: 0543 outargtypes = '' 0544 invokemethodargs = ', '.join(['Q_ARG(' + argbindings[i].val + ', ' + argnames[i] + ')' for i in inargs]) 0545 0546 inparams = [argbindings[i].val for i in inargs] 0547 inparams.append("%s::%s::%sContextPtr" % (self.namespace, ifacename, name)) 0548 normalized_adaptee_params = ','.join(inparams) 0549 0550 adaptee_params = [argbindings[i].inarg + ' ' + argnames[i] for i in inargs] 0551 adaptee_params.append('const %(namespace)s::%(ifacename)s::%(name)sContextPtr &context' % 0552 {'namespace': self.namespace, 0553 'ifacename': ifacename, 0554 'name': name}) 0555 adaptee_params = ', '.join(adaptee_params) 0556 0557 self.h("""\ 0558 /** 0559 * Begins a call to the exported D-Bus method \\c %(name)s on this object. 0560 * 0561 * Adaptees should export this method as a Qt slot with the following signature: 0562 * void %(adaptee_name)s(%(adaptee_params)s); 0563 * 0564 * Implementations should call MethodInvocationContext::setFinished (or setFinishedWithError 0565 * accordingly) on the received \\a context object once the method has finished processing. 0566 * 0567 %(docstring)s\ 0568 * 0569 """ % {'name': name, 0570 'adaptee_name': adaptee_name, 0571 'adaptee_params': adaptee_params, 0572 'rettype': rettype, 0573 'docstring': docstring 0574 }) 0575 0576 for i in inargs: 0577 if argdocstrings[i]: 0578 self.h("""\ 0579 * \\param %s 0580 %s\ 0581 """ % (argnames[i], argdocstrings[i])) 0582 0583 for i in outargs[1:]: 0584 if argdocstrings[i]: 0585 self.h("""\ 0586 * \\param %s Output parameter 0587 %s\ 0588 """ % (argnames[i], argdocstrings[i])) 0589 0590 if outargs: 0591 self.h("""\ 0592 * \\return 0593 %s\ 0594 """ % argdocstrings[outargs[0]]) 0595 0596 self.h("""\ 0597 */ 0598 %(rettype)s %(name)s(%(params)s); 0599 """ % {'rettype': rettype, 0600 'name': name, 0601 'params': params 0602 }) 0603 0604 self.b(""" 0605 %(rettype)s %(ifacename)s::%(name)s(%(params)s) 0606 { 0607 if (adaptee()->metaObject()->indexOfMethod("%(adaptee_name)s(%(normalized_adaptee_params)s)") < 0) { 0608 dbusConnection().send(dbusMessage.createErrorReply(TP_QT_ERROR_NOT_IMPLEMENTED, QLatin1String("Not implemented"))); 0609 """ % {'rettype': rettype, 0610 'ifacename': ifacename, 0611 'name': name, 0612 'adaptee_name': adaptee_name, 0613 'normalized_adaptee_params': normalized_adaptee_params, 0614 'params': params, 0615 }) 0616 0617 if rettype != 'void': 0618 self.b("""\ 0619 return %(rettype)s(); 0620 """ % {'rettype': rettype}) 0621 else: 0622 self.b("""\ 0623 return; 0624 """) 0625 0626 self.b("""\ 0627 } 0628 0629 %(name)sContextPtr ctx = %(name)sContextPtr( 0630 new Tp::MethodInvocationContext< %(outargtypes)s >(dbusConnection(), dbusMessage)); 0631 """ % {'name': name, 0632 'outargtypes': outargtypes, 0633 }) 0634 0635 if invokemethodargs: 0636 self.b("""\ 0637 QMetaObject::invokeMethod(adaptee(), "%(adaptee_name)s", 0638 %(invokemethodargs)s, 0639 Q_ARG(%(namespace)s::%(ifacename)s::%(name)sContextPtr, ctx)); 0640 """ % {'namespace': self.namespace, 0641 'ifacename': ifacename, 0642 'name': name, 0643 'adaptee_name': adaptee_name, 0644 'invokemethodargs': invokemethodargs, 0645 }) 0646 else: 0647 self.b("""\ 0648 QMetaObject::invokeMethod(adaptee(), "%(lname)s", 0649 Q_ARG(%(namespace)s::%(ifacename)s::%(name)sContextPtr, ctx)); 0650 """ % {'namespace': self.namespace, 0651 'ifacename': ifacename, 0652 'name': name, 0653 'lname': (name[0].lower() + name[1:]), 0654 }) 0655 0656 if rettype != 'void': 0657 self.b("""\ 0658 return %(rettype)s(); 0659 """ % {'rettype': rettype}) 0660 0661 self.b("}\n") 0662 0663 def do_signal(self, signal): 0664 name = signal.getAttribute('name') 0665 adaptee_name = to_lower_camel_case(signal.getAttribute('tp:name-for-bindings')) 0666 argnames, argdocstrings, argbindings = extract_arg_or_member_info(get_by_path(signal, 0667 'arg'), self.custom_lists, self.externals, self.typesnamespace, self.refs, ' * ') 0668 params = ', '.join(['%s %s' % (binding.inarg, param_name) for binding, param_name in zip(argbindings, argnames)]) 0669 0670 for i in range(len(argnames)): 0671 assert argnames[i] != None, 'Name missing from argument at index %d for signal %s' % (i, name) 0672 0673 self.h("""\ 0674 /** 0675 * Represents the exported D-Bus signal \\c %(name)s on this object. 0676 * 0677 * Adaptees should export this signal as a Qt signal with the following signature: 0678 * void %(adaptee_name)s(%(params)s); 0679 * 0680 * The adaptee signal will be automatically relayed as a D-Bus signal once emitted. 0681 * 0682 """ % {'name': name, 0683 'adaptee_name': adaptee_name, 0684 'params': params 0685 }) 0686 0687 for i in range(len(argnames)): 0688 assert argnames[i] != None, 'Name missing from argument at index %d for signal %s' % (i, name) 0689 if argdocstrings[i]: 0690 self.h("""\ 0691 * \\param %s 0692 %s\ 0693 """ % (argnames[i], argdocstrings[i])) 0694 0695 self.h("""\ 0696 */ 0697 void %(name)s(%(params)s); 0698 """ % {'name': name, 0699 'params': params 0700 }) 0701 0702 def do_signals_connect(self, signals): 0703 for signal in signals: 0704 name = signal.getAttribute('name') 0705 adaptee_name = to_lower_camel_case(signal.getAttribute('tp:name-for-bindings')) 0706 _, _, argbindings = extract_arg_or_member_info(get_by_path(signal, 'arg'), 0707 self.custom_lists, self.externals, self.typesnamespace, self.refs, ' * ') 0708 0709 self.b("""\ 0710 connect(adaptee, SIGNAL(%(adaptee_name)s(%(params)s)), SIGNAL(%(name)s(%(params)s))); 0711 """ % {'name': name, 0712 'adaptee_name': adaptee_name, 0713 'params': ', '.join([binding.inarg for binding in argbindings]) 0714 }) 0715 0716 def h(self, str): 0717 self.hs.append(str) 0718 0719 def b(self, str): 0720 self.bs.append(str) 0721 0722 def hb(self, str): 0723 self.h(str) 0724 self.b(str) 0725 0726 0727 if __name__ == '__main__': 0728 options, argv = gnu_getopt(argv[1:], '', 0729 ['group=', 0730 'headerfile=', 0731 'implfile=', 0732 'namespace=', 0733 'typesnamespace=', 0734 'realinclude=', 0735 'mocinclude=', 0736 'prettyinclude=', 0737 'extraincludes=', 0738 'must-define=', 0739 'visibility=', 0740 'ifacexml=', 0741 'specxml=']) 0742 0743 Generator(dict(options))()