Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdbusxmlgenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qmetaobject.h>
5#include <QtCore/qstringlist.h>
6#include <QtCore/qdebug.h>
7
8#include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
9#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
10#include "qdbusconnection_p.h" // for the flags
11#include "qdbusmetatype_p.h"
12#include "qdbusmetatype.h"
13#include "qdbusutil_p.h"
14
15#ifndef QT_NO_DBUS
16
18
19using namespace Qt::StringLiterals;
20
22 const QMetaObject *base, int flags);
23
24static inline QString typeNameToXml(const char *typeName)
25{
26 // ### copied from qtextdocument.cpp
27 // ### move this into Qt Core at some point
28 const QLatin1StringView plain(typeName);
29 QString rich;
30 rich.reserve(int(plain.size() * 1.1));
31 for (int i = 0; i < plain.size(); ++i) {
32 if (plain.at(i) == u'<')
33 rich += "&lt;"_L1;
34 else if (plain.at(i) == u'>')
35 rich += "&gt;"_L1;
36 else if (plain.at(i) == u'&')
37 rich += "&amp;"_L1;
38 else
39 rich += plain.at(i);
40 }
41 return rich;
42}
43
44static inline QLatin1StringView accessAsString(bool read, bool write)
45{
46 if (read)
47 return write ? "readwrite"_L1 : "read"_L1 ;
48 else
49 return write ? "write"_L1 : ""_L1 ;
50}
51
52// implement the D-Bus org.freedesktop.DBus.Introspectable interface
53// we do that by analysing the metaObject of all the adaptor interfaces
54
55static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
56{
57 QString retval;
58
59 // start with properties:
62 for (int i = propOffset; i < mo->propertyCount(); ++i) {
63
64 QMetaProperty mp = mo->property(i);
65
66 if (!((mp.isScriptable() && (flags & QDBusConnection::ExportScriptableProperties)) ||
67 (!mp.isScriptable() && (flags & QDBusConnection::ExportNonScriptableProperties))))
68 continue;
69
70 QMetaType type = mp.metaType();
71 if (!type.isValid())
72 continue;
73 const char *signature = QDBusMetaType::typeToSignature(type);
74 if (!signature)
75 continue;
76
77 retval += " <property name=\"%1\" type=\"%2\" access=\"%3\""_L1
78 .arg(QLatin1StringView(mp.name()),
79 QLatin1StringView(signature),
80 accessAsString(mp.isReadable(), mp.isWritable()));
81
82 if (!QDBusMetaType::signatureToMetaType(signature).isValid()) {
83 const char *typeName = type.name();
84 retval += ">\n <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n"_L1
86 } else {
87 retval += "/>\n"_L1;
88 }
89 }
90 }
91
92 // now add methods:
93 for (int i = methodOffset; i < mo->methodCount(); ++i) {
94 QMetaMethod mm = mo->method(i);
95
96 bool isSignal = false;
97 bool isSlot = false;
99 // adding a signal
100 isSignal = true;
101 else if (mm.access() == QMetaMethod::Public && mm.methodType() == QMetaMethod::Slot)
102 isSlot = true;
103 else if (mm.access() == QMetaMethod::Public && mm.methodType() == QMetaMethod::Method)
104 ; // invokable, neither signal nor slot
105 else
106 continue; // neither signal nor public method/slot
107
110 continue; // we're not exporting any signals
113 continue; // we're not exporting any slots or invokables
114
115 // we want to skip non-scriptable stuff as early as possible to avoid bogus warning
116 // for methods that are not being exported at all
117 bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
119 continue;
120
121 QString xml = QString::asprintf(" <%s name=\"%s\">\n",
122 isSignal ? "signal" : "method", mm.name().constData());
123
124 // check the return type first
125 QMetaType typeId = mm.returnMetaType();
126 if (typeId.isValid() && typeId.id() != QMetaType::Void) {
127 const char *typeName = QDBusMetaType::typeToSignature(typeId);
128 if (typeName) {
129 xml += " <arg type=\"%1\" direction=\"out\"/>\n"_L1
130 .arg(typeNameToXml(typeName));
131
132 // do we need to describe this argument?
134 xml += " <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n"_L1
135 .arg(typeNameToXml(QMetaType(typeId).name()));
136 } else {
137 qWarning() << "Unsupported return type" << typeId.id() << typeId.name() << "in method" << mm.name();
138 continue;
139 }
140 }
141 else if (!typeId.isValid()) {
142 qWarning() << "Invalid return type in method" << mm.name();
143 continue; // wasn't a valid type
144 }
145
146 QList<QByteArray> names = mm.parameterNames();
147 QList<QMetaType> types;
148 QString errorMsg;
149 int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
150 if (inputCount == -1) {
151 qWarning() << "Skipped method" << mm.name() << ":" << qPrintable(errorMsg);
152 continue; // invalid form
153 }
154 if (isSignal && inputCount + 1 != types.size())
155 continue; // signal with output arguments?
156 if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message())
157 continue; // signal with QDBusMessage argument?
158 if (isSignal && mm.attributes() & QMetaMethod::Cloned)
159 continue; // cloned signal?
160
161 int j;
162 for (j = 1; j < types.size(); ++j) {
163 // input parameter for a slot or output for a signal
164 if (types.at(j) == QDBusMetaTypeId::message()) {
165 isScriptable = true;
166 continue;
167 }
168
170 if (!names.at(j - 1).isEmpty())
171 name = "name=\"%1\" "_L1.arg(QLatin1StringView(names.at(j - 1)));
172
173 bool isOutput = isSignal || j > inputCount;
174
175 const char *signature = QDBusMetaType::typeToSignature(types.at(j));
176 xml += QString::asprintf(" <arg %lstype=\"%s\" direction=\"%s\"/>\n",
177 qUtf16Printable(name), signature, isOutput ? "out" : "in");
178
179 // do we need to describe this argument?
180 if (!QDBusMetaType::signatureToMetaType(signature).isValid()) {
181 const char *typeName = QMetaType(types.at(j)).name();
182 xml += QString::fromLatin1(" <annotation name=\"org.qtproject.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n")
183 .arg(isOutput ? "Out"_L1 : "In"_L1)
184 .arg(isOutput && !isSignal ? j - inputCount : j - 1)
186 }
187 }
188
189 int wantedMask;
190 if (isScriptable)
191 wantedMask = isSignal ? QDBusConnection::ExportScriptableSignals
194 else
195 wantedMask = isSignal ? QDBusConnection::ExportNonScriptableSignals
198 if ((flags & wantedMask) != wantedMask)
199 continue;
200
201 if (qDBusCheckAsyncTag(mm.tag()))
202 // add the no-reply annotation
203 xml += " <annotation name=\"" ANNOTATION_NO_WAIT "\" value=\"true\"/>\n"_L1;
204
205 retval += xml;
206 retval += " </%1>\n"_L1.arg(isSignal ? "signal"_L1 : "method"_L1);
207 }
208
209 return retval;
210}
211
213 const QMetaObject *base, int flags)
214{
215 if (interface.isEmpty())
216 // generate the interface name from the meta object
217 interface = qDBusInterfaceFromMetaObject(mo);
218
219 QString xml;
220 int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTROSPECTION);
221 if (idx >= mo->classInfoOffset())
222 return QString::fromUtf8(mo->classInfo(idx).value());
223 else
224 xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
225
226 if (xml.isEmpty())
227 return QString(); // don't add an empty interface
228 return " <interface name=\"%1\">\n%2 </interface>\n"_L1
229 .arg(interface, xml);
230}
231
233
234#endif // QT_NO_DBUS
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
static QMetaType signatureToMetaType(const char *signature)
static const char * typeToSignature(QMetaType type)
\inmodule QtCore
Definition qmetaobject.h:19
Access access() const
Returns the access specification of this method (private, protected, or public).
QMetaType returnMetaType() const
const char * tag() const
Returns the tag associated with this method.
int attributes() const
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
QByteArray name() const
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:341
constexpr const char * name() const
Definition qmetatype.h:2680
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1325
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition qstring.cpp:7263
auto mo
[7]
QMetaType message()
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
#define QCLASSINFO_DBUS_INTROSPECTION
#define ANNOTATION_NO_WAIT
int qDBusParametersForMethod(const QMetaMethod &mm, QList< QMetaType > &metaTypes, QString &errorMsg)
Q_DBUS_EXPORT bool qDBusCheckAsyncTag(const char *tag)
Definition qdbusmisc.cpp:25
static QLatin1StringView accessAsString(bool read, bool write)
static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
Q_DBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base, int flags)
static QString typeNameToXml(const char *typeName)
#define qWarning
Definition qlogging.h:166
const char * typeName
GLsizei GLenum GLenum * types
GLenum type
GLbitfield flags
GLuint name
GLuint GLuint * names
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
#define qUtf16Printable(string)
Definition qstring.h:1543
static const uint base
Definition qurlidna.cpp:20
ReturnedValue read(const char *data)
gzip write("uncompressed data")
QXmlStreamReader xml
[0]
\inmodule QtCore