|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtDBus module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qdbusmetaobject_p.h" |
|
43 |
|
44 #include <QtCore/qbytearray.h> |
|
45 #include <QtCore/qhash.h> |
|
46 #include <QtCore/qstring.h> |
|
47 #include <QtCore/qvarlengtharray.h> |
|
48 |
|
49 #include "qdbusutil_p.h" |
|
50 #include "qdbuserror.h" |
|
51 #include "qdbusmetatype.h" |
|
52 #include "qdbusargument.h" |
|
53 #include "qdbusintrospection_p.h" |
|
54 #include "qdbusabstractinterface_p.h" |
|
55 |
|
56 QT_BEGIN_NAMESPACE |
|
57 |
|
58 class QDBusMetaObjectGenerator |
|
59 { |
|
60 public: |
|
61 QDBusMetaObjectGenerator(const QString &interface, |
|
62 const QDBusIntrospection::Interface *parsedData); |
|
63 void write(QDBusMetaObject *obj); |
|
64 void writeWithoutXml(QDBusMetaObject *obj); |
|
65 |
|
66 private: |
|
67 struct Method { |
|
68 QByteArray parameters; |
|
69 QByteArray typeName; |
|
70 QByteArray tag; |
|
71 QByteArray name; |
|
72 QByteArray inputSignature; |
|
73 QByteArray outputSignature; |
|
74 QVarLengthArray<int, 4> inputTypes; |
|
75 QVarLengthArray<int, 4> outputTypes; |
|
76 int flags; |
|
77 }; |
|
78 |
|
79 struct Property { |
|
80 QByteArray typeName; |
|
81 QByteArray signature; |
|
82 int type; |
|
83 int flags; |
|
84 }; |
|
85 struct Type { |
|
86 int id; |
|
87 QByteArray name; |
|
88 }; |
|
89 |
|
90 enum PropertyFlags { |
|
91 Invalid = 0x00000000, |
|
92 Readable = 0x00000001, |
|
93 Writable = 0x00000002, |
|
94 Resettable = 0x00000004, |
|
95 EnumOrFlag = 0x00000008, |
|
96 StdCppSet = 0x00000100, |
|
97 // Override = 0x00000200, |
|
98 Designable = 0x00001000, |
|
99 ResolveDesignable = 0x00002000, |
|
100 Scriptable = 0x00004000, |
|
101 ResolveScriptable = 0x00008000, |
|
102 Stored = 0x00010000, |
|
103 ResolveStored = 0x00020000, |
|
104 Editable = 0x00040000, |
|
105 ResolveEditable = 0x00080000, |
|
106 User = 0x00100000, |
|
107 ResolveUser = 0x00200000 |
|
108 }; |
|
109 |
|
110 enum MethodFlags { |
|
111 AccessPrivate = 0x00, |
|
112 AccessProtected = 0x01, |
|
113 AccessPublic = 0x02, |
|
114 AccessMask = 0x03, //mask |
|
115 |
|
116 MethodMethod = 0x00, |
|
117 MethodSignal = 0x04, |
|
118 MethodSlot = 0x08, |
|
119 MethodTypeMask = 0x0c, |
|
120 |
|
121 MethodCompatibility = 0x10, |
|
122 MethodCloned = 0x20, |
|
123 MethodScriptable = 0x40 |
|
124 }; |
|
125 |
|
126 QMap<QByteArray, Method> methods; |
|
127 QMap<QByteArray, Property> properties; |
|
128 |
|
129 const QDBusIntrospection::Interface *data; |
|
130 QString interface; |
|
131 |
|
132 Type findType(const QByteArray &signature, |
|
133 const QDBusIntrospection::Annotations &annotations, |
|
134 const char *direction = "Out", int id = -1); |
|
135 |
|
136 void parseMethods(); |
|
137 void parseSignals(); |
|
138 void parseProperties(); |
|
139 }; |
|
140 |
|
141 static const int intsPerProperty = 2; |
|
142 static const int intsPerMethod = 5; |
|
143 |
|
144 // ### from kernel/qmetaobject.cpp (Qt 4.1.2): |
|
145 struct QDBusMetaObjectPrivate |
|
146 { |
|
147 int revision; |
|
148 int className; |
|
149 int classInfoCount, classInfoData; |
|
150 int methodCount, methodData; |
|
151 int propertyCount, propertyData; |
|
152 int enumeratorCount, enumeratorData; |
|
153 |
|
154 // this is specific for QDBusMetaObject: |
|
155 int propertyDBusData; |
|
156 int methodDBusData; |
|
157 }; |
|
158 |
|
159 QDBusMetaObjectGenerator::QDBusMetaObjectGenerator(const QString &interfaceName, |
|
160 const QDBusIntrospection::Interface *parsedData) |
|
161 : data(parsedData), interface(interfaceName) |
|
162 { |
|
163 if (data) { |
|
164 parseProperties(); |
|
165 parseSignals(); // call parseSignals first so that slots override signals |
|
166 parseMethods(); |
|
167 } |
|
168 } |
|
169 |
|
170 QDBusMetaObjectGenerator::Type |
|
171 QDBusMetaObjectGenerator::findType(const QByteArray &signature, |
|
172 const QDBusIntrospection::Annotations &annotations, |
|
173 const char *direction, int id) |
|
174 { |
|
175 Type result; |
|
176 result.id = QVariant::Invalid; |
|
177 |
|
178 int type = QDBusMetaType::signatureToType(signature); |
|
179 if (type == QVariant::Invalid) { |
|
180 // it's not a type normally handled by our meta type system |
|
181 // it must contain an annotation |
|
182 QString annotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); |
|
183 if (id >= 0) |
|
184 annotationName += QString::fromLatin1(".%1%2") |
|
185 .arg(QLatin1String(direction)) |
|
186 .arg(id); |
|
187 |
|
188 // extract from annotations: |
|
189 QByteArray typeName = annotations.value(annotationName).toLatin1(); |
|
190 |
|
191 // verify that it's a valid one |
|
192 if (typeName.isEmpty()) |
|
193 return result; // invalid |
|
194 |
|
195 type = QVariant::nameToType(typeName); |
|
196 if (type == QVariant::UserType) |
|
197 type = QMetaType::type(typeName); |
|
198 if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) |
|
199 return result; // unknown type is invalid too |
|
200 |
|
201 result.name = typeName; |
|
202 } else { |
|
203 result.name = QVariant::typeToName( QVariant::Type(type) ); |
|
204 } |
|
205 |
|
206 result.id = type; |
|
207 return result; // success |
|
208 } |
|
209 |
|
210 void QDBusMetaObjectGenerator::parseMethods() |
|
211 { |
|
212 // |
|
213 // TODO: |
|
214 // Add cloned methods when the remote object has return types |
|
215 // |
|
216 |
|
217 QDBusIntrospection::Methods::ConstIterator method_it = data->methods.constBegin(); |
|
218 QDBusIntrospection::Methods::ConstIterator method_end = data->methods.constEnd(); |
|
219 for ( ; method_it != method_end; ++method_it) { |
|
220 const QDBusIntrospection::Method &m = *method_it; |
|
221 Method mm; |
|
222 |
|
223 mm.name = m.name.toLatin1(); |
|
224 QByteArray prototype = mm.name; |
|
225 prototype += '('; |
|
226 |
|
227 bool ok = true; |
|
228 |
|
229 // build the input argument list |
|
230 for (int i = 0; i < m.inputArgs.count(); ++i) { |
|
231 const QDBusIntrospection::Argument &arg = m.inputArgs.at(i); |
|
232 |
|
233 Type type = findType(arg.type.toLatin1(), m.annotations, "In", i); |
|
234 if (type.id == QVariant::Invalid) { |
|
235 ok = false; |
|
236 break; |
|
237 } |
|
238 |
|
239 mm.inputSignature += arg.type.toLatin1(); |
|
240 mm.inputTypes.append(type.id); |
|
241 |
|
242 mm.parameters.append(arg.name.toLatin1()); |
|
243 mm.parameters.append(','); |
|
244 |
|
245 prototype.append(type.name); |
|
246 prototype.append(','); |
|
247 } |
|
248 if (!ok) continue; |
|
249 |
|
250 // build the output argument list: |
|
251 for (int i = 0; i < m.outputArgs.count(); ++i) { |
|
252 const QDBusIntrospection::Argument &arg = m.outputArgs.at(i); |
|
253 |
|
254 Type type = findType(arg.type.toLatin1(), m.annotations, "Out", i); |
|
255 if (type.id == QVariant::Invalid) { |
|
256 ok = false; |
|
257 break; |
|
258 } |
|
259 |
|
260 mm.outputSignature += arg.type.toLatin1(); |
|
261 mm.outputTypes.append(type.id); |
|
262 |
|
263 if (i == 0) { |
|
264 // return value |
|
265 mm.typeName = type.name; |
|
266 } else { |
|
267 // non-const ref parameter |
|
268 mm.parameters.append(arg.name.toLatin1()); |
|
269 mm.parameters.append(','); |
|
270 |
|
271 prototype.append(type.name); |
|
272 prototype.append("&,"); |
|
273 } |
|
274 } |
|
275 if (!ok) continue; |
|
276 |
|
277 // convert the last commas: |
|
278 if (!mm.parameters.isEmpty()) { |
|
279 mm.parameters.truncate(mm.parameters.length() - 1); |
|
280 prototype[prototype.length() - 1] = ')'; |
|
281 } else { |
|
282 prototype.append(')'); |
|
283 } |
|
284 |
|
285 // check the async tag |
|
286 if (m.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true")) |
|
287 mm.tag = "Q_NOREPLY"; |
|
288 |
|
289 // meta method flags |
|
290 mm.flags = AccessPublic | MethodSlot | MethodScriptable; |
|
291 |
|
292 // add |
|
293 methods.insert(QMetaObject::normalizedSignature(prototype), mm); |
|
294 } |
|
295 } |
|
296 |
|
297 void QDBusMetaObjectGenerator::parseSignals() |
|
298 { |
|
299 QDBusIntrospection::Signals::ConstIterator signal_it = data->signals_.constBegin(); |
|
300 QDBusIntrospection::Signals::ConstIterator signal_end = data->signals_.constEnd(); |
|
301 for ( ; signal_it != signal_end; ++signal_it) { |
|
302 const QDBusIntrospection::Signal &s = *signal_it; |
|
303 Method mm; |
|
304 |
|
305 mm.name = s.name.toLatin1(); |
|
306 QByteArray prototype = mm.name; |
|
307 prototype += '('; |
|
308 |
|
309 bool ok = true; |
|
310 |
|
311 // build the output argument list |
|
312 for (int i = 0; i < s.outputArgs.count(); ++i) { |
|
313 const QDBusIntrospection::Argument &arg = s.outputArgs.at(i); |
|
314 |
|
315 Type type = findType(arg.type.toLatin1(), s.annotations, "Out", i); |
|
316 if (type.id == QVariant::Invalid) { |
|
317 ok = false; |
|
318 break; |
|
319 } |
|
320 |
|
321 mm.inputSignature += arg.type.toLatin1(); |
|
322 mm.inputTypes.append(type.id); |
|
323 |
|
324 mm.parameters.append(arg.name.toLatin1()); |
|
325 mm.parameters.append(','); |
|
326 |
|
327 prototype.append(type.name); |
|
328 prototype.append(','); |
|
329 } |
|
330 if (!ok) continue; |
|
331 |
|
332 // convert the last commas: |
|
333 if (!mm.parameters.isEmpty()) { |
|
334 mm.parameters.truncate(mm.parameters.length() - 1); |
|
335 prototype[prototype.length() - 1] = ')'; |
|
336 } else { |
|
337 prototype.append(')'); |
|
338 } |
|
339 |
|
340 // meta method flags |
|
341 mm.flags = AccessProtected | MethodSignal | MethodScriptable; |
|
342 |
|
343 // add |
|
344 methods.insert(QMetaObject::normalizedSignature(prototype), mm); |
|
345 } |
|
346 } |
|
347 |
|
348 void QDBusMetaObjectGenerator::parseProperties() |
|
349 { |
|
350 QDBusIntrospection::Properties::ConstIterator prop_it = data->properties.constBegin(); |
|
351 QDBusIntrospection::Properties::ConstIterator prop_end = data->properties.constEnd(); |
|
352 for ( ; prop_it != prop_end; ++prop_it) { |
|
353 const QDBusIntrospection::Property &p = *prop_it; |
|
354 Property mp; |
|
355 Type type = findType(p.type.toLatin1(), p.annotations); |
|
356 if (type.id == QVariant::Invalid) |
|
357 continue; |
|
358 |
|
359 QByteArray name = p.name.toLatin1(); |
|
360 mp.signature = p.type.toLatin1(); |
|
361 mp.type = type.id; |
|
362 mp.typeName = type.name; |
|
363 |
|
364 // build the flags: |
|
365 mp.flags = StdCppSet | Scriptable | Stored | Designable; |
|
366 if (p.access != QDBusIntrospection::Property::Write) |
|
367 mp.flags |= Readable; |
|
368 if (p.access != QDBusIntrospection::Property::Read) |
|
369 mp.flags |= Writable; |
|
370 |
|
371 if (mp.typeName == "QDBusVariant") |
|
372 mp.flags |= 0xff << 24; |
|
373 else if (mp.type < 0xff) |
|
374 // encode the type in the flags |
|
375 mp.flags |= mp.type << 24; |
|
376 |
|
377 // add the property: |
|
378 properties.insert(name, mp); |
|
379 } |
|
380 } |
|
381 |
|
382 void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj) |
|
383 { |
|
384 // this code here is mostly copied from qaxbase.cpp |
|
385 // with a few modifications to make it cleaner |
|
386 |
|
387 QString className = interface; |
|
388 className.replace(QLatin1Char('.'), QLatin1String("::")); |
|
389 if (className.isEmpty()) |
|
390 className = QLatin1String("QDBusInterface"); |
|
391 |
|
392 QVarLengthArray<int> idata; |
|
393 idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int)); |
|
394 |
|
395 QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data()); |
|
396 header->revision = 1; |
|
397 header->className = 0; |
|
398 header->classInfoCount = 0; |
|
399 header->classInfoData = 0; |
|
400 header->methodCount = methods.count(); |
|
401 header->methodData = idata.size(); |
|
402 header->propertyCount = properties.count(); |
|
403 header->propertyData = header->methodData + header->methodCount * 5; |
|
404 header->enumeratorCount = 0; |
|
405 header->enumeratorData = 0; |
|
406 header->propertyDBusData = header->propertyData + header->propertyCount * 3; |
|
407 header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty; |
|
408 |
|
409 int data_size = idata.size() + |
|
410 (header->methodCount * (5+intsPerMethod)) + |
|
411 (header->propertyCount * (3+intsPerProperty)); |
|
412 foreach (const Method &mm, methods) |
|
413 data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count(); |
|
414 idata.resize(data_size + 1); |
|
415 |
|
416 char null('\0'); |
|
417 QByteArray stringdata = className.toLatin1(); |
|
418 stringdata += null; |
|
419 stringdata.reserve(8192); |
|
420 |
|
421 int offset = header->methodData; |
|
422 int signatureOffset = header->methodDBusData; |
|
423 int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod; |
|
424 idata[typeidOffset++] = 0; // eod |
|
425 |
|
426 // add each method: |
|
427 for (QMap<QByteArray, Method>::ConstIterator it = methods.constBegin(); |
|
428 it != methods.constEnd(); ++it) { |
|
429 // form "prototype\0parameters\0typeName\0tag\0methodname\0inputSignature\0outputSignature" |
|
430 const Method &mm = it.value(); |
|
431 |
|
432 idata[offset++] = stringdata.length(); |
|
433 stringdata += it.key(); // prototype |
|
434 stringdata += null; |
|
435 idata[offset++] = stringdata.length(); |
|
436 stringdata += mm.parameters; |
|
437 stringdata += null; |
|
438 idata[offset++] = stringdata.length(); |
|
439 stringdata += mm.typeName; |
|
440 stringdata += null; |
|
441 idata[offset++] = stringdata.length(); |
|
442 stringdata += mm.tag; |
|
443 stringdata += null; |
|
444 idata[offset++] = mm.flags; |
|
445 |
|
446 idata[signatureOffset++] = stringdata.length(); |
|
447 stringdata += mm.name; |
|
448 stringdata += null; |
|
449 idata[signatureOffset++] = stringdata.length(); |
|
450 stringdata += mm.inputSignature; |
|
451 stringdata += null; |
|
452 idata[signatureOffset++] = stringdata.length(); |
|
453 stringdata += mm.outputSignature; |
|
454 stringdata += null; |
|
455 |
|
456 idata[signatureOffset++] = typeidOffset; |
|
457 idata[typeidOffset++] = mm.inputTypes.count(); |
|
458 memcpy(idata.data() + typeidOffset, mm.inputTypes.data(), mm.inputTypes.count() * sizeof(int)); |
|
459 typeidOffset += mm.inputTypes.count(); |
|
460 |
|
461 idata[signatureOffset++] = typeidOffset; |
|
462 idata[typeidOffset++] = mm.outputTypes.count(); |
|
463 memcpy(idata.data() + typeidOffset, mm.outputTypes.data(), mm.outputTypes.count() * sizeof(int)); |
|
464 typeidOffset += mm.outputTypes.count(); |
|
465 } |
|
466 |
|
467 Q_ASSERT(offset == header->propertyData); |
|
468 Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod); |
|
469 Q_ASSERT(typeidOffset == idata.size()); |
|
470 |
|
471 // add each property |
|
472 signatureOffset = header->propertyDBusData; |
|
473 for (QMap<QByteArray, Property>::ConstIterator it = properties.constBegin(); |
|
474 it != properties.constEnd(); ++it) { |
|
475 const Property &mp = it.value(); |
|
476 |
|
477 // form is "name\0typeName\0signature\0" |
|
478 idata[offset++] = stringdata.length(); |
|
479 stringdata += it.key(); // name |
|
480 stringdata += null; |
|
481 idata[offset++] = stringdata.length(); |
|
482 stringdata += mp.typeName; |
|
483 stringdata += null; |
|
484 idata[offset++] = mp.flags; |
|
485 |
|
486 idata[signatureOffset++] = stringdata.length(); |
|
487 stringdata += mp.signature; |
|
488 stringdata += null; |
|
489 idata[signatureOffset++] = mp.type; |
|
490 } |
|
491 |
|
492 Q_ASSERT(offset == header->propertyDBusData); |
|
493 Q_ASSERT(signatureOffset == header->methodDBusData); |
|
494 |
|
495 char *string_data = new char[stringdata.length()]; |
|
496 memcpy(string_data, stringdata, stringdata.length()); |
|
497 |
|
498 uint *uint_data = new uint[idata.size()]; |
|
499 memcpy(uint_data, idata.data(), idata.size() * sizeof(int)); |
|
500 |
|
501 // put the metaobject together |
|
502 obj->d.data = uint_data; |
|
503 obj->d.extradata = 0; |
|
504 obj->d.stringdata = string_data; |
|
505 obj->d.superdata = &QDBusAbstractInterface::staticMetaObject; |
|
506 } |
|
507 |
|
508 #if 0 |
|
509 void QDBusMetaObjectGenerator::writeWithoutXml(const QString &interface) |
|
510 { |
|
511 // no XML definition |
|
512 QString tmp(interface); |
|
513 tmp.replace(QLatin1Char('.'), QLatin1String("::")); |
|
514 QByteArray name(tmp.toLatin1()); |
|
515 |
|
516 QDBusMetaObjectPrivate *header = new QDBusMetaObjectPrivate; |
|
517 memset(header, 0, sizeof *header); |
|
518 header->revision = 1; |
|
519 // leave the rest with 0 |
|
520 |
|
521 char *stringdata = new char[name.length() + 1]; |
|
522 stringdata[name.length()] = '\0'; |
|
523 |
|
524 d.data = reinterpret_cast<uint*>(header); |
|
525 d.extradata = 0; |
|
526 d.stringdata = stringdata; |
|
527 d.superdata = &QDBusAbstractInterface::staticMetaObject; |
|
528 cached = false; |
|
529 } |
|
530 #endif |
|
531 |
|
532 ///////// |
|
533 // class QDBusMetaObject |
|
534 |
|
535 QDBusMetaObject *QDBusMetaObject::createMetaObject(const QString &interface, const QString &xml, |
|
536 QHash<QString, QDBusMetaObject *> &cache, |
|
537 QDBusError &error) |
|
538 { |
|
539 error = QDBusError(); |
|
540 QDBusIntrospection::Interfaces parsed = QDBusIntrospection::parseInterfaces(xml); |
|
541 |
|
542 QDBusMetaObject *we = 0; |
|
543 QDBusIntrospection::Interfaces::ConstIterator it = parsed.constBegin(); |
|
544 QDBusIntrospection::Interfaces::ConstIterator end = parsed.constEnd(); |
|
545 for ( ; it != end; ++it) { |
|
546 // check if it's in the cache |
|
547 bool us = it.key() == interface; |
|
548 |
|
549 QDBusMetaObject *obj = cache.value(it.key(), 0); |
|
550 if ( !obj && ( us || !interface.startsWith( QLatin1String("local.") ) ) ) { |
|
551 // not in cache; create |
|
552 obj = new QDBusMetaObject; |
|
553 QDBusMetaObjectGenerator generator(it.key(), it.value().constData()); |
|
554 generator.write(obj); |
|
555 |
|
556 if ( (obj->cached = !it.key().startsWith( QLatin1String("local.") )) ) |
|
557 // cache it |
|
558 cache.insert(it.key(), obj); |
|
559 else if (!us) |
|
560 delete obj; |
|
561 |
|
562 } |
|
563 |
|
564 if (us) |
|
565 // it's us |
|
566 we = obj; |
|
567 } |
|
568 |
|
569 if (we) |
|
570 return we; |
|
571 // still nothing? |
|
572 |
|
573 if (parsed.isEmpty()) { |
|
574 // object didn't return introspection |
|
575 we = new QDBusMetaObject; |
|
576 QDBusMetaObjectGenerator generator(interface, 0); |
|
577 generator.write(we); |
|
578 we->cached = false; |
|
579 return we; |
|
580 } else if (interface.isEmpty()) { |
|
581 // merge all interfaces |
|
582 it = parsed.constBegin(); |
|
583 QDBusIntrospection::Interface merged = *it.value().constData(); |
|
584 |
|
585 for (++it; it != end; ++it) { |
|
586 merged.annotations.unite(it.value()->annotations); |
|
587 merged.methods.unite(it.value()->methods); |
|
588 merged.signals_.unite(it.value()->signals_); |
|
589 merged.properties.unite(it.value()->properties); |
|
590 } |
|
591 |
|
592 merged.name = QLatin1String("local.Merged"); |
|
593 merged.introspection.clear(); |
|
594 |
|
595 we = new QDBusMetaObject; |
|
596 QDBusMetaObjectGenerator generator(merged.name, &merged); |
|
597 generator.write(we); |
|
598 we->cached = false; |
|
599 return we; |
|
600 } |
|
601 |
|
602 // mark as an error |
|
603 error = QDBusError(QDBusError::UnknownInterface, |
|
604 QString::fromLatin1("Interface '%1' was not found") |
|
605 .arg(interface)); |
|
606 return 0; |
|
607 } |
|
608 |
|
609 QDBusMetaObject::QDBusMetaObject() |
|
610 { |
|
611 } |
|
612 |
|
613 static inline const QDBusMetaObjectPrivate *priv(const uint* data) |
|
614 { |
|
615 return reinterpret_cast<const QDBusMetaObjectPrivate *>(data); |
|
616 } |
|
617 |
|
618 const char *QDBusMetaObject::dbusNameForMethod(int id) const |
|
619 { |
|
620 //id -= methodOffset(); |
|
621 if (id >= 0 && id < priv(d.data)->methodCount) { |
|
622 int handle = priv(d.data)->methodDBusData + id*intsPerMethod; |
|
623 return d.stringdata + d.data[handle]; |
|
624 } |
|
625 return 0; |
|
626 } |
|
627 |
|
628 const char *QDBusMetaObject::inputSignatureForMethod(int id) const |
|
629 { |
|
630 //id -= methodOffset(); |
|
631 if (id >= 0 && id < priv(d.data)->methodCount) { |
|
632 int handle = priv(d.data)->methodDBusData + id*intsPerMethod; |
|
633 return d.stringdata + d.data[handle + 1]; |
|
634 } |
|
635 return 0; |
|
636 } |
|
637 |
|
638 const char *QDBusMetaObject::outputSignatureForMethod(int id) const |
|
639 { |
|
640 //id -= methodOffset(); |
|
641 if (id >= 0 && id < priv(d.data)->methodCount) { |
|
642 int handle = priv(d.data)->methodDBusData + id*intsPerMethod; |
|
643 return d.stringdata + d.data[handle + 2]; |
|
644 } |
|
645 return 0; |
|
646 } |
|
647 |
|
648 const int *QDBusMetaObject::inputTypesForMethod(int id) const |
|
649 { |
|
650 //id -= methodOffset(); |
|
651 if (id >= 0 && id < priv(d.data)->methodCount) { |
|
652 int handle = priv(d.data)->methodDBusData + id*intsPerMethod; |
|
653 return reinterpret_cast<const int*>(d.data + d.data[handle + 3]); |
|
654 } |
|
655 return 0; |
|
656 } |
|
657 |
|
658 const int *QDBusMetaObject::outputTypesForMethod(int id) const |
|
659 { |
|
660 //id -= methodOffset(); |
|
661 if (id >= 0 && id < priv(d.data)->methodCount) { |
|
662 int handle = priv(d.data)->methodDBusData + id*intsPerMethod; |
|
663 return reinterpret_cast<const int*>(d.data + d.data[handle + 4]); |
|
664 } |
|
665 return 0; |
|
666 } |
|
667 |
|
668 int QDBusMetaObject::propertyMetaType(int id) const |
|
669 { |
|
670 //id -= propertyOffset(); |
|
671 if (id >= 0 && id < priv(d.data)->propertyCount) { |
|
672 int handle = priv(d.data)->propertyDBusData + id*intsPerProperty; |
|
673 return d.data[handle + 1]; |
|
674 } |
|
675 return 0; |
|
676 } |
|
677 |
|
678 QT_END_NAMESPACE |
|
679 |