dbus/qt Makefile.am, 1.22, 1.23 dbuscpp2xml.cpp, NONE,
1.1 dbusidl2cpp.cpp, 1.4, 1.5 qdbusabstractadaptor.cpp, 1.4,
1.5 qdbusabstractinterface.cpp, 1.4,
1.5 qdbusabstractinterface.h, 1.4, 1.5 qdbusconnection.cpp,
1.7, 1.8 qdbusconnection_p.h, 1.9, 1.10 qdbusintegrator.cpp,
1.11, 1.12 qdbusinterface.cpp, 1.7, 1.8 qdbusinterface.h, 1.5,
1.6 qdbusinternalfilters.cpp, 1.5, 1.6 qdbusmacros.h, 1.5,
1.6 qdbusmetaobject.cpp, 1.2, 1.3 qdbusmisc.cpp, NONE,
1.1 qdbusxmlgenerator.cpp, NONE, 1.1
Thiago J. Macieira
thiago at kemper.freedesktop.org
Mon May 29 11:17:11 PDT 2006
Update of /cvs/dbus/dbus/qt
In directory kemper:/tmp/cvs-serv20573/qt
Modified Files:
Makefile.am dbusidl2cpp.cpp qdbusabstractadaptor.cpp
qdbusabstractinterface.cpp qdbusabstractinterface.h
qdbusconnection.cpp qdbusconnection_p.h qdbusintegrator.cpp
qdbusinterface.cpp qdbusinterface.h qdbusinternalfilters.cpp
qdbusmacros.h qdbusmetaobject.cpp
Added Files:
dbuscpp2xml.cpp qdbusmisc.cpp qdbusxmlgenerator.cpp
Log Message:
* qt/*: Update the QtDBus bindings up to revision 546310 in
Subversion.
This adds the dbuscpp2xml tool, that parses a C++ header and
outputs a D-BUS Introspection XML.
Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/qt/Makefile.am,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- Makefile.am 28 Apr 2006 20:09:17 -0000 1.22
+++ Makefile.am 29 May 2006 18:17:09 -0000 1.23
@@ -41,20 +41,25 @@
qdbusmessage.cpp \
qdbusserver.cpp \
qdbustype.cpp \
- qdbusabstractinterface.cpp \
+ qdbusabstractinterface.cpp \
qdbusinterface.cpp \
qdbusxmlparser.cpp \
qdbusutil.cpp \
qdbusintrospection.cpp \
- qdbusabstractadaptor.cpp \
+ qdbusabstractadaptor.cpp \
qdbusthread.cpp \
- qdbusinternalfilters.cpp \
- qdbusmetaobject.cpp
+ qdbusinternalfilters.cpp \
+ qdbusmetaobject.cpp \
+ qdbusmisc.cpp \
+ qdbusxmlgenerator.cpp
-bin_PROGRAMS = dbusidl2cpp
+bin_PROGRAMS = dbusidl2cpp dbuscpp2xml
dbusidl2cpp_SOURCES = dbusidl2cpp.cpp
dbusidl2cpp_LDFLAGS = -no-undefined
dbusidl2cpp_LDADD = $(DBUS_QT_LIBS) libdbus-qt4-1.la
+dbuscpp2xml_SOURCES = dbuscpp2xml.cpp
+dbuscpp2xml_LDFLAGS = -no-undefined
+dbuscpp2xml_LDADD = $(DBUS_QT_LIBS) libdbus-qt4-1.la
qdbusabstractadaptor.lo: qdbusabstractadaptor.moc qdbusabstractadaptor_p.moc
qdbusabstractinterface.lo: qdbusabstractinterface.moc
@@ -66,6 +71,7 @@
libdbus_qt4_1_la_LIBADD= $(DBUS_QT_LIBS) $(top_builddir)/dbus/libdbus-1.la
libdbus_qt4_1_la_LDFLAGS= -version-info 1:0 -no-undefined
+libdbus_qt4_1_la_CPPFLAGS= -DQDBUS_MAKEDLL
EXTRA_DIST = qt-dbus.qdocconf
--- NEW FILE: dbuscpp2xml.cpp ---
/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at trolltech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <QByteArray>
#include <QString>
#include <QVarLengthArray>
#include <QFile>
#include <QProcess>
#include <QMetaObject>
#include <QList>
#include <QRegExp>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "qdbusconnection.h" // for the Export* flags
#include <dbus/dbus.h> // for the XML DOCTYPE declaration
// in qdbusxmlgenerator.cpp
extern QDBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
const QMetaObject *base, int flags);
#define PROGRAMNAME "dbuscpp2xml"
#define PROGRAMVERSION "0.1"
#define PROGRAMCOPYRIGHT "Copyright (C) 2006 Trolltech AS. All rights reserved."
static const char cmdlineOptions[] = "psmaPSMAo:";
static const char *outputFile;
static int flags;
static const char help[] =
"Usage: " PROGRAMNAME " [options...] [files...]\n"
"Parses the C++ source or header file containing a QObject-derived class and\n"
"produces the D-Bus Introspection XML."
"\n"
"Options:\n"
" -p|-s|-m Only parse scriptable Properties, Signals and Methods (slots)\n"
" -P|-S|-M Parse all Properties, Signals and Methods (slots)\n"
" -a Output all scriptable contents (equivalent to -psm)\n"
" -A Output all contents (equivalent to -PSM)\n"
" -o <filename> Write the output to file <filename>\n"
" -h Show this information\n"
" -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 line;
public:
~MocParser();
void parse(const char *filename, QIODevice *input, int lineNumber = 0);
QList<QMetaObject> objects;
};
void MocParser::parseError()
{
fprintf(stderr, PROGRAMNAME ": error parsing input file '%s' line %d \n", filename, line);
exit(1);
}
QByteArray MocParser::readLine()
{
++line;
return input->readLine();
}
void MocParser::loadIntData(uint *&data)
{
data = 0; // initialise
QVarLengthArray<uint> array;
QRegExp rx("(\\d+|0x[0-9abcdef]+)", Qt::CaseInsensitive);
while (!input->atEnd()) {
QString line = QLatin1String(readLine());
int pos = line.indexOf("//");
if (pos != -1)
line.truncate(pos); // drop comments
if (line == "};\n") {
// end of data
data = new uint[array.count()];
memcpy(data, array.data(), array.count() * sizeof(*data));
return;
}
pos = 0;
while ((pos = rx.indexIn(line, pos)) != -1) {
QString num = rx.cap(1);
if (num.startsWith("0x"))
array.append(num.mid(2).toUInt(0, 16));
else
array.append(num.toUInt());
pos += rx.matchedLength();
}
}
parseError();
}
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("([0-7]+)");
if (octal.indexIn(QLatin1String(line), start) == -1)
parseError();
array.append(char(octal.cap(1).toInt(0, 8)));
}
} else {
array.append(line.at(start));
}
}
parseError();
}
void MocParser::parse(const char *fname, QIODevice *io, int lineNumber)
{
filename = fname;
input = io;
line = lineNumber;
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);
}
}
fname = 0;
input = 0;
}
MocParser::~MocParser()
{
foreach (QMetaObject mo, objects) {
delete const_cast<char *>(mo.d.stringdata);
delete const_cast<uint *>(mo.d.data);
}
}
static void showHelp()
{
printf("%s", help);
exit(0);
}
static void showVersion()
{
printf("%s version %s\n", PROGRAMNAME, PROGRAMVERSION);
printf("D-Bus QObject-to-XML converter\n");
exit(0);
}
static void parseCmdLine(int argc, char **argv)
{
int c;
opterr = true;
while ((c = getopt(argc, argv, cmdlineOptions)) != -1)
switch (c)
{
case 'p':
flags |= QDBusConnection::ExportProperties;
break;
case 's':
flags |= QDBusConnection::ExportSignals;
break;
case 'm':
flags |= QDBusConnection::ExportSlots;
break;
case 'a':
flags |= QDBusConnection::ExportContents;
break;
case 'P':
flags |= QDBusConnection::ExportAllProperties;
break;
case 'S':
flags |= QDBusConnection::ExportAllSignals;
break;
case 'M':
flags |= QDBusConnection::ExportAllSlots;
break;
case 'A':
flags |= QDBusConnection::ExportAllContents;
break;
case 'o':
outputFile = optarg;
break;
case 'h':
showHelp();
break;
case 'V':
showVersion();
break;
case '?':
exit(1);
default:
abort();
}
if (flags == 0)
flags = QDBusConnection::ExportAllContents;
}
int main(int argc, char **argv)
{
MocParser parser;
parseCmdLine(argc, argv);
for (int i = 1; i < argc; ++i) {
FILE *in = fopen(argv[i], "r");
if (in == 0) {
fprintf(stderr, PROGRAMNAME ": could not open '%s': %s\n",
argv[i], strerror(errno));
return 1;
}
QFile f;
f.open(in, QIODevice::ReadOnly);
f.readLine();
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("moc", QStringList() << QFile::encodeName(argv[i]));
if (!proc.waitForStarted()) {
fprintf(stderr, PROGRAMNAME ": could not execute moc! Aborting.\n");
return 1;
}
proc.closeWriteChannel();
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);
}
f.close();
fclose(in);
}
FILE *output = stdout;
if (outputFile != 0) {
output = fopen(outputFile, "w");
if (output == 0) {
fprintf(stderr, PROGRAMNAME ": could not open output file '%s': %s",
outputFile, strerror(errno));
return 1;
}
}
fprintf(output, "%s<node>\n", DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
foreach (QMetaObject mo, parser.objects) {
QString xml = qDBusGenerateMetaObjectXml(QString(), &mo, &QObject::staticMetaObject,
flags);
fprintf(output, "%s", qPrintable(xml));
}
fprintf(output, "</node>\n");
if (output != stdout)
fclose(output);
}
Index: dbusidl2cpp.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/dbusidl2cpp.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- dbusidl2cpp.cpp 2 May 2006 14:00:27 -0000 1.4
+++ dbusidl2cpp.cpp 29 May 2006 18:17:09 -0000 1.5
@@ -375,7 +375,7 @@
retval += "\\\"";
else
retval += data[i];
- retval += "\"\n";
+ retval += "\\n\"\n";
}
return retval;
}
Index: qdbusabstractadaptor.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusabstractadaptor.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- qdbusabstractadaptor.cpp 2 May 2006 14:00:27 -0000 1.4
+++ qdbusabstractadaptor.cpp 29 May 2006 18:17:09 -0000 1.5
@@ -242,12 +242,11 @@
return; // avoid working multiple times if multiple adaptors were added
waitingForPolish = false;
- const QObjectList &objs = children();
+ const QObjectList &objs = parent()->children();
foreach (QObject *obj, objs) {
- Q_ASSERT(qobject_cast<QDBusAbstractAdaptor *>(obj));
-
- QDBusAbstractAdaptor *adaptor = static_cast<QDBusAbstractAdaptor *>(obj);
- addAdaptor(adaptor);
+ QDBusAbstractAdaptor *adaptor = qobject_cast<QDBusAbstractAdaptor *>(obj);
+ if (adaptor)
+ addAdaptor(adaptor);
}
// sort the adaptor list
Index: qdbusabstractinterface.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusabstractinterface.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- qdbusabstractinterface.cpp 2 May 2006 14:00:27 -0000 1.4
+++ qdbusabstractinterface.cpp 29 May 2006 18:17:09 -0000 1.5
@@ -131,6 +131,19 @@
}
/*!
+ Returns true if this is a valid reference to a remote object. It returns false if
+ there was an error during the creation of this interface (for instance, if the remote
+ application does not exist).
+
+ Note: when dealing with remote objects, it is not always possible to determine if it
+ exists when creating a QDBusInterface or QDBusInterfacePtr object.
+*/
+bool QDBusAbstractInterface::isValid() const
+{
+ return d_func()->isValid;
+}
+
+/*!
Returns the connection this interface is assocated with.
*/
QDBusConnection QDBusAbstractInterface::connection() const
Index: qdbusabstractinterface.h
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusabstractinterface.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- qdbusabstractinterface.h 2 May 2006 14:00:27 -0000 1.4
+++ qdbusabstractinterface.h 29 May 2006 18:17:09 -0000 1.5
@@ -51,6 +51,7 @@
public:
virtual ~QDBusAbstractInterface();
+ bool isValid() const;
QDBusConnection connection() const;
Index: qdbusconnection.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusconnection.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- qdbusconnection.cpp 23 Apr 2006 19:04:53 -0000 1.7
+++ qdbusconnection.cpp 29 May 2006 18:17:09 -0000 1.8
@@ -85,6 +85,7 @@
}
}
+QDBUS_EXPORT void qDBusBindToApplication();
void qDBusBindToApplication()
{
manager()->bindToApplication();
@@ -351,12 +352,6 @@
manager()->removeConnection(name);
}
-void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
-{
- DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
- dbus_timeout_handle(timeout);
-}
-
/*!
Sends the \a message over this connection, without waiting for a reply. This is suitable for
errors, signals, and return values as well as calls whose return values are not necessary.
@@ -367,7 +362,7 @@
{
if (!d || !d->connection)
return false;
- return d->send(message);
+ return d->send(message) != 0;
}
/*!
@@ -445,25 +440,21 @@
if (source.isEmpty())
return false;
}
- source += path;
// check the slot
QDBusConnectionPrivate::SignalHook hook;
- if ((hook.midx = QDBusConnectionPrivate::findSlot(receiver, slot + 1, hook.params)) == -1)
- return false;
-
- hook.interface = interface;
- hook.name = name;
+ QString key;
hook.signature = signature;
- hook.obj = receiver;
+ if (!d->prepareHook(hook, key, source, path, interface, name, receiver, slot, 0, false))
+ return false; // don't connect
// avoid duplicating:
QWriteLocker locker(&d->lock);
- QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(source);
- for ( ; it != d->signalHooks.end() && it.key() == source; ++it) {
+ QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(key);
+ for ( ; it != d->signalHooks.end() && it.key() == key; ++it) {
const QDBusConnectionPrivate::SignalHook &entry = it.value();
- if (entry.interface == hook.interface &&
- entry.name == hook.name &&
+ if (entry.sender == hook.sender &&
+ entry.path == hook.path &&
entry.signature == hook.signature &&
entry.obj == hook.obj &&
entry.midx == hook.midx) {
@@ -473,7 +464,7 @@
}
- d->connectSignal(source, hook);
+ d->connectSignal(key, hook);
return true;
}
Index: qdbusconnection_p.h
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusconnection_p.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- qdbusconnection_p.h 29 Apr 2006 12:44:31 -0000 1.9
+++ qdbusconnection_p.h 29 May 2006 18:17:09 -0000 1.10
@@ -85,7 +85,7 @@
struct SignalHook
{
inline SignalHook() : obj(0), midx(-1) { }
- QString interface, name, signature;
+ QString sender, path, signature;
QObject* obj;
int midx;
QList<int> params;
@@ -139,7 +139,7 @@
QString getNameOwner(const QString &service);
- bool send(const QDBusMessage &message) const;
+ int send(const QDBusMessage &message) const;
QDBusMessage sendWithReply(const QDBusMessage &message, int mode);
int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
const char *method);
@@ -150,7 +150,7 @@
void disconnectRelay(const QString &service, const QString &path, const QString &interface,
QDBusAbstractInterface *receiver, const char *signal);
- bool handleSignal(const QString &path, const QDBusMessage &msg);
+ bool handleSignal(const QString &key, const QDBusMessage &msg);
bool handleSignal(const QDBusMessage &msg);
bool handleObjectCall(const QDBusMessage &message);
bool handleError();
@@ -176,6 +176,7 @@
public slots:
// public slots
+ void doDispatch();
void socketRead(int);
void socketWrite(int);
void objectDestroyed(QObject *o);
@@ -210,7 +211,12 @@
// static methods
static int messageMetaType;
static int registerMessageMetaType();
- static int findSlot(QObject *obj, const char *slotName, QList<int>& params);
+ static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<int>& params);
+ static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
+ const QString &service, const QString &path,
+ const QString &interface, const QString &name,
+ QObject *receiver, const char *signal, int minMIdx,
+ bool buildSignature);
static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *);
static void messageResultReceived(DBusPendingCall *, void *);
};
@@ -225,6 +231,7 @@
void reply(const QDBusMessage &msg);
};
+// in qdbusmisc.cpp
extern int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes);
extern int qDBusNameToTypeId(const char *name);
extern bool qDBusCheckAsyncTag(const char *tag);
Index: qdbusintegrator.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusintegrator.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- qdbusintegrator.cpp 6 May 2006 10:37:59 -0000 1.11
+++ qdbusintegrator.cpp 29 May 2006 18:17:09 -0000 1.12
@@ -46,6 +46,9 @@
int QDBusConnectionPrivate::messageMetaType = 0;
+typedef void (*qDBusSpyHook)(const QDBusMessage&);
+static qDBusSpyHook messageSpyHook;
+
struct QDBusPendingCall
{
QPointer<QObject> receiver;
@@ -217,6 +220,12 @@
qDebug("SERVER: GOT A NEW CONNECTION"); // TODO
}
+extern QDBUS_EXPORT void qDBusSetSpyHook(qDBusSpyHook);
+void qDBusSetSpyHook(qDBusSpyHook hook)
+{
+ messageSpyHook = hook;
+}
+
#if USE_OUTSIDE_DISPATCH
# define HANDLED DBUS_HANDLER_RESULT_HANDLED_OUTSIDE_DISPATCH
static DBusHandlerResult qDBusSignalFilterOutside(DBusConnection *connection,
@@ -262,6 +271,11 @@
QDBusMessage amsg = QDBusMessage::fromDBusMessage(message, QDBusConnection(d->name));
qDebug() << "got message:" << amsg;
+ if (messageSpyHook) {
+ qDebug() << "calling the message spy hook";
+ (*messageSpyHook)(amsg);
+ }
+
bool handled = false;
int msgType = dbus_message_get_type(message);
if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) {
@@ -304,26 +318,6 @@
}
}
-bool qDBusCheckAsyncTag(const char *tag)
-{
- if (!tag || !*tag)
- return false;
-
- const char *p = strstr(tag, "async");
- if (p != NULL &&
- (p == tag || *(p-1) == ' ') &&
- (p[5] == '\0' || p[5] == ' '))
- return true;
-
- p = strstr(tag, "Q_ASYNC");
- if (p != NULL &&
- (p == tag || *(p-1) == ' ') &&
- (p[7] == '\0' || p[7] == ' '))
- return true;
-
- return false;
-}
-
static bool typesMatch(int metaId, int variantType)
{
if (metaId == int(variantType))
@@ -351,112 +345,6 @@
return false; // no match
}
-int qDBusNameToTypeId(const char *name)
-{
- int id = static_cast<int>( QVariant::nameToType(name) );
- if (id == QVariant::UserType)
- id = QMetaType::type(name);
-
- switch (id) {
- case QVariant::Bool:
- case QVariant::Int:
- case QVariant::UInt:
- case QVariant::Char:
- case QMetaType::Short:
- case QMetaType::UShort:
- case QMetaType::UChar:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- case QVariant::Double:
- case QVariant::String:
- case QVariant::Date:
- case QVariant::Time:
- case QVariant::DateTime:
- case QVariant::Map:
- case QVariant::StringList:
- case QVariant::ByteArray:
- case QVariant::List:
- return id;
-
- default:
- if (id == QDBusConnectionPrivate::messageMetaType ||
- id == QDBusTypeHelper<QVariant>::id() ||
- id == QDBusTypeHelper<bool>::listId() ||
- id == QDBusTypeHelper<short>::listId() ||
- id == QDBusTypeHelper<ushort>::listId() ||
- id == QDBusTypeHelper<int>::listId() ||
- id == QDBusTypeHelper<qlonglong>::listId() ||
- id == QDBusTypeHelper<qulonglong>::listId() ||
- id == QDBusTypeHelper<double>::listId())
- return id;
-
- return 0; // invalid
- }
-}
-
-// calculates the metatypes for the method
-// the slot must have the parameters in the following form:
-// - zero or more value or const-ref parameters of any kind
-// - zero or one const ref of QDBusMessage
-// - zero or more non-const ref parameters
-// No parameter may be a template.
-// this function returns -1 if the parameters don't match the above form
-// this function returns the number of *input* parameters, including the QDBusMessage one if any
-// this function does not check the return type, so metaTypes[0] is always 0 and always present
-// metaTypes.count() >= retval + 1 in all cases
-//
-// sig must be the normalised signature for the method
-int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
-{
- QList<QByteArray> parameterTypes = mm.parameterTypes();
- metaTypes.clear();
-
- metaTypes.append(0); // return type
- int inputCount = 0;
- bool seenMessage = false;
- foreach (QByteArray type, parameterTypes) {
- if (type.endsWith('*')) {
- qWarning("Could not parse the method '%s'", mm.signature());
- // pointer?
- return -1;
- }
-
- if (type.endsWith('&')) {
- type.truncate(type.length() - 1);
- int id = qDBusNameToTypeId(type);
- if (id == 0) {
- qWarning("Could not parse the method '%s'", mm.signature());
- // invalid type in method parameter list
- return -1;
- }
-
- metaTypes.append( id );
- seenMessage = true; // it cannot appear anymore anyways
- continue;
- }
-
- if (seenMessage) { // && !type.endsWith('&')
- qWarning("Could not parse the method '%s'", mm.signature());
- // non-output parameters after message or after output params
- return -1; // not allowed
- }
-
- int id = qDBusNameToTypeId(type);
- if (id == 0) {
- qWarning("Could not parse the method '%s'", mm.signature());
- // invalid type in method parameter list
- return -1;
- }
- metaTypes.append(id);
- ++inputCount;
-
- if (id == QDBusConnectionPrivate::messageMetaType)
- seenMessage = true;
- }
-
- return inputCount;
-}
-
static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
const QDBusTypeList &types, QList<int>& metaTypes)
{
@@ -681,7 +569,7 @@
QVarLengthArray<void *, 10> params;
params.reserve(metaTypes.count());
- QVarLengthArray<QVariant, 4> auxParameters;
+ QVariantList auxParameters;
// let's create the parameter list
// first one is the return type -- add it below
@@ -879,6 +767,10 @@
void QDBusConnectionPrivate::bindToApplication()
{
// Yay, now that we have an application we are in business
+ Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection",
+ "qDBusBindToApplication called without an application");
+ moveToThread(QCoreApplication::instance()->thread());
+
// Re-add all watchers
WatcherHash oldWatchers = watchers;
watchers.clear();
@@ -887,6 +779,8 @@
it.next();
if (!it.value().read && !it.value().write) {
qDBusAddWatch(it.value().watch, this);
+ } else {
+ watchers.insertMulti(it.key(), it.value());
}
}
@@ -895,6 +789,18 @@
qDBusAddTimeout(pendingTimeouts.takeFirst(), this);
}
+void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
+{
+ DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
+ dbus_timeout_handle(timeout);
+}
+
+void QDBusConnectionPrivate::doDispatch()
+{
+ if (mode == ClientMode)
+ while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
void QDBusConnectionPrivate::socketRead(int fd)
{
QHashIterator<int, QDBusConnectionPrivate::Watcher> it(watchers);
@@ -905,8 +811,8 @@
qDebug("OUT OF MEM");
}
}
- if (mode == ClientMode)
- while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
+
+ doDispatch();
}
void QDBusConnectionPrivate::socketWrite(int fd)
@@ -963,13 +869,12 @@
return tp;
}
-int QDBusConnectionPrivate::findSlot(QObject* obj, const char *slotName, QList<int>& params)
+int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName,
+ QList<int> ¶ms)
{
- Q_ASSERT(slotName);
- QByteArray normalizedName = QMetaObject::normalizedSignature(slotName);
- int midx = obj->metaObject()->indexOfSlot(normalizedName);
+ int midx = obj->metaObject()->indexOfMethod(normalizedName);
if (midx == -1) {
- qWarning("No such slot '%s' while connecting D-Bus", slotName);
+ qWarning("No such slot '%s' while connecting D-Bus", normalizedName.constData());
return -1;
}
@@ -980,6 +885,42 @@
return midx;
}
+bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
+ const QString &service, const QString &path,
+ const QString &interface, const QString &name,
+ QObject *receiver, const char *signal, int minMIdx,
+ bool buildSignature)
+{
+ QByteArray normalizedName = QMetaObject::normalizedSignature(signal + 1);
+ hook.midx = findSlot(receiver, normalizedName, hook.params);
+ if (hook.midx < minMIdx)
+ return false;
+
+ hook.sender = service;
+ hook.path = path;
+ hook.obj = receiver;
+
+ // build the D-Bus signal name and signature
+ QString mname = name;
+ if (mname.isEmpty()) {
+ normalizedName.truncate(normalizedName.indexOf('('));
+ mname = QString::fromUtf8(normalizedName);
+ }
+ key = mname;
+ key.reserve(interface.length() + 1 + mname.length());
+ key += ':';
+ key += interface;
+
+ if (buildSignature) {
+ hook.signature.clear();
+ for (int i = 1; i < hook.params.count(); ++i)
+ if (hook.params.at(i) != messageMetaType)
+ hook.signature += QLatin1String( QDBusType::dbusSignature( QVariant::Type(hook.params.at(i)) ) );
+ }
+
+ return true; // connect to this signal
+}
+
bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node, const QDBusMessage &msg)
{
// object may be null
@@ -987,7 +928,8 @@
if (msg.interface().isEmpty() || msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) {
if (msg.method() == QLatin1String("Introspect") && msg.signature().isEmpty())
qDBusIntrospectObject(node, msg);
- return true;
+ if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE))
+ return true;
}
if (node->obj && (msg.interface().isEmpty() ||
@@ -996,10 +938,9 @@
qDBusPropertyGet(node, msg);
else if (msg.method() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv"))
qDBusPropertySet(node, msg);
- else
- return false;
-
- return true;
+
+ if (msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES))
+ return true;
}
return false;
@@ -1144,19 +1085,17 @@
return false;
}
-bool QDBusConnectionPrivate::handleSignal(const QString &path, const QDBusMessage &msg)
+bool QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage& msg)
{
- QReadLocker locker(&lock);
-
bool result = false;
- SignalHookHash::const_iterator it = signalHooks.find(path);
+ SignalHookHash::const_iterator it = signalHooks.find(key);
//qDebug("looking for: %s", path.toLocal8Bit().constData());
//qDebug() << signalHooks.keys();
- for ( ; it != signalHooks.constEnd() && it.key() == path; ++ it) {
+ for ( ; it != signalHooks.constEnd() && it.key() == key; ++it) {
const SignalHook &hook = it.value();
- if ( !hook.name.isEmpty() && hook.name != msg.name() )
+ if ( !hook.sender.isEmpty() && hook.sender != msg.sender() )
continue;
- if ( !hook.interface.isEmpty() && hook.interface != msg.interface() )
+ if ( !hook.path.isEmpty() && hook.path != msg.path() )
continue;
if ( !hook.signature.isEmpty() && hook.signature != msg.signature() )
continue;
@@ -1171,8 +1110,17 @@
bool QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
{
- // yes, it is a single "|" below...
- return handleSignal(QString(), msg) | handleSignal(msg.sender() + msg.path(), msg);
+ QString key = msg.member();
+ key.reserve(key.length() + 1 + msg.interface().length());
+ key += ':';
+ key += msg.interface();
+
+ QReadLocker locker(&lock);
+ bool result = handleSignal(key, msg); // one try
+
+ key.truncate(msg.member().length() + 1); // keep the ':'
+ result |= handleSignal(key, msg); // second try
+ return result;
}
static dbus_int32_t server_slot = -1;
@@ -1247,6 +1195,9 @@
#endif
//qDebug("base service: %s", service);
+
+ // schedule a dispatch:
+ QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
}
extern "C"{
@@ -1255,6 +1206,7 @@
QDBusConnectionPrivate::messageResultReceived(pending, user_data);
}
}
+
void QDBusConnectionPrivate::messageResultReceived(DBusPendingCall *pending, void *user_data)
{
QDBusPendingCall *call = reinterpret_cast<QDBusPendingCall *>(user_data);
@@ -1284,18 +1236,22 @@
delete call;
}
-bool QDBusConnectionPrivate::send(const QDBusMessage& message) const
+int QDBusConnectionPrivate::send(const QDBusMessage& message) const
{
DBusMessage *msg = message.toDBusMessage();
if (!msg)
- return false;
+ return 0;
dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything
qDebug() << "sending message:" << message;
bool isOk = dbus_connection_send(connection, msg, 0);
+ int serial = 0;
+ if (isOk)
+ serial = dbus_message_get_serial(msg);
+
dbus_message_unref(msg);
- return isOk;
+ return serial;
}
QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
@@ -1306,6 +1262,7 @@
if (!msg)
return QDBusMessage();
+ qDebug() << "sending message:" << message;
DBusMessage *reply = dbus_connection_send_with_reply_and_block(connection, msg,
-1, &error);
handleError();
@@ -1314,7 +1271,12 @@
if (lastError.isValid())
return QDBusMessage::fromError(lastError);
- return QDBusMessage::fromDBusMessage(reply, QDBusConnection(name));
+ QDBusMessage amsg = QDBusMessage::fromDBusMessage(reply, QDBusConnection(name));
+ qDebug() << "got message:" << amsg;
+
+ if (dbus_connection_get_dispatch_status(connection) == DBUS_DISPATCH_DATA_REMAINS)
+ QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
+ return amsg;
} else { // use the event loop
QDBusReplyWaiter waiter;
if (sendWithReplyAsync(message, &waiter, SLOT(reply(const QDBusMessage&))) > 0) {
@@ -1332,14 +1294,21 @@
int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
const char *method)
{
- DBusMessage *msg = message.toDBusMessage();
- if (!msg)
- return 0;
+ if (!receiver || !method || !*method)
+ // would not be able to deliver a reply
+ return send(message);
int slotIdx = -1;
QList<int> metaTypes;
- if (receiver && method && *method)
- slotIdx = findSlot(receiver, method + 1, metaTypes);
+ QByteArray normalizedName = QMetaObject::normalizedSignature(method + 1);
+ slotIdx = findSlot(receiver, normalizedName, metaTypes);
+ if (slotIdx == -1)
+ // would not be able to deliver a reply
+ return send(message);
+
+ DBusMessage *msg = message.toDBusMessage();
+ if (!msg)
+ return 0;
qDebug() << "sending message:" << message;
DBusPendingCall *pending = 0;
@@ -1388,45 +1357,27 @@
{
// this function is called by QDBusAbstractInterface when one of its signals is connected
// we set up a relay from D-Bus into it
-
- // similar to QDBusConnectionPrivate::findSlot! Merge!
- QByteArray normalizedName = QMetaObject::normalizedSignature(signal + 1);
SignalHook hook;
- hook.midx = receiver->metaObject()->indexOfSignal(normalizedName);
- Q_ASSERT(hook.midx != -1); // cannot happen
- if (hook.midx < QDBusAbstractInterface::staticMetaObject.methodCount())
- return; // don't connect to this signal
-
- int inputCount = qDBusParametersForMethod(receiver->metaObject()->method(hook.midx), hook.params);
- if ( inputCount == -1 || inputCount + 1 != hook.params.count() )
- return; // failed to parse or invalid arguments or output arguments
-
- // build the D-Bus signal name and signature
- QString source = service;
- source += path;
- normalizedName.truncate(normalizedName.indexOf('('));
- hook.name = QString::fromUtf8(normalizedName);
- hook.interface = interface;
- hook.obj = receiver;
- for (int i = 1; i <= inputCount; ++i)
- if (hook.params.at(i) != messageMetaType)
- hook.signature += QLatin1String( QDBusType::dbusSignature( QVariant::Type(hook.params.at(i)) ) );
+ QString key;
+ if (!prepareHook(hook, key, service, path, interface, QString(), receiver, signal,
+ QDBusAbstractInterface::staticMetaObject.methodCount(), true))
+ return; // don't connect
// add it to our list:
QWriteLocker locker(&lock);
- SignalHookHash::ConstIterator it = signalHooks.find(source);
+ SignalHookHash::ConstIterator it = signalHooks.find(key);
SignalHookHash::ConstIterator end = signalHooks.end();
- for ( ; it != end && it.key() == source; ++it) {
+ for ( ; it != end && it.key() == key; ++it) {
const SignalHook &entry = it.value();
- if (entry.interface == hook.interface &&
- entry.name == hook.name &&
+ if (entry.sender == hook.sender &&
+ entry.path == hook.path &&
entry.signature == hook.signature &&
entry.obj == hook.obj &&
entry.midx == hook.midx)
return; // already there, no need to re-add
}
- connectSignal(source, hook);
+ connectSignal(key, hook);
}
void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &path,
@@ -1436,38 +1387,20 @@
{
// this function is called by QDBusAbstractInterface when one of its signals is disconnected
// we remove relay from D-Bus into it
-
- // similar to QDBusConnectionPrivate::findSlot! Merge!
- QByteArray normalizedName = QMetaObject::normalizedSignature(signal + 1);
SignalHook hook;
- hook.midx = receiver->metaObject()->indexOfSignal(normalizedName);
- Q_ASSERT(hook.midx != -1); // cannot happen
- if (hook.midx < QDBusAbstractInterface::staticMetaObject.methodCount())
- return; // we won't find it, so don't bother
-
- int inputCount = qDBusParametersForMethod(receiver->metaObject()->method(hook.midx), hook.params);
- if ( inputCount == -1 || inputCount + 1 != hook.params.count() )
- return; // failed to parse or invalid arguments or output arguments
-
- // build the D-Bus signal name and signature
- QString source = service;
- source += path;
- normalizedName.truncate(normalizedName.indexOf('('));
- hook.name = QString::fromUtf8(normalizedName);
- hook.interface = interface;
- hook.obj = receiver;
- for (int i = 1; i <= inputCount; ++i)
- if (hook.params.at(i) != messageMetaType)
- hook.signature += QLatin1String( QDBusType::dbusSignature( QVariant::Type(hook.params.at(i)) ) );
+ QString key;
+ if (!prepareHook(hook, key, service, path, interface, QString(), receiver, signal,
+ QDBusAbstractInterface::staticMetaObject.methodCount(), true))
+ return; // don't connect
// remove it from our list:
QWriteLocker locker(&lock);
- SignalHookHash::Iterator it = signalHooks.find(source);
+ SignalHookHash::Iterator it = signalHooks.find(key);
SignalHookHash::Iterator end = signalHooks.end();
- for ( ; it != end && it.key() == source; ++it) {
+ for ( ; it != end && it.key() == key; ++it) {
const SignalHook &entry = it.value();
- if (entry.interface == hook.interface &&
- entry.name == hook.name &&
+ if (entry.sender == hook.sender &&
+ entry.path == hook.path &&
entry.signature == hook.signature &&
entry.obj == hook.obj &&
entry.midx == hook.midx) {
Index: qdbusinterface.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusinterface.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- qdbusinterface.cpp 2 May 2006 14:00:27 -0000 1.7
+++ qdbusinterface.cpp 29 May 2006 18:17:09 -0000 1.8
@@ -58,19 +58,6 @@
}
/*!
- Returns true if this is a valid reference to a remote object. It returns false if
- there was an error during the creation of this interface (for instance, if the remote
- application does not exist).
-
- Note: when dealing with remote objects, it is not always possible to determine if it
- exists when creating a QDBusInterface or QDBusInterfacePtr object.
-*/
-bool QDBusInterface::isValid() const
-{
- return d_func()->isValid;
-}
-
-/*!
\internal
Overrides QObject::metaObject to return our own copy.
*/
Index: qdbusinterface.h
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusinterface.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- qdbusinterface.h 29 Apr 2006 12:44:31 -0000 1.5
+++ qdbusinterface.h 29 May 2006 18:17:09 -0000 1.6
@@ -35,7 +35,6 @@
public:
~QDBusInterface();
- bool isValid() const;
virtual const QMetaObject *metaObject() const;
virtual void *qt_metacast(const char *);
@@ -43,6 +42,7 @@
private:
Q_DECLARE_PRIVATE(QDBusInterface);
+ Q_DISABLE_COPY(QDBusInterface)
};
struct QDBUS_EXPORT QDBusInterfacePtr
Index: qdbusinternalfilters.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusinternalfilters.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- qdbusinternalfilters.cpp 29 Apr 2006 12:44:31 -0000 1.5
+++ qdbusinternalfilters.cpp 29 May 2006 18:17:09 -0000 1.6
@@ -30,10 +30,15 @@
#include "qdbusabstractadaptor.h"
#include "qdbusabstractadaptor_p.h"
-#include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
+#include "qdbusconnection.h"
#include "qdbusmessage.h"
+#include "qdbustypehelper_p.h"
#include "qdbusutil.h"
+// defined in qdbusxmlgenerator.cpp
+extern QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
+ const QMetaObject *base, int flags);
+
static const char introspectableInterfaceXml[] =
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
" <method name=\"Introspect\">\n"
@@ -55,164 +60,6 @@
" </method>\n"
" </interface>\n";
-// implement the D-Bus org.freedesktop.DBus.Introspectable interface
-// we do that by analysing the metaObject of all the adaptor interfaces
-
-static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
-{
- QString retval;
-
- // start with properties:
- if (flags & QDBusConnection::ExportProperties) {
- for (int i = propOffset; i < mo->propertyCount(); ++i) {
- static const char *accessvalues[] = {0, "read", "write", "readwrite"};
-
- QMetaProperty mp = mo->property(i);
-
- if (!mp.isScriptable() && (flags & QDBusConnection::ExportAllProperties) !=
- QDBusConnection::ExportAllProperties)
- continue;
-
- int access = 0;
- if (mp.isReadable())
- access |= 1;
- if (mp.isWritable())
- access |= 2;
-
- int typeId = qDBusNameToTypeId(mp.typeName());
- if (!typeId)
- continue;
-
- retval += QString(QLatin1String(" <property name=\"%1\" type=\"%2\" access=\"%3\" />\n"))
- .arg(mp.name())
- .arg(QLatin1String( QDBusUtil::typeToSignature( QVariant::Type(typeId) )))
- .arg(QLatin1String( accessvalues[access] ));
- }
- }
-
- // now add methods:
- for (int i = methodOffset; i < mo->methodCount(); ++i) {
- QMetaMethod mm = mo->method(i);
- QByteArray signature = mm.signature();
- int paren = signature.indexOf('(');
-
- bool isSignal;
- if (mm.methodType() == QMetaMethod::Signal)
- // adding a signal
- isSignal = true;
- else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public)
- isSignal = false;
- else
- continue; // neither signal nor public slot
-
- if ((isSignal && !(flags & QDBusConnection::ExportSignals)) ||
- (!isSignal && !(flags & QDBusConnection::ExportSlots)))
- continue;
-
- QString xml = QString(QLatin1String(" <%1 name=\"%2\">\n"))
- .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
- .arg(QLatin1String(signature.left(paren)));
-
- // check the return type first
- int typeId = qDBusNameToTypeId(mm.typeName());
- if (typeId)
- xml += QString(QLatin1String(" <arg type=\"%1\" direction=\"out\"/>\n"))
- .arg(QLatin1String(QDBusUtil::typeToSignature( QVariant::Type(typeId) )));
- else if (*mm.typeName())
- continue; // wasn't a valid type
-
- QList<QByteArray> names = mm.parameterNames();
- QList<int> types;
- int inputCount = qDBusParametersForMethod(mm, types);
- if (inputCount == -1)
- continue; // invalid form
- if (isSignal && inputCount + 1 != types.count())
- continue; // signal with output arguments?
- if (isSignal && types.at(inputCount) == QDBusConnectionPrivate::messageMetaType)
- continue; // signal with QDBusMessage argument?
-
- int j;
- bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
- for (j = 1; j < types.count(); ++j) {
- // input parameter for a slot or output for a signal
- if (types.at(j) == QDBusConnectionPrivate::messageMetaType) {
- isScriptable = true;
- continue;
- }
-
- QString name;
- if (!names.at(j - 1).isEmpty())
- name = QString(QLatin1String("name=\"%1\" ")).arg(QLatin1String(names.at(j - 1)));
-
- bool isOutput = isSignal || j > inputCount;
-
- xml += QString(QLatin1String(" <arg %1type=\"%2\" direction=\"%3\"/>\n"))
- .arg(name)
- .arg(QLatin1String(QDBusUtil::typeToSignature( QVariant::Type(types.at(j)) )))
- .arg(isOutput ? QLatin1String("out") : QLatin1String("in"));
- }
-
- if (!isScriptable) {
- // check if this was added by other means
- if (isSignal && (flags & QDBusConnection::ExportAllSignals) != QDBusConnection::ExportAllSignals)
- continue;
- if (!isSignal && (flags & QDBusConnection::ExportAllSlots) != QDBusConnection::ExportAllSlots)
- continue;
- }
-
- if (qDBusCheckAsyncTag(mm.tag()))
- // add the no-reply annotation
- xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
- " value=\"true\"/>\n");
-
- retval += xml;
- retval += QString(QLatin1String(" </%1>\n"))
- .arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
- }
-
- return retval;
-}
-
-static QString generateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base,
- int flags)
-{
- if (interface.isEmpty()) {
- // generate the interface name from the meta object
- int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
- if (idx >= mo->classInfoOffset()) {
- interface = QLatin1String(mo->classInfo(idx).value());
- } else {
- 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') )) {
- // assume it's Qt
- interface.prepend( QLatin1String("com.trolltech.Qt.") );
- } else if (!QCoreApplication::instance() ||
- QCoreApplication::instance()->applicationName().isEmpty()) {
- interface.prepend( QLatin1String("local.") );
- } else {
- interface.prepend(QLatin1Char('.')).prepend( QCoreApplication::instance()->applicationName() );
- QStringList domainName = QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'));
- foreach (const QString &part, domainName)
- interface.prepend(QLatin1Char('.')).prepend(part);
- }
- }
- }
-
- QString xml;
- int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTROSPECTION);
- if (idx >= mo->classInfoOffset())
- xml = QString::fromUtf8(mo->classInfo(idx).value());
- else
- xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
-
- return QString(QLatin1String(" <interface name=\"%1\">\n%2 </interface>\n"))
- .arg(interface, xml);
-}
-
static QString generateSubObjectXml(QObject *object)
{
QString retval;
@@ -236,7 +83,7 @@
if (node->flags & QDBusConnection::ExportContents) {
const QMetaObject *mo = node->obj->metaObject();
for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
- xml_data += generateMetaObjectXml(QString(), mo, mo->superClass(),
+ xml_data += qDBusGenerateMetaObjectXml(QString(), mo, mo->superClass(),
node->flags);
}
@@ -253,9 +100,9 @@
QString ifaceXml = QDBusAbstractAdaptorPrivate::retrieveIntrospectionXml(it->adaptor);
if (ifaceXml.isEmpty()) {
// add the interface's contents:
- ifaceXml += generateMetaObjectXml(it->interface, it->metaObject,
- &QDBusAbstractAdaptor::staticMetaObject,
- QDBusConnection::ExportAllContents);
+ ifaceXml += qDBusGenerateMetaObjectXml(it->interface, it->metaObject,
+ &QDBusAbstractAdaptor::staticMetaObject,
+ QDBusConnection::ExportAllContents);
QDBusAbstractAdaptorPrivate::saveIntrospectionXml(it->adaptor, ifaceXml);
}
Index: qdbusmacros.h
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusmacros.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- qdbusmacros.h 28 Mar 2006 18:56:08 -0000 1.5
+++ qdbusmacros.h 29 May 2006 18:17:09 -0000 1.6
@@ -37,7 +37,7 @@
# error Sorry, you need a compiler with support for template member functions to compile QtDBus.
#endif
-#if defined(DBUS_COMPILATION) && defined(QDBUS_MAKEDLL)
+#if defined(QDBUS_MAKEDLL)
# define QDBUS_EXPORT Q_DECL_EXPORT
#else
# define QDBUS_EXPORT Q_DECL_IMPORT
@@ -46,8 +46,5 @@
#ifndef Q_MOC_RUN
# define Q_ASYNC
#endif
-#ifndef QT_NO_KEYWORDS
-# define async Q_ASYNC
-#endif
#endif
Index: qdbusmetaobject.cpp
===================================================================
RCS file: /cvs/dbus/dbus/qt/qdbusmetaobject.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- qdbusmetaobject.cpp 23 Apr 2006 19:04:53 -0000 1.2
+++ qdbusmetaobject.cpp 29 May 2006 18:17:09 -0000 1.3
@@ -48,8 +48,8 @@
QByteArray tag;
QByteArray inputSignature;
QByteArray outputSignature;
- QVarLengthArray<int, 6> inputTypes;
- QVarLengthArray<int, 2> outputTypes;
+ QVarLengthArray<int, 4> inputTypes;
+ QVarLengthArray<int, 4> outputTypes;
int flags;
};
@@ -297,7 +297,7 @@
if (className.isEmpty())
className = QLatin1String("QDBusInterface");
- QVarLengthArray<uint> data;
+ QVarLengthArray<int> data;
data.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(data.data());
--- NEW FILE: qdbusmisc.cpp ---
/* qdbusmisc.cpp Miscellaneous routines that didn't fit anywhere else
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at trolltech.com>
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <string.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetaobject.h>
#include "qdbusconnection_p.h"
#include "qdbustypehelper_p.h"
bool qDBusCheckAsyncTag(const char *tag)
{
if (!tag || !*tag)
return false;
const char *p = strstr(tag, "async");
if (p != NULL &&
(p == tag || *(p-1) == ' ') &&
(p[5] == '\0' || p[5] == ' '))
return true;
p = strstr(tag, "Q_ASYNC");
if (p != NULL &&
(p == tag || *(p-1) == ' ') &&
(p[7] == '\0' || p[7] == ' '))
return true;
return false;
}
int qDBusNameToTypeId(const char *name)
{
int id = static_cast<int>( QVariant::nameToType(name) );
if (id == QVariant::UserType)
id = QMetaType::type(name);
switch (id) {
case QVariant::Bool:
case QVariant::Int:
case QVariant::UInt:
case QVariant::Char:
case QMetaType::Short:
case QMetaType::UShort:
case QMetaType::UChar:
case QVariant::LongLong:
case QVariant::ULongLong:
case QVariant::Double:
case QVariant::String:
case QVariant::Date:
case QVariant::Time:
case QVariant::DateTime:
case QVariant::Map:
case QVariant::StringList:
case QVariant::ByteArray:
case QVariant::List:
return id;
default:
if (id == QDBusConnectionPrivate::registerMessageMetaType() ||
id == QDBusTypeHelper<QVariant>::id() ||
id == QDBusTypeHelper<bool>::listId() ||
id == QDBusTypeHelper<short>::listId() ||
id == QDBusTypeHelper<ushort>::listId() ||
id == QDBusTypeHelper<int>::listId() ||
id == QDBusTypeHelper<qlonglong>::listId() ||
id == QDBusTypeHelper<qulonglong>::listId() ||
id == QDBusTypeHelper<double>::listId())
return id;
return 0; // invalid
}
}
// calculates the metatypes for the method
// the slot must have the parameters in the following form:
// - zero or more value or const-ref parameters of any kind
// - zero or one const ref of QDBusMessage
// - zero or more non-const ref parameters
// No parameter may be a template.
// this function returns -1 if the parameters don't match the above form
// this function returns the number of *input* parameters, including the QDBusMessage one if any
// this function does not check the return type, so metaTypes[0] is always 0 and always present
// metaTypes.count() >= retval + 1 in all cases
//
// sig must be the normalised signature for the method
int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
{
QList<QByteArray> parameterTypes = mm.parameterTypes();
metaTypes.clear();
metaTypes.append(0); // return type
int inputCount = 0;
bool seenMessage = false;
foreach (QByteArray type, parameterTypes) {
if (type.endsWith('*')) {
//qWarning("Could not parse the method '%s'", mm.signature());
// pointer?
return -1;
}
if (type.endsWith('&')) {
type.truncate(type.length() - 1);
int id = qDBusNameToTypeId(type);
if (id == 0) {
//qWarning("Could not parse the method '%s'", mm.signature());
// invalid type in method parameter list
return -1;
}
metaTypes.append( id );
seenMessage = true; // it cannot appear anymore anyways
continue;
}
if (seenMessage) { // && !type.endsWith('&')
//qWarning("Could not parse the method '%s'", mm.signature());
// non-output parameters after message or after output params
return -1; // not allowed
}
int id = qDBusNameToTypeId(type);
if (id == 0) {
//qWarning("Could not parse the method '%s'", mm.signature());
// invalid type in method parameter list
return -1;
}
metaTypes.append(id);
++inputCount;
if (id == QDBusConnectionPrivate::registerMessageMetaType())
seenMessage = true;
}
return inputCount;
}
--- NEW FILE: qdbusxmlgenerator.cpp ---
/* -*- mode: C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at trolltech.com>
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qstringlist.h>
#include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
#include "qdbusconnection_p.h" // for the flags
#include "qdbusutil.h"
extern QDBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
const QMetaObject *base, int flags);
// implement the D-Bus org.freedesktop.DBus.Introspectable interface
// we do that by analysing the metaObject of all the adaptor interfaces
static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
{
QString retval;
// start with properties:
if (flags & QDBusConnection::ExportProperties) {
for (int i = propOffset; i < mo->propertyCount(); ++i) {
static const char *accessvalues[] = {0, "read", "write", "readwrite"};
QMetaProperty mp = mo->property(i);
if (!mp.isScriptable() && (flags & QDBusConnection::ExportAllProperties) !=
QDBusConnection::ExportAllProperties)
continue;
int access = 0;
if (mp.isReadable())
access |= 1;
if (mp.isWritable())
access |= 2;
int typeId = qDBusNameToTypeId(mp.typeName());
if (!typeId)
continue;
retval += QString(QLatin1String(" <property name=\"%1\" type=\"%2\" access=\"%3\" />\n"))
.arg(mp.name())
.arg(QLatin1String( QDBusUtil::typeToSignature( QVariant::Type(typeId) )))
.arg(QLatin1String( accessvalues[access] ));
}
}
// now add methods:
for (int i = methodOffset; i < mo->methodCount(); ++i) {
QMetaMethod mm = mo->method(i);
QByteArray signature = mm.signature();
int paren = signature.indexOf('(');
bool isSignal;
if (mm.methodType() == QMetaMethod::Signal)
// adding a signal
isSignal = true;
else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public)
isSignal = false;
else
continue; // neither signal nor public slot
if ((isSignal && !(flags & QDBusConnection::ExportSignals)) ||
(!isSignal && !(flags & QDBusConnection::ExportSlots)))
continue;
QString xml = QString(QLatin1String(" <%1 name=\"%2\">\n"))
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
.arg(QLatin1String(signature.left(paren)));
// check the return type first
int typeId = qDBusNameToTypeId(mm.typeName());
if (typeId)
xml += QString(QLatin1String(" <arg type=\"%1\" direction=\"out\"/>\n"))
.arg(QLatin1String(QDBusUtil::typeToSignature( QVariant::Type(typeId) )));
else if (*mm.typeName())
continue; // wasn't a valid type
QList<QByteArray> names = mm.parameterNames();
QList<int> types;
int inputCount = qDBusParametersForMethod(mm, types);
if (inputCount == -1)
continue; // invalid form
if (isSignal && inputCount + 1 != types.count())
continue; // signal with output arguments?
if (isSignal && types.at(inputCount) == QDBusConnectionPrivate::messageMetaType)
continue; // signal with QDBusMessage argument?
int j;
bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
for (j = 1; j < types.count(); ++j) {
// input parameter for a slot or output for a signal
if (types.at(j) == QDBusConnectionPrivate::messageMetaType) {
isScriptable = true;
continue;
}
QString name;
if (!names.at(j - 1).isEmpty())
name = QString(QLatin1String("name=\"%1\" ")).arg(QLatin1String(names.at(j - 1)));
bool isOutput = isSignal || j > inputCount;
xml += QString(QLatin1String(" <arg %1type=\"%2\" direction=\"%3\"/>\n"))
.arg(name)
.arg(QLatin1String(QDBusUtil::typeToSignature( QVariant::Type(types.at(j)) )))
.arg(isOutput ? QLatin1String("out") : QLatin1String("in"));
}
if (!isScriptable) {
// check if this was added by other means
if (isSignal && (flags & QDBusConnection::ExportAllSignals) != QDBusConnection::ExportAllSignals)
continue;
if (!isSignal && (flags & QDBusConnection::ExportAllSlots) != QDBusConnection::ExportAllSlots)
continue;
}
if (qDBusCheckAsyncTag(mm.tag()))
// add the no-reply annotation
xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
" value=\"true\"/>\n");
retval += xml;
retval += QString(QLatin1String(" </%1>\n"))
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
}
return retval;
}
QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base,
int flags)
{
if (interface.isEmpty()) {
// generate the interface name from the meta object
int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
if (idx >= mo->classInfoOffset()) {
interface = QLatin1String(mo->classInfo(idx).value());
} else {
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') )) {
// assume it's Qt
interface.prepend( QLatin1String("com.trolltech.Qt.") );
} else if (!QCoreApplication::instance() ||
QCoreApplication::instance()->applicationName().isEmpty()) {
interface.prepend( QLatin1String("local.") );
} else {
interface.prepend(QLatin1Char('.')).prepend( QCoreApplication::instance()->applicationName() );
QStringList domainName = QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'));
foreach (const QString &part, domainName)
interface.prepend(QLatin1Char('.')).prepend(part);
}
}
}
QString xml;
int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTROSPECTION);
if (idx >= mo->classInfoOffset())
return QString::fromUtf8(mo->classInfo(idx).value());
else
xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
return QString(QLatin1String(" <interface name=\"%1\">\n%2 </interface>\n"))
.arg(interface, xml);
}
More information about the dbus-commit
mailing list