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