Qt 4.8
qdbusxmlgenerator.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDBus module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <QtCore/qmetaobject.h>
43 #include <QtCore/qstringlist.h>
44 
45 #include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
46 #include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
47 #include "qdbusconnection_p.h" // for the flags
48 #include "qdbusmetatype_p.h"
49 #include "qdbusmetatype.h"
50 #include "qdbusutil_p.h"
51 
52 #ifndef QT_NO_DBUS
53 
55 
57  const QMetaObject *base, int flags);
58 
59 static inline QString typeNameToXml(const char *typeName)
60 {
61  // ### copied from qtextdocument.cpp
62  // ### move this into QtCore at some point
63  QString plain = QLatin1String(typeName);
64  QString rich;
65  rich.reserve(int(plain.length() * 1.1));
66  for (int i = 0; i < plain.length(); ++i) {
67  if (plain.at(i) == QLatin1Char('<'))
68  rich += QLatin1String("&lt;");
69  else if (plain.at(i) == QLatin1Char('>'))
70  rich += QLatin1String("&gt;");
71  else if (plain.at(i) == QLatin1Char('&'))
72  rich += QLatin1String("&amp;");
73  else
74  rich += plain.at(i);
75  }
76  return rich;
77 }
78 
79 // implement the D-Bus org.freedesktop.DBus.Introspectable interface
80 // we do that by analysing the metaObject of all the adaptor interfaces
81 
82 static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
83 {
84  QString retval;
85 
86  // start with properties:
89  for (int i = propOffset; i < mo->propertyCount(); ++i) {
90  static const char *accessvalues[] = {0, "read", "write", "readwrite"};
91 
92  QMetaProperty mp = mo->property(i);
93 
96  continue;
97 
98  int access = 0;
99  if (mp.isReadable())
100  access |= 1;
101  if (mp.isWritable())
102  access |= 2;
103 
104  int typeId = qDBusNameToTypeId(mp.typeName());
105  if (!typeId)
106  continue;
107  const char *signature = QDBusMetaType::typeToSignature(typeId);
108  if (!signature)
109  continue;
110 
111  retval += QString::fromLatin1(" <property name=\"%1\" type=\"%2\" access=\"%3\"")
112  .arg(QLatin1String(mp.name()))
113  .arg(QLatin1String(signature))
114  .arg(QLatin1String(accessvalues[access]));
115 
117  const char *typeName = QVariant::typeToName(QVariant::Type(typeId));
118  retval += QString::fromLatin1(">\n <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n")
119  .arg(typeNameToXml(typeName));
120  } else {
121  retval += QLatin1String("/>\n");
122  }
123  }
124  }
125 
126  // now add methods:
127  for (int i = methodOffset; i < mo->methodCount(); ++i) {
128  QMetaMethod mm = mo->method(i);
129  QByteArray signature = mm.signature();
130  int paren = signature.indexOf('(');
131 
132  bool isSignal;
133  if (mm.methodType() == QMetaMethod::Signal)
134  // adding a signal
135  isSignal = true;
136  else if (mm.access() == QMetaMethod::Public && (mm.methodType() == QMetaMethod::Slot || mm.methodType() == QMetaMethod::Method))
137  isSignal = false;
138  else
139  continue; // neither signal nor public slot
140 
141  if (isSignal && !(flags & (QDBusConnection::ExportScriptableSignals |
143  continue; // we're not exporting any signals
146  continue; // we're not exporting any slots or invokables
147 
148  QString xml = QString::fromLatin1(" <%1 name=\"%2\">\n")
149  .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
150  .arg(QLatin1String(signature.left(paren)));
151 
152  // check the return type first
153  int typeId = qDBusNameToTypeId(mm.typeName());
154  if (typeId) {
155  const char *typeName = QDBusMetaType::typeToSignature(typeId);
156  if (typeName) {
157  xml += QString::fromLatin1(" <arg type=\"%1\" direction=\"out\"/>\n")
158  .arg(typeNameToXml(typeName));
159 
160  // do we need to describe this argument?
162  xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
164  } else
165  continue;
166  }
167  else if (*mm.typeName())
168  continue; // wasn't a valid type
169 
170  QList<QByteArray> names = mm.parameterNames();
172  int inputCount = qDBusParametersForMethod(mm, types);
173  if (inputCount == -1)
174  continue; // invalid form
175  if (isSignal && inputCount + 1 != types.count())
176  continue; // signal with output arguments?
177  if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message)
178  continue; // signal with QDBusMessage argument?
179  if (isSignal && mm.attributes() & QMetaMethod::Cloned)
180  continue; // cloned signal?
181 
182  int j;
183  bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
184  for (j = 1; j < types.count(); ++j) {
185  // input parameter for a slot or output for a signal
186  if (types.at(j) == QDBusMetaTypeId::message) {
187  isScriptable = true;
188  continue;
189  }
190 
191  QString name;
192  if (!names.at(j - 1).isEmpty())
193  name = QString::fromLatin1("name=\"%1\" ").arg(QLatin1String(names.at(j - 1)));
194 
195  bool isOutput = isSignal || j > inputCount;
196 
197  const char *signature = QDBusMetaType::typeToSignature(types.at(j));
198  xml += QString::fromLatin1(" <arg %1type=\"%2\" direction=\"%3\"/>\n")
199  .arg(name)
200  .arg(QLatin1String(signature))
201  .arg(isOutput ? QLatin1String("out") : QLatin1String("in"));
202 
203  // do we need to describe this argument?
205  const char *typeName = QVariant::typeToName( QVariant::Type(types.at(j)) );
206  xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n")
207  .arg(isOutput ? QLatin1String("Out") : QLatin1String("In"))
208  .arg(isOutput && !isSignal ? j - inputCount : j - 1)
209  .arg(typeNameToXml(typeName));
210  }
211  }
212 
213  int wantedMask;
214  if (isScriptable)
215  wantedMask = isSignal ? QDBusConnection::ExportScriptableSignals
217  else
218  wantedMask = isSignal ? QDBusConnection::ExportNonScriptableSignals
220  if ((flags & wantedMask) != wantedMask)
221  continue;
222 
223  if (qDBusCheckAsyncTag(mm.tag()))
224  // add the no-reply annotation
225  xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
226  " value=\"true\"/>\n");
227 
228  retval += xml;
229  retval += QString::fromLatin1(" </%1>\n")
230  .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
231  }
232 
233  return retval;
234 }
235 
237  const QMetaObject *base, int flags)
238 {
239  if (interface.isEmpty())
240  // generate the interface name from the meta object
241  interface = qDBusInterfaceFromMetaObject(mo);
242 
243  QString xml;
245  if (idx >= mo->classInfoOffset())
246  return QString::fromUtf8(mo->classInfo(idx).value());
247  else
248  xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
249 
250  if (xml.isEmpty())
251  return QString(); // don't add an empty interface
252  return QString::fromLatin1(" <interface name=\"%1\">\n%2 </interface>\n")
253  .arg(interface, xml);
254 }
255 #if 0
257  int flags)
258 {
259  if (interface.isEmpty()) {
260  // generate the interface name from the meta object
262  if (idx >= mo->classInfoOffset()) {
263  interface = QLatin1String(mo->classInfo(idx).value());
264  } else {
265  interface = QLatin1String(mo->className());
266  interface.replace(QLatin1String("::"), QLatin1String("."));
267 
268  if (interface.startsWith(QLatin1String("QDBus"))) {
269  interface.prepend(QLatin1String("org.qtproject.QtDBus."));
270  } else if (interface.startsWith(QLatin1Char('Q')) &&
271  interface.length() >= 2 && interface.at(1).isUpper()) {
272  // assume it's Qt
273  interface.prepend(QLatin1String("org.qtproject.Qt."));
274  } else if (!QCoreApplication::instance()||
275  QCoreApplication::instance()->applicationName().isEmpty()) {
276  interface.prepend(QLatin1String("local."));
277  } else {
278  interface.prepend(QLatin1Char('.')).prepend(QCoreApplication::instance()->applicationName());
279  QStringList domainName =
282  if (domainName.isEmpty())
283  interface.prepend(QLatin1String("local."));
284  else
285  for (int i = 0; i < domainName.count(); ++i)
286  interface.prepend(QLatin1Char('.')).prepend(domainName.at(i));
287  }
288  }
289  }
290 
291  QString xml;
293  if (idx >= mo->classInfoOffset())
294  return QString::fromUtf8(mo->classInfo(idx).value());
295  else
296  xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
297 
298  if (xml.isEmpty())
299  return QString(); // don't add an empty interface
300  return QString::fromLatin1(" <interface name=\"%1\">\n%2 </interface>\n")
301  .arg(interface, xml);
302 }
303 
304 #endif
305 
307 
308 #endif // QT_NO_DBUS
static QString typeNameToXml(const char *typeName)
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
static int signatureToType(const char *signature)
bool isScriptable(const QObject *obj=0) const
Returns true if the property is scriptable for the given object; otherwise returns false...
bool isWritable() const
Returns true if this property is writable; otherwise returns false.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define QCLASSINFO_DBUS_INTROSPECTION
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QString organizationDomain
the Internet domain of the organization that wrote this application
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
int propertyCount() const
Returns the number of properties in this class, including the number of properties provided by each b...
The QString class provides a Unicode character string.
Definition: qstring.h:83
const char * typeName() const
Returns the return type of this method, or an empty string if the return type is void.
static const char * typeToName(Type type)
Converts the enum representation of the storage type, typ, to its string representation.
Definition: qvariant.cpp:2008
const char * value() const
Returns the value of this item.
static const uint base
Definition: qurl.cpp:268
bool qDBusCheckAsyncTag(const char *tag)
Definition: qdbusmisc.cpp:57
int qDBusParametersForMethod(const QMetaMethod &mm, QList< int > &metaTypes)
Definition: qdbusmisc.cpp:137
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void reserve(int size)
Attempts to allocate memory for at least size characters.
Definition: qstring.h:881
Q_DBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base, int flags)
static const char * typeToSignature(int type)
Returns the D-Bus signature equivalent to the supplied meta type id type.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QString qDBusInterfaceFromMetaObject(const QMetaObject *mo)
Definition: qdbusmisc.cpp:80
static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
static bool isEmpty(const char *str)
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
#define ANNOTATION_NO_WAIT
int access(const char *, int)
const char * typeName
Definition: qmetatype.cpp:239
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static int message
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define QCLASSINFO_DBUS_INTERFACE
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
int indexOf(char c, int from=0) const
Returns the index position of the first occurrence of the character ch in the byte array...
bool isUpper() const
Returns true if the character is an uppercase letter, i.
Definition: qchar.h:273
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
int qDBusNameToTypeId(const char *name)
Definition: qdbusmisc.cpp:72
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
const char * name() const
Returns this property&#39;s name.
static const struct @32 types[]
static QCoreApplication * instance()
Returns a pointer to the application&#39;s QCoreApplication (or QApplication) instance.
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
const char * tag() const
Returns the tag associated with this method.
int classInfoOffset() const
Returns the class information offset for this class; i.e.
#define Q_DBUS_EXPORT
Definition: qglobal.h:1463
int attributes() const
bool isReadable() const
Returns true if this property is readable; otherwise returns false.
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:176
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
Access access() const
Returns the access specification of this method (private, protected, or public).
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
int methodCount() const
Returns the number of methods known to the meta-object system in this class, including the number of ...
const char * typeName() const
Returns the name of this property&#39;s type.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.