summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2012-03-08 23:43:28 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-18 14:14:42 +0100
commit72367b1679f8176c8f8a2a424a1c9325433dd8cd (patch)
treee5df865b041b1a1841a816a54b6d1664ac7f7431
parent0054505510b6f2bd20eb7648dbbcaa0e0a975d79 (diff)
Bootstrap qdbuscpp2xml.
This involves invoking the Moc classes directly and using the data structures it provides instead of invoking the moc exectutable and parsing the generated code. Change-Id: Ia5c654e8ef58d52d0d3376252c13e13885f80da3 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp431
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.pro38
-rw-r--r--src/tools/tools.pro5
-rw-r--r--tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.pro11
-rw-r--r--tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.qrc5
-rw-r--r--tests/auto/tools/qdbuscpp2xml/test1.h128
-rw-r--r--tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp181
-rw-r--r--tests/auto/tools/tools.pro1
8 files changed, 582 insertions, 218 deletions
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index 5814dc740b..2029147ecf 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -43,12 +43,9 @@
#include <QString>
#include <QVarLengthArray>
#include <QFile>
-#include <QProcess>
-#include <QMetaObject>
#include <QList>
+#include <QBuffer>
#include <QRegExp>
-#include <QCoreApplication>
-#include <QLibraryInfo>
#include <stdio.h>
#include <stdlib.h>
@@ -56,20 +53,26 @@
#include <stdlib.h>
#include "qdbusconnection.h" // for the Export* flags
+#include "qdbusconnection_p.h" // for the qDBusCheckAsyncTag
// copied from dbus-protocol.h:
static const char docTypeHeader[] =
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
-// in qdbusxmlgenerator.cpp
-QT_BEGIN_NAMESPACE
-extern Q_DBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
- const QMetaObject *base, int flags);
-QT_END_NAMESPACE
+#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
+#define QCLASSINFO_DBUS_INTERFACE "D-Bus Interface"
+#define QCLASSINFO_DBUS_INTROSPECTION "D-Bus Introspection"
+
+#include "qdbusmetatype_p.h"
+#include "qdbusmetatype.h"
+#include "qdbusutil_p.h"
+
+#include "moc.h"
+#include "generator.h"
#define PROGRAMNAME "qdbuscpp2xml"
-#define PROGRAMVERSION "0.1"
+#define PROGRAMVERSION "0.2"
#define PROGRAMCOPYRIGHT "Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)."
static QString outputFile;
@@ -90,199 +93,218 @@ static const char help[] =
" -V Show the program version and quit.\n"
"\n";
-class MocParser
-{
- void parseError();
- QByteArray readLine();
- void loadIntData(uint *&data);
- void loadStringData(char *&stringdata);
-
- QIODevice *input;
- const char *filename;
- int lineNumber;
-public:
- ~MocParser();
- void parse(const char *filename, QIODevice *input, int lineNumber = 0);
-
- QList<QMetaObject> objects;
-};
-
-void MocParser::parseError()
+
+int qDBusParametersForMethod(const FunctionDef &mm, QList<int>& metaTypes)
{
- fprintf(stderr, PROGRAMNAME ": error parsing input file '%s' line %d \n", filename, lineNumber);
- exit(1);
+ QList<QByteArray> parameterTypes;
+
+ foreach (const ArgumentDef &arg, mm.arguments)
+ parameterTypes.append(arg.normalizedType);
+
+ return qDBusParametersForMethod(parameterTypes, metaTypes);
}
-QByteArray MocParser::readLine()
+
+static inline QString typeNameToXml(const char *typeName)
{
- ++lineNumber;
- return input->readLine();
+ QString plain = QLatin1String(typeName);
+ return plain.toHtmlEscaped();
}
-void MocParser::loadIntData(uint *&data)
-{
- data = 0; // initialise
- QVarLengthArray<uint> array;
- QRegExp rx(QLatin1String("(\\d+|0x[0-9abcdef]+)"), Qt::CaseInsensitive);
-
- while (!input->atEnd()) {
- QString line = QLatin1String(readLine());
- int pos = line.indexOf(QLatin1String("//"));
- if (pos != -1)
- line.truncate(pos); // drop comments
-
- if (line == QLatin1String("};\n")) {
- // end of data
- data = new uint[array.count()];
- memcpy(data, array.data(), array.count() * sizeof(*data));
- return;
+static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
+
+ QString xml = QString::fromLatin1(" <%1 name=\"%2\">\n")
+ .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
+ .arg(QLatin1String(mm.name));
+
+ // check the return type first
+ int typeId = QMetaType::type(mm.normalizedType.constData());
+ if (typeId != QMetaType::Void) {
+ if (typeId) {
+ const char *typeName = QDBusMetaType::typeToSignature(typeId);
+ if (typeName) {
+ xml += QString::fromLatin1(" <arg type=\"%1\" direction=\"out\"/>\n")
+ .arg(typeNameToXml(typeName));
+
+ // do we need to describe this argument?
+ if (QDBusMetaType::signatureToType(typeName) == QVariant::Invalid)
+ xml += QString::fromLatin1(" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"%1\"/>\n")
+ .arg(typeNameToXml(mm.normalizedType.constData()));
+ } else {
+ return QString();
+ }
+ } else if (!mm.normalizedType.isEmpty()) {
+ return QString(); // wasn't a valid type
+ }
+ }
+ QList<ArgumentDef> names = mm.arguments;
+ QList<int> types;
+ int inputCount = qDBusParametersForMethod(mm, types);
+ if (inputCount == -1)
+ return QString(); // invalid form
+ if (isSignal && inputCount + 1 != types.count())
+ return QString(); // signal with output arguments?
+ if (isSignal && types.at(inputCount) == QDBusMetaTypeId::message)
+ return QString(); // signal with QDBusMessage argument?
+
+ bool isScriptable = mm.isScriptable;
+ for (int j = 1; j < types.count(); ++j) {
+ // input parameter for a slot or output for a signal
+ if (types.at(j) == QDBusMetaTypeId::message) {
+ isScriptable = true;
+ continue;
}
- pos = 0;
- while ((pos = rx.indexIn(line, pos)) != -1) {
- QString num = rx.cap(1);
- if (num.startsWith(QLatin1String("0x")))
- array.append(num.mid(2).toUInt(0, 16));
- else
- array.append(num.toUInt());
- pos += rx.matchedLength();
+ QString name;
+ if (!names.at(j - 1).name.isEmpty())
+ name = QString::fromLatin1("name=\"%1\" ").arg(QString::fromLatin1(names.at(j - 1).name));
+
+ bool isOutput = isSignal || j > inputCount;
+
+ const char *signature = QDBusMetaType::typeToSignature(types.at(j));
+ xml += QString::fromLatin1(" <arg %1type=\"%2\" direction=\"%3\"/>\n")
+ .arg(name)
+ .arg(QLatin1String(signature))
+ .arg(isOutput ? QLatin1String("out") : QLatin1String("in"));
+
+ // do we need to describe this argument?
+ if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) {
+ const char *typeName = QMetaType::typeName(types.at(j));
+ xml += QString::fromLatin1(" <annotation name=\"com.trolltech.QtDBus.QtTypeName.%1%2\" value=\"%3\"/>\n")
+ .arg(isOutput ? QLatin1String("Out") : QLatin1String("In"))
+ .arg(isOutput && !isSignal ? j - inputCount : j - 1)
+ .arg(typeNameToXml(typeName));
}
}
- parseError();
+ int wantedMask;
+ if (isScriptable)
+ wantedMask = isSignal ? QDBusConnection::ExportScriptableSignals
+ : QDBusConnection::ExportScriptableSlots;
+ else
+ wantedMask = isSignal ? QDBusConnection::ExportNonScriptableSignals
+ : QDBusConnection::ExportNonScriptableSlots;
+ if ((flags & wantedMask) != wantedMask)
+ return QString();
+
+ if (qDBusCheckAsyncTag(mm.tag.constData()))
+ // add the no-reply annotation
+ xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
+ " value=\"true\"/>\n");
+
+ QString retval = xml;
+ retval += QString::fromLatin1(" </%1>\n")
+ .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
+
+ return retval;
}
-void MocParser::loadStringData(char *&stringdata)
-{
- stringdata = 0;
- QVarLengthArray<char, 1024> array;
-
- while (!input->atEnd()) {
- QByteArray line = readLine();
- if (line == "};\n") {
- // end of data
- stringdata = new char[array.count()];
- memcpy(stringdata, array.data(), array.count() * sizeof(*stringdata));
- return;
- }
- int start = line.indexOf('"');
- if (start == -1)
- parseError();
-
- int len = line.length() - 1;
- line.truncate(len); // drop ending \n
- if (line.at(len - 1) != '"')
- parseError();
-
- --len;
- ++start;
- for ( ; start < len; ++start)
- if (line.at(start) == '\\') {
- // parse escaped sequence
- ++start;
- if (start == len)
- parseError();
-
- QChar c(QLatin1Char(line.at(start)));
- if (!c.isDigit()) {
- switch (c.toLatin1()) {
- case 'a':
- array.append('\a');
- break;
- case 'b':
- array.append('\b');
- break;
- case 'f':
- array.append('\f');
- break;
- case 'n':
- array.append('\n');
- break;
- case 'r':
- array.append('\r');
- break;
- case 't':
- array.append('\t');
- break;
- case 'v':
- array.append('\v');
- break;
- case '\\':
- case '?':
- case '\'':
- case '"':
- array.append(c.toLatin1());
- break;
-
- case 'x':
- if (start + 2 <= len)
- parseError();
- array.append(char(line.mid(start + 1, 2).toInt(0, 16)));
- break;
-
- default:
- array.append(c.toLatin1());
- fprintf(stderr, PROGRAMNAME ": warning: invalid escape sequence '\\%c' found in input",
- c.toLatin1());
- }
- } else {
- // octal
- QRegExp octal(QLatin1String("([0-7]+)"));
- if (octal.indexIn(QLatin1String(line), start) == -1)
- parseError();
- array.append(char(octal.cap(1).toInt(0, 8)));
- }
+static QString generateInterfaceXml(const ClassDef *mo)
+{
+ QString retval;
+
+ // start with properties:
+ if (flags & (QDBusConnection::ExportScriptableProperties |
+ QDBusConnection::ExportNonScriptableProperties)) {
+ static const char *accessvalues[] = {0, "read", "write", "readwrite"};
+ foreach (const PropertyDef &mp, mo->propertyList) {
+ if (!((!mp.scriptable.isEmpty() && (flags & QDBusConnection::ExportScriptableProperties)) ||
+ (!mp.scriptable.isEmpty() && (flags & QDBusConnection::ExportNonScriptableProperties))))
+ continue;
+
+ int access = 0;
+ if (!mp.read.isEmpty())
+ access |= 1;
+ if (!mp.write.isEmpty())
+ access |= 2;
+
+ int typeId = QMetaType::type(mp.type.constData());
+ if (!typeId)
+ continue;
+ const char *signature = QDBusMetaType::typeToSignature(typeId);
+ if (!signature)
+ continue;
+
+ retval += QString::fromLatin1(" <property name=\"%1\" type=\"%2\" access=\"%3\"")
+ .arg(QLatin1String(mp.name))
+ .arg(QLatin1String(signature))
+ .arg(QLatin1String(accessvalues[access]));
+
+ if (QDBusMetaType::signatureToType(signature) == QVariant::Invalid) {
+ retval += QString::fromLatin1(">\n <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"%3\"/>\n </property>\n")
+ .arg(typeNameToXml(mp.type.constData()));
} else {
- array.append(line.at(start));
+ retval += QLatin1String("/>\n");
}
+ }
+ }
+
+ // now add methods:
+
+ if (flags & (QDBusConnection::ExportScriptableSignals | QDBusConnection::ExportNonScriptableSignals)) {
+ foreach (const FunctionDef &mm, mo->signalList) {
+ if (mm.wasCloned)
+ continue;
+
+ retval += addFunction(mm, true);
+ }
}
- parseError();
+ if (flags & (QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportNonScriptableSlots)) {
+ foreach (const FunctionDef &slot, mo->slotList) {
+ if (slot.access == FunctionDef::Public)
+ retval += addFunction(slot);
+ }
+ foreach (const FunctionDef &method, mo->methodList) {
+ if (method.access == FunctionDef::Public)
+ retval += addFunction(method);
+ }
+ }
+ return retval;
}
-void MocParser::parse(const char *fname, QIODevice *io, int lineNum)
+QString qDBusInterfaceFromClassDef(const ClassDef *mo)
{
- filename = fname;
- input = io;
- lineNumber = lineNum;
-
- while (!input->atEnd()) {
- QByteArray line = readLine();
- if (line.startsWith("static const uint qt_meta_data_")) {
- // start of new class data
- uint *data;
- loadIntData(data);
-
- // find the start of the string data
- do {
- line = readLine();
- if (input->atEnd())
- parseError();
- } while (!line.startsWith("static const char qt_meta_stringdata_"));
-
- char *stringdata;
- loadStringData(stringdata);
-
- QMetaObject mo;
- mo.d.superdata = &QObject::staticMetaObject;
- mo.d.stringdata = stringdata;
- mo.d.data = data;
- mo.d.extradata = 0;
- objects.append(mo);
- }
+ QString interface;
+
+ foreach (ClassInfoDef cid, mo->classInfoList) {
+ if (cid.name == QCLASSINFO_DBUS_INTERFACE)
+ return QString::fromUtf8(cid.value);
+ }
+ interface = QLatin1String(mo->classname);
+ interface.replace(QLatin1String("::"), QLatin1String("."));
+
+ if (interface.startsWith(QLatin1String("QDBus"))) {
+ interface.prepend(QLatin1String("com.trolltech.QtDBus."));
+ } else if (interface.startsWith(QLatin1Char('Q')) &&
+ interface.length() >= 2 && interface.at(1).isUpper()) {
+ // assume it's Qt
+ interface.prepend(QLatin1String("local.com.trolltech.Qt."));
+ } else {
+ interface.prepend(QLatin1String("local."));
}
- fname = 0;
- input = 0;
+ return interface;
}
-MocParser::~MocParser()
+
+QString qDBusGenerateClassDefXml(const ClassDef *cdef)
{
- foreach (QMetaObject mo, objects) {
- delete const_cast<char *>(mo.d.stringdata);
- delete const_cast<uint *>(mo.d.data);
+ foreach (const ClassInfoDef &cid, cdef->classInfoList) {
+ if (cid.name == QCLASSINFO_DBUS_INTROSPECTION)
+ return QString::fromUtf8(cid.value);
}
+
+ // generate the interface name from the meta object
+ QString interface = qDBusInterfaceFromClassDef(cdef);
+
+ QString xml = generateInterfaceXml(cdef);
+
+ if (xml.isEmpty())
+ return QString(); // don't add an empty interface
+ return QString::fromLatin1(" <interface name=\"%1\">\n%2 </interface>\n")
+ .arg(interface, xml);
}
static void showHelp()
@@ -300,7 +322,8 @@ static void showVersion()
static void parseCmdLine(QStringList &arguments)
{
- for (int i = 1; i < arguments.count(); ++i) {
+ flags = 0;
+ for (int i = 0; i < arguments.count(); ++i) {
const QString arg = arguments.at(i);
if (arg == QLatin1String("--help"))
@@ -369,14 +392,16 @@ static void parseCmdLine(QStringList &arguments)
int main(int argc, char **argv)
{
- QCoreApplication app(argc, argv);
- QStringList args = app.arguments();
-
- MocParser parser;
+ QStringList args;
+ for (int n = 1; n < argc; ++n)
+ args.append(QString::fromLocal8Bit(argv[n]));
parseCmdLine(args);
- for (int i = 1; i < args.count(); ++i) {
+ QList<ClassDef> classes;
+
+ for (int i = 0; i < args.count(); ++i) {
const QString arg = args.at(i);
+
if (arg.startsWith(QLatin1Char('-')))
continue;
@@ -387,35 +412,22 @@ int main(int argc, char **argv)
return 1;
}
- f.readLine();
+ Preprocessor pp;
+ Moc moc(pp);
+ pp.macros["Q_MOC_RUN"];
+ pp.macros["__cplusplus"];
- QByteArray line = f.readLine();
- if (line.contains("Meta object code from reading C++ file"))
- // this is a moc-generated file
- parser.parse(argv[i], &f, 3);
- else {
- // run moc on this file
- QProcess proc;
- proc.start(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/moc"), QStringList() << QFile::decodeName(argv[i]), QIODevice::ReadOnly | QIODevice::Text);
+ const QByteArray filename = QFile::decodeName(argv[i]).toLatin1();
- if (!proc.waitForStarted()) {
- fprintf(stderr, PROGRAMNAME ": could not execute moc! Aborting.\n");
- return 1;
- }
+ moc.filename = filename;
+ moc.currentFilenames.push(filename);
- proc.closeWriteChannel();
+ moc.symbols = pp.preprocessed(moc.filename, &f);
+ moc.parse();
- if (!proc.waitForFinished() || proc.exitStatus() != QProcess::NormalExit ||
- proc.exitCode() != 0) {
- // output the moc errors:
- fprintf(stderr, "%s", proc.readAllStandardError().constData());
- fprintf(stderr, PROGRAMNAME ": exit code %d from moc. Aborting\n", proc.exitCode());
- return 1;
- }
- fprintf(stderr, "%s", proc.readAllStandardError().constData());
-
- parser.parse(argv[i], &proc, 1);
- }
+ if (moc.classList.isEmpty())
+ return 0;
+ classes = moc.classList;
f.close();
}
@@ -434,9 +446,8 @@ int main(int argc, char **argv)
output.write(docTypeHeader);
output.write("<node>\n");
- foreach (QMetaObject mo, parser.objects) {
- QString xml = qDBusGenerateMetaObjectXml(QString(), &mo, &QObject::staticMetaObject,
- flags);
+ foreach (const ClassDef &cdef, classes) {
+ QString xml = qDBusGenerateClassDefXml(&cdef);
output.write(xml.toLocal8Bit());
}
output.write("</node>\n");
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro b/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
index 4f5f826ce7..33f7937c5b 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
@@ -1,10 +1,34 @@
-SOURCES = qdbuscpp2xml.cpp
-DESTDIR = $$QT.designer.bins
+
+TEMPLATE = app
TARGET = qdbuscpp2xml
-QT = core
-CONFIG += qdbus
-CONFIG -= app_bundle
-win32:CONFIG += console
-target.path=$$[QT_INSTALL_BINS]
+DESTDIR = ../../../bin
+
+include(../moc/moc.pri)
+
+INCLUDEPATH += .
+DEPENDPATH += .
+
+INCLUDEPATH += $$QT_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtDBus \
+ $$QT_BUILD_TREE/include/QtDBus/$$QT.dbus.VERSION \
+ $$QT_BUILD_TREE/include/QtDBus/$$QT.dbus.VERSION/QtDBus \
+ $$QT_SOURCE_TREE/src/dbus
+
+QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS
+
+SOURCES += qdbuscpp2xml.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusmetatype.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusutil.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusmisc.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusargument.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusmarshaller.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusextratypes.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbus_symbols.cpp \
+ $$QT_SOURCE_TREE/src/dbus/qdbusunixfiledescriptor.cpp
+
+include(../bootstrap/bootstrap.pri)
+
+target.path = $$[QT_HOST_BINS]
INSTALLS += target
+load(qt_targets)
diff --git a/src/tools/tools.pro b/src/tools/tools.pro
index 23666bd4ef..8ad30a998d 100644
--- a/src/tools/tools.pro
+++ b/src/tools/tools.pro
@@ -1,7 +1,7 @@
TEMPLATE = subdirs
TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_qdoc
-contains(QT_CONFIG, dbus): TOOLS_SUBDIRS += src_tools_qdbusxml2cpp
+contains(QT_CONFIG, dbus): TOOLS_SUBDIRS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
!contains(QT_CONFIG, no-gui): TOOLS_SUBDIRS += src_tools_uic
# Set subdir and respective target name
src_tools_bootstrap.subdir = $$PWD/bootstrap
@@ -17,6 +17,8 @@ src_tools_qdoc.target = sub-qdoc
contains(QT_CONFIG, dbus) {
src_tools_qdbusxml2cpp.subdir = $$QT_SOURCE_TREE/src/tools/qdbusxml2cpp
src_tools_qdbusxml2cpp.target = sub-qdbusxml2cpp
+ src_tools_qdbuscpp2xml.subdir = $$QT_SOURCE_TREE/src/tools/qdbuscpp2xml
+ src_tools_qdbuscpp2xml.target = sub-qdbuscpp2xml
}
!wince*:!ordered {
@@ -27,6 +29,7 @@ contains(QT_CONFIG, dbus) {
src_tools_qdoc.depends = src_tools_bootstrap
contains(QT_CONFIG, dbus) {
src_tools_qdbusxml2cpp.depends = src_tools_bootstrap
+ src_tools_qdbuscpp2xml.depends = src_tools_bootstrap
}
}
diff --git a/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.pro b/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.pro
new file mode 100644
index 0000000000..4217d5e73c
--- /dev/null
+++ b/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+QT = core testlib dbus
+TARGET = tst_qdbuscpp2xml
+
+QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS
+
+SOURCES += tst_qdbuscpp2xml.cpp \
+
+RESOURCES += qdbuscpp2xml.qrc
+
+HEADERS += test1.h \ No newline at end of file
diff --git a/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.qrc b/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.qrc
new file mode 100644
index 0000000000..b4cffb842e
--- /dev/null
+++ b/tests/auto/tools/qdbuscpp2xml/qdbuscpp2xml.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/tst_qdbuscpp2xml/">
+ <file>test1.h</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/tools/qdbuscpp2xml/test1.h b/tests/auto/tools/qdbuscpp2xml/test1.h
new file mode 100644
index 0000000000..35dee2cc38
--- /dev/null
+++ b/tests/auto/tools/qdbuscpp2xml/test1.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSCPP2XML_TEST1_H
+#define QDBUSCPP2XML_TEST1_H
+
+#include <QObject>
+
+class QDBusObjectPath;
+class QDBusUnixFileDescriptor;
+class QDBusSignature;
+
+class Test1 : public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.qtProject.qdbuscpp2xmlTests.Test1")
+ Q_PROPERTY(int numProperty1 READ numProperty1 CONSTANT)
+ Q_PROPERTY(int numProperty2 READ numProperty2 WRITE setNumProperty2)
+public:
+ Test1(QObject *parent = 0) : QObject(parent) {}
+
+ int numProperty1() { return 42; }
+
+ int numProperty2() { return 42; }
+ void setNumProperty2(int) {}
+
+signals:
+ void signalVoidType();
+ int signalIntType();
+ void signal_primitive_args(int a1, bool a2, short a3, ushort a4, uint a5, qlonglong a6, double a7, qlonglong a8 = 0);
+ void signal_string_args(const QByteArray &ba, const QString &a2);
+ void signal_Qt_args1(const QDate &a1, const QTime &a2, const QDateTime &a3,
+ const QRect &a4, const QRectF &a5, const QSize &a6, const QSizeF &a7);
+ void signal_Qt_args2(const QPoint &a1, const QPointF &a2, const QLine &a3, const QLineF &a4,
+ const QVariantList &a5, const QVariantMap &a6, const QVariantHash &a7);
+
+ void signal_QDBus_args(const QDBusObjectPath &a1, const QDBusSignature &a2, const QDBusUnixFileDescriptor &a3);
+
+ void signal_container_args1(const QList<bool> &a1, const QList<short> &a2, const QList<ushort> &a3, const QList<int> &a4, const QList<uint> &a5);
+ void signal_container_args2(const QList<qlonglong> &a1, const QList<qulonglong> &a2, const QList<double> &a3, const QList<QDBusObjectPath> &a4, const QList<QDBusSignature> &a5, const QList<QDBusUnixFileDescriptor> &a6);
+
+ Q_SCRIPTABLE void signalVoidType_scriptable();
+ Q_SCRIPTABLE int signalIntType_scriptable();
+ Q_SCRIPTABLE void signal_primitive_args_scriptable(int a1, bool a2, short a3, ushort a4, uint a5, qlonglong a6, double a7, qlonglong a8 = 0);
+ Q_SCRIPTABLE void signal_string_args_scriptable(const QByteArray &ba, const QString &a2);
+ Q_SCRIPTABLE void signal_Qt_args1_scriptable(const QDate &a1, const QTime &a2, const QDateTime &a3,
+ const QRect &a4, const QRectF &a5, const QSize &a6, const QSizeF &a7);
+ Q_SCRIPTABLE void signal_Qt_args2_scriptable(const QPoint &a1, const QPointF &a2, const QLine &a3, const QLineF &a4,
+ const QVariantList &a5, const QVariantMap &a6, const QVariantHash &a7);
+
+ Q_SCRIPTABLE void signal_QDBus_args_scriptable(const QDBusObjectPath &a1, const QDBusSignature &a2, const QDBusUnixFileDescriptor &a3);
+
+ Q_SCRIPTABLE void signal_container_args1_scriptable(const QList<bool> &a1, const QList<short> &a2, const QList<ushort> &a3, const QList<int> &a4, const QList<uint> &a5);
+ Q_SCRIPTABLE void signal_container_args2_scriptable(const QList<qlonglong> &a1, const QList<qulonglong> &a2, const QList<double> &a3, const QList<QDBusObjectPath> &a4, const QList<QDBusSignature> &a5, const QList<QDBusUnixFileDescriptor> &a6);
+
+public slots:
+ void slotVoidType() {}
+ int slotIntType() { return 42; }
+
+ Q_SCRIPTABLE void slotVoidType_scriptable() {}
+ Q_SCRIPTABLE int slotIntType_scriptable() { return 42; }
+
+protected slots:
+ void neverExported1() {}
+ int neverExported2() { return 42; }
+
+ Q_SCRIPTABLE void neverExported3() {}
+ Q_SCRIPTABLE int neverExported4() { return 42; }
+
+private slots:
+ void neverExported5() {}
+ int neverExported6() { return 42; }
+
+ Q_SCRIPTABLE void neverExported7() {}
+ Q_SCRIPTABLE int neverExported8() { return 42; }
+
+public:
+ Q_SCRIPTABLE void methodVoidType() {}
+ Q_SCRIPTABLE int methodIntType() { return 42; }
+
+protected:
+ Q_SCRIPTABLE void neverExported9() {}
+ Q_SCRIPTABLE int neverExported10() { return 42; }
+
+private:
+ Q_SCRIPTABLE void neverExported11() {}
+ Q_SCRIPTABLE int neverExported12() { return 42; }
+};
+
+#endif
diff --git a/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp b/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp
new file mode 100644
index 0000000000..5510c656e1
--- /dev/null
+++ b/tests/auto/tools/qdbuscpp2xml/tst_qdbuscpp2xml.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include "test1.h"
+
+#include <QtDBus/QDBusConnection>
+
+// in qdbusxmlgenerator.cpp
+QT_BEGIN_NAMESPACE
+extern Q_DBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface,
+ const QMetaObject *mo,
+ const QMetaObject *base,
+ int flags);
+QT_END_NAMESPACE
+
+static QString addXmlHeader(const QString &input)
+{
+ return
+ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n<node>"
+ + (input.isEmpty() ? QString() : QString("\n " + input.trimmed()))
+ + "\n</node>\n";
+}
+
+class tst_qdbuscpp2xml : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void qdbuscpp2xml_data();
+ void qdbuscpp2xml();
+
+ void initTestCase();
+ void cleanupTestCase();
+
+private:
+ QHash<QString, QObject*> m_tests;
+};
+
+void tst_qdbuscpp2xml::initTestCase()
+{
+ m_tests.insert("test1", new Test1);
+}
+
+void tst_qdbuscpp2xml::cleanupTestCase()
+{
+ qDeleteAll(m_tests);
+}
+
+void tst_qdbuscpp2xml::qdbuscpp2xml_data()
+{
+ QTest::addColumn<QString>("inputfile");
+ QTest::addColumn<int>("flags");
+
+ QBitArray doneFlags(QDBusConnection::ExportAllContents + 1);
+ for (int flag = 0x10; flag < QDBusConnection::ExportScriptableContents; flag += 0x10) {
+ QTest::newRow("xmlgenerator-" + QByteArray::number(flag)) << "test1" << flag;
+ doneFlags.setBit(flag);
+ for (int mask = QDBusConnection::ExportAllSlots; mask <= QDBusConnection::ExportAllContents; mask += 0x110) {
+ int flags = flag | mask;
+ if (doneFlags.testBit(flags))
+ continue;
+ QTest::newRow("xmlgenerator-" + QByteArray::number(flags)) << "test1" << flags;
+ doneFlags.setBit(flags);
+ }
+ }
+}
+
+void tst_qdbuscpp2xml::qdbuscpp2xml()
+{
+ QFETCH(QString, inputfile);
+ QFETCH(int, flags);
+
+ // qdbuscpp2xml considers these equivalent
+ if (flags & QDBusConnection::ExportScriptableSlots)
+ flags |= QDBusConnection::ExportScriptableInvokables;
+ if (flags & QDBusConnection::ExportNonScriptableSlots)
+ flags |= QDBusConnection::ExportNonScriptableInvokables;
+
+ if (flags & QDBusConnection::ExportScriptableInvokables)
+ flags |= QDBusConnection::ExportScriptableSlots;
+ if (flags & QDBusConnection::ExportNonScriptableInvokables)
+ flags |= QDBusConnection::ExportNonScriptableSlots;
+
+ QStringList options;
+ if (flags & QDBusConnection::ExportScriptableProperties) {
+ if (flags & QDBusConnection::ExportNonScriptableProperties)
+ options << "-P";
+ else
+ options << "-p";
+ }
+ if (flags & QDBusConnection::ExportScriptableSignals) {
+ if (flags & QDBusConnection::ExportNonScriptableSignals)
+ options << "-S";
+ else
+ options << "-s";
+ }
+ if (flags & QDBusConnection::ExportScriptableSlots) {
+ if (flags & QDBusConnection::ExportNonScriptableSlots)
+ options << "-M";
+ else
+ options << "-m";
+ }
+
+ // Launch
+ const QString command = QLatin1String("qdbuscpp2xml");
+ QProcess process;
+ process.start(command, QStringList() << options << (QFINDTESTDATA(inputfile + QStringLiteral(".h"))));
+ if (!process.waitForFinished()) {
+ const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
+ QString message = QString::fromLatin1("'%1' could not be found when run from '%2'. Path: '%3' ").
+ arg(command, QDir::currentPath(), path);
+ QFAIL(qPrintable(message));
+ }
+ const QChar cr = QLatin1Char('\r');
+ const QString err = QString::fromLocal8Bit(process.readAllStandardError()).remove(cr);
+ const QString out = QString::fromAscii(process.readAllStandardOutput()).remove(cr);
+
+ if (!err.isEmpty()) {
+ qDebug() << "UNEXPECTED STDERR CONTENTS: " << err;
+ QFAIL("UNEXPECTED STDERR CONTENTS");
+ }
+
+ const QChar nl = QLatin1Char('\n');
+ const QStringList actualLines = out.split(nl);
+
+ QObject *testObject = m_tests.value(inputfile);
+
+ if (flags == 0)
+ flags = QDBusConnection::ExportScriptableContents
+ | QDBusConnection::ExportNonScriptableContents;
+
+ QString expected = qDBusGenerateMetaObjectXml(QString(), testObject->metaObject(), &QObject::staticMetaObject, flags);
+
+ expected = addXmlHeader(expected);
+
+ QCOMPARE(out, expected);
+}
+
+QTEST_APPLESS_MAIN(tst_qdbuscpp2xml)
+
+#include "tst_qdbuscpp2xml.moc"
diff --git a/tests/auto/tools/tools.pro b/tests/auto/tools/tools.pro
index 6bf6ddf64f..0a2821773f 100644
--- a/tests/auto/tools/tools.pro
+++ b/tests/auto/tools/tools.pro
@@ -5,3 +5,4 @@ SUBDIRS=\
moc \
rcc \
+contains(QT_CONFIG, dbus):SUBDIRS += qdbuscpp2xml