dbus/qt Makefile.am, 1.9, 1.10 connection.cpp, 1.10, NONE connection.h, 1.10, NONE dbus-qt.h, 1.4, NONE dbus-qthread.cpp, 1.4, NONE integrator.cpp, 1.5, NONE integrator.h, 1.5, NONE message.cpp, 1.12, NONE message.h, 1.8, NONE qdbus.h, NONE, 1.1 qdbusconnection.cpp, NONE, 1.1 qdbusconnection.h, NONE, 1.1 qdbusconnection_p.h, NONE, 1.1 qdbuserror.cpp, NONE, 1.1 qdbuserror.h, NONE, 1.1 qdbusintegrator.cpp, NONE, 1.1 qdbusmacros.h, NONE, 1.1 qdbusmarshall.cpp, NONE, 1.1 qdbusmarshall.h, NONE, 1.1 qdbusmessage.cpp, NONE, 1.1 qdbusmessage.h, NONE, 1.1 qdbusmessage_p.h, NONE, 1.1 qdbusserver.cpp, NONE, 1.1 qdbusserver.h, NONE, 1.1 qdbusvariant.h, NONE, 1.1 server.cpp, 1.3, NONE server.h, 1.3, NONE

Harald Fernengel harry at freedesktop.org
Fri Sep 23 06:08:28 PDT 2005


Update of /cvs/dbus/dbus/qt
In directory gabe:/tmp/cvs-serv20433/qt

Modified Files:
	Makefile.am 
Added Files:
	qdbus.h qdbusconnection.cpp qdbusconnection.h 
	qdbusconnection_p.h qdbuserror.cpp qdbuserror.h 
	qdbusintegrator.cpp qdbusmacros.h qdbusmarshall.cpp 
	qdbusmarshall.h qdbusmessage.cpp qdbusmessage.h 
	qdbusmessage_p.h qdbusserver.cpp qdbusserver.h qdbusvariant.h 
Removed Files:
	connection.cpp connection.h dbus-qt.h dbus-qthread.cpp 
	integrator.cpp integrator.h message.cpp message.h server.cpp 
	server.h 
Log Message:
With the permission of the original authors, removing the non-working and hopelessly unmaintained old Qt D-BUS bindings and adding the ones from KDE's SVN.


Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/qt/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Makefile.am	6 Sep 2005 22:38:54 -0000	1.9
+++ Makefile.am	23 Sep 2005 13:08:26 -0000	1.10
@@ -1,37 +1,50 @@
 if HAVE_QT
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_QT_CXXFLAGS)
+INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_QT_CFLAGS)
 
 dbusincludedir=$(includedir)/dbus-1.0/dbus
 
 lib_LTLIBRARIES=libdbus-qt-1.la
 
-dbusinclude_HEADERS=				\
-	dbus-qt.h message.h connection.h        \
-	server.h
+dbusinclude_HEADERS=	\
+	qdbuserror.h \
+	qdbusmacros.h \
+	qdbusmessage.h \
+	qdbusserver.h \
+	qdbus.h \
+	qdbusmarshall.h \
+	qdbusvariant.h
 
 libdbus_qt_1_la_SOURCES = 			\
-	dbus-qthread.cpp \
-	$(top_srcdir)/qt/message.cpp \
-	$(top_srcdir)/qt/connection.cpp \
-	$(top_srcdir)/qt/integrator.cpp \
-	$(top_srcdir)/qt/server.cpp \
-	$(top_srcdir)/qt/connection.h \
-	$(top_srcdir)/qt/integrator.h \
-	$(top_srcdir)/qt/server.h
+	$(top_srcdir)/qt/qdbusconnection.cpp    \
+	$(top_srcdir)/qt/qdbuserror.cpp         \
+	$(top_srcdir)/qt/qdbusintegrator.cpp    \
+	$(top_srcdir)/qt/qdbusmarshall.cpp      \
+	$(top_srcdir)/qt/qdbusmessage.cpp       \
+	$(top_srcdir)/qt/qdbusserver.cpp        \
+	$(top_srcdir)/qt/qdbusconnection.h      \
+	$(top_srcdir)/qt/qdbuserror.h           \
+	$(top_srcdir)/qt/qdbusmacros.h          \
+	$(top_srcdir)/qt/qdbusmessage.h         \
+	$(top_srcdir)/qt/qdbusserver.h          \
+	$(top_srcdir)/qt/qdbusconnection_p.h    \
+	$(top_srcdir)/qt/qdbus.h                \
+	$(top_srcdir)/qt/qdbusmarshall.h        \
+	$(top_srcdir)/qt/qdbusmessage_p.h       \
+	$(top_srcdir)/qt/qdbusvariant.h
 
 
-$(top_srcdir)/qt/connection.cpp: connection.moc
-$(top_srcdir)/qt/integrator.cpp: integrator.moc
-$(top_srcdir)/qt/server.cpp: server.moc
-$(top_srcdir)/qt/connection.h: connection.moc
-$(top_srcdir)/qt/integrator.h: integrator.moc
-$(top_srcdir)/qt/server.h: server.moc
+$(top_srcdir)/qt/qdbusserver.cpp: qdbusserver.moc
+$(top_srcdir)/qt/qdbusconnection.cpp: qdbusconnection.moc
 
-CLEANFILES=connection.moc integrator.moc server.moc
+CLEANFILES=qdbusserver.moc qdbusconnection.moc
 
 libdbus_qt_1_la_LIBADD= $(DBUS_QT_LIBS) $(top_builddir)/dbus/libdbus-1.la
 libdbus_qt_1_la_LDFLAGS= -version-info 1:0 -no-undefined
 
+# _p.h files are a exception
+qdbusconnection.moc: qdbusconnection_p.h
+	$(QT_MOC) -o qdbusconnection.moc $(top_srcdir)/qt/qdbusconnection_p.h
+
 %.moc: %.h
 	$(QT_MOC) $< > $@
 endif

--- connection.cpp DELETED ---

--- connection.h DELETED ---

--- dbus-qt.h DELETED ---

--- dbus-qthread.cpp DELETED ---

--- integrator.cpp DELETED ---

--- integrator.h DELETED ---

--- message.cpp DELETED ---

--- message.h DELETED ---

--- NEW FILE: qdbus.h ---
/* qdbus.h precompiled header
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUS_H
#define QDBUS_H

#include <QtDBUS/qdbusconnection.h>
#include <QtDBUS/qdbuserror.h>
#include <QtDBUS/qdbusmessage.h>
#include <QtDBUS/qdbusserver.h>

#endif

--- NEW FILE: qdbusconnection.cpp ---
/* qdbusconnection.cpp
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>

#include "qdbusconnection.h"
#include "qdbuserror.h"
#include "qdbusmessage.h"
#include "qdbusconnection_p.h"

QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";

class QDBusConnectionManager
{
public:
    QDBusConnectionManager(): default_connection(0) {}
    ~QDBusConnectionManager();
    void bindToApplication();
    QDBusConnectionPrivate *connection(const QString &name) const;
    void removeConnection(const QString &name);
    void setConnection(const QString &name, QDBusConnectionPrivate *c);

private:
    QDBusConnectionPrivate *default_connection;
    QHash<QString, QDBusConnectionPrivate *> connectionHash;
};

Q_GLOBAL_STATIC(QDBusConnectionManager, manager);

QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
{
    return name == QLatin1String(QDBusConnection::default_connection_name) ?
            default_connection : connectionHash.value(name, 0);
}

void QDBusConnectionManager::removeConnection(const QString &name)
{
    QDBusConnectionPrivate *d = 0;
    if (name == QLatin1String(QDBusConnection::default_connection_name)) {
        d = default_connection;
        default_connection = 0;
    } else {
        d = connectionHash.take(name);
    }
    if (!d->ref.deref())
        delete d;
}

QDBusConnectionManager::~QDBusConnectionManager()
{
    if (default_connection) {
        delete default_connection;
        default_connection = 0;
    }
    for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
         it != connectionHash.constEnd(); ++it) {
             delete it.value();
    }
    connectionHash.clear();
}

void QDBusConnectionManager::bindToApplication()
{
    if (default_connection) {
        default_connection->bindToApplication();
    }
    for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
         it != connectionHash.constEnd(); ++it) {
             (*it)->bindToApplication();
    }
}

void qDBusBindToApplication()
{
    manager()->bindToApplication();
}

void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
{
    if (name == QLatin1String(QDBusConnection::default_connection_name))
        default_connection = c;
    else
        connectionHash[name] = c;
}


QDBusConnection::QDBusConnection(const QString &name)
{
    d = manager()->connection(name);
    if (d)
        d->ref.ref();
}

QDBusConnection::QDBusConnection(const QDBusConnection &other)
{
    d = other.d;
    if (d)
        d->ref.ref();
}

QDBusConnection::~QDBusConnection()
{
    if (d && !d->ref.deref())
        delete d;
}

QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
{
    if (other.d)
        other.d->ref.ref();
    QDBusConnectionPrivate *old = static_cast<QDBusConnectionPrivate *>(
            q_atomic_set_ptr(&d, other.d));
    if (old && !old->ref.deref())
        delete old;

    return *this;
}

QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
{
//    Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
//               "Cannot create connection without a Q[Core]Application instance");

    QDBusConnectionPrivate *d = manager()->connection(name);
    if (d)
        return QDBusConnection(name);

    d = new QDBusConnectionPrivate;
    DBusConnection *c = 0;
    switch (type) {
        case SystemBus:
            c = dbus_bus_get(DBUS_BUS_SYSTEM, &d->error);
            break;
        case SessionBus:
            c = dbus_bus_get(DBUS_BUS_SESSION, &d->error);
            break;
        case ActivationBus:
            c = dbus_bus_get(DBUS_BUS_STARTER, &d->error);
            break;
    }
    d->setConnection(c); //setConnection does the error handling for us

    manager()->setConnection(name, d);

    return QDBusConnection(name);
}

QDBusConnection QDBusConnection::addConnection(const QString &address,
                    const QString &name)
{
//    Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
//               "Cannot create connection without a Q[Core]Application instance");

    QDBusConnectionPrivate *d = manager()->connection(name);
    if (d)
        return QDBusConnection(name);

    d = new QDBusConnectionPrivate;
    // setConnection does the error handling for us
    d->setConnection(dbus_connection_open(address.toUtf8().constData(), &d->error));

    manager()->setConnection(name, d);

    return QDBusConnection(name);
}

void QDBusConnection::closeConnection(const QString &name)
{
    manager()->removeConnection(name);
}

void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
{
    DBusTimeout *timeout = timeouts.value(e->timerId(), 0);
    dbus_timeout_handle(timeout);
}

bool QDBusConnection::send(const QDBusMessage &message) const
{
    if (!d || !d->connection)
        return false;

    DBusMessage *msg = message.toDBusMessage();
    if (!msg)
        return false;

    bool isOk = dbus_connection_send(d->connection, msg, 0);
    dbus_message_unref(msg);
    return isOk;
}

int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
        const char *method) const
{
    if (!d || !d->connection)
        return 0;

    return d->sendWithReplyAsync(message, receiver, method);
}

QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
{
    if (!d || !d->connection)
        return QDBusMessage::fromDBusMessage(0);

    DBusMessage *msg = message.toDBusMessage();
    if (!msg)
        return QDBusMessage::fromDBusMessage(0);
    DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
                                                -1, &d->error);
    d->handleError();
    dbus_message_unref(msg);

    return QDBusMessage::fromDBusMessage(reply);
}

bool QDBusConnection::connect(const QString &path, const QString &interface,
                              const QString &name, QObject *receiver, const char *slot)
{
    if (!receiver || !slot || !d || !d->connection)
        return false;

    QDBusConnectionPrivate::SignalHook hook;

    hook.interface = interface;
    hook.name = name;
    hook.obj = QPointer<QObject>(receiver);
    if (!hook.setSlot(slot + 1))
        return false;

    d->signalHooks.insertMulti(path, hook);
    d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));

    return true;
}

bool QDBusConnection::registerObject(const QString &path, const QString &interface,
                                     QObject *object)
{
    if (!d || !d->connection || !object || path.isEmpty() || interface.isEmpty())
        return false;

    QDBusConnectionPrivate::ObjectHook hook;
    hook.interface = interface;
    hook.obj = object;

    QDBusConnectionPrivate::ObjectHookHash::iterator it = d->objectHooks.find(path);
    while (it != d->objectHooks.end() && it.key() == path) {
        if (it.value().interface == interface) {
            d->objectHooks.erase(it);
            break;
        }
        ++it;
    }

    d->objectHooks.insert(path, hook);

    d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
    qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());

    return true; // todo - check for slots etc.
}

void QDBusConnection::unregisterObject(const QString &path)
{
    if (!d || !d->connection)
        return;

    // TODO - check interfaces
    d->objectHooks.remove(path);
}

bool QDBusConnection::isConnected( ) const
{
    return d && d->connection && dbus_connection_get_is_connected(d->connection);
}

QDBusError QDBusConnection::lastError() const
{
    return d ? d->lastError : QDBusError();
}

QString QDBusConnection::baseService() const
{
    return d && d->connection ?
            QString::fromUtf8(dbus_bus_get_unique_name(d->connection))
            : QString();
}

bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
{
    static const int DBusModes[] = { 0, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT,
        DBUS_NAME_FLAG_REPLACE_EXISTING };
    Q_ASSERT(mode == 0 || mode == DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ||
             mode == DBUS_NAME_FLAG_REPLACE_EXISTING);

    DBusError error;
    dbus_error_init (&error);
    dbus_bus_request_name(d->connection, name.toUtf8(), DBusModes[mode], &error);
    if (dbus_error_is_set (&error)) {
        qDebug("Error %s\n", error.message);
        dbus_error_free (&error);
        return false;
    }
    return true;
}

#include "qdbusconnection.moc"

--- NEW FILE: qdbusconnection.h ---
/* qdbusconnection.h QDBusConnection object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSCONNECTION_H
#define QDBUSCONNECTION_H

#include "qdbusmacros.h"
#include <QtCore/qstring.h>

class QDBusConnectionPrivate;
class QDBusError;
class QDBusMessage;
class QByteArray;
class QObject;

class QDBUS_EXPORT QDBusConnection
{
public:
    enum BusType { SessionBus, SystemBus, ActivationBus };

    QDBusConnection(const QString &name = QLatin1String(default_connection_name));
    QDBusConnection(const QDBusConnection &other);
    ~QDBusConnection();

    QDBusConnection &operator=(const QDBusConnection &other);

    bool isConnected() const;
    QDBusError lastError() const;

    enum NameRequestMode { NoReplace = 0, ProhibitReplace = 1, ReplaceExisting = 2 };
    bool requestName(const QString &name, NameRequestMode mode = NoReplace);

    QString baseService() const;

    bool send(const QDBusMessage &message) const;
    QDBusMessage sendWithReply(const QDBusMessage &message) const;
    int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
                           const char *slot) const;

    bool connect(const QString &path, const QString &interface,
                 const QString &name, QObject *receiver, const char *slot);

    bool registerObject(const QString &path, const QString &interface,
                        QObject *object);
    void unregisterObject(const QString &path);

    static QDBusConnection addConnection(BusType type,
                               const QString &name = QLatin1String(default_connection_name));
    static QDBusConnection addConnection(const QString &address,
                               const QString &name = QLatin1String(default_connection_name));
    static void closeConnection(const QString &name = QLatin1String(default_connection_name));

    QT_STATIC_CONST char *default_connection_name;

private:
    QDBusConnectionPrivate *d;
};

#endif

--- NEW FILE: qdbusconnection_p.h ---
/* qdbusconnection_p.h QDBusConnection private object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

//
//  W A R N I N G
//  -------------
//
// This file is not part of the public API.  This header file may
// change from version to version without notice, or even be
// removed.
//
// We mean it.
//
//

#include <QtCore/qatomic.h>
#include <QtCore/qhash.h>
#include <QtCore/qobject.h>
#include <QtCore/qpointer.h>
#include <QtCore/qvarlengtharray.h>

#include <dbus/dbus.h>

#include "qdbuserror.h"

class QDBusMessage;
class QSocketNotifier;
class QTimerEvent;

typedef struct DBusConnection;
typedef struct DBusServer;

class QDBusConnectionPrivate: public QObject
{
    Q_OBJECT
public:
    QDBusConnectionPrivate(QObject *parent = 0);
    ~QDBusConnectionPrivate();

    void bindToApplication();

    void setConnection(DBusConnection *connection);
    void setServer(DBusServer *server);
    void closeConnection();
    void timerEvent(QTimerEvent *e);

    bool handleSignal(DBusMessage *msg) const;
    bool handleObjectCall(DBusMessage *message) const;
    bool handleError();

public slots:
    void socketRead(int);
    void socketWrite(int);
    void objectDestroyed(QObject *o);

public:
    DBusError error;
    QDBusError lastError;

    enum ConnectionMode { InvalidMode, ServerMode, ClientMode };

    QAtomic ref;
    ConnectionMode mode;
    DBusConnection *connection;
    DBusServer *server;

    static int messageMetaType;
    static int registerMessageMetaType();
    bool handleSignal(const QString &path, const QDBusMessage &msg) const;
    int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
                           const char *method) const;

    struct Watcher
    {
        Watcher(): watch(0), read(0), write(0) {}
        DBusWatch *watch;
        QSocketNotifier *read;
        QSocketNotifier *write;
    };
    typedef QMultiHash<int, Watcher> WatcherHash;
    WatcherHash watchers;

    typedef QHash<int, DBusTimeout *> TimeoutHash;
    TimeoutHash timeouts;

    struct SignalHook
    {
        QString interface, name;
        QPointer<QObject> obj;
        int midx;
        QVarLengthArray<int, 10> params;

        bool setSlot(const char *slotName);
    };

    typedef QMultiHash<QString, SignalHook> SignalHookHash;
    SignalHookHash signalHooks;

    struct ObjectHook
    {
        QString interface;
        QPointer<QObject> obj;
    };
    typedef QMultiHash<QString, ObjectHook> ObjectHookHash;
    ObjectHookHash objectHooks;
    QList<DBusTimeout *> pendingTimeouts;
};

--- NEW FILE: qdbuserror.cpp ---
/* qdbuserror.h QDBusError object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qdbuserror.h"

#include <QtCore/qdebug.h>

#include <dbus/dbus.h>

QDBusError::QDBusError(const DBusError *error)
{
    if (!error || !dbus_error_is_set(error))
        return;

    nm = QString::fromUtf8(error->name);
    msg = QString::fromUtf8(error->message);
}

#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const QDBusError &msg)
{
    dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ")";
    return dbg.space();
}
#endif



--- NEW FILE: qdbuserror.h ---
/* qdbuserror.h QDBusError object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSERROR_H
#define QDBUSERROR_H

#include "qdbusmacros.h"
#include <QtCore/qstring.h>

struct DBusError;

class QDBUS_EXPORT QDBusError
{
public:
    QDBusError(const DBusError *error = 0);

    inline QString name() const { return nm; }
    inline QString message() const { return msg; }
    inline bool isValid() const { return !nm.isNull() && !msg.isNull(); }

private:
    QString nm, msg;
};

#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug, const QDBusError &);
#endif

#endif

--- NEW FILE: qdbusintegrator.cpp ---
/* qdbusintegrator.cpp QDBusConnection private implementation
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <QtCore/qcoreapplication.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qsocketnotifier.h>

#include "qdbusconnection_p.h"
#include "qdbusmessage.h"

int QDBusConnectionPrivate::messageMetaType = 0;

static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
{
    Q_ASSERT(timeout);
    Q_ASSERT(data);

  //  qDebug("addTimeout %d", dbus_timeout_get_interval(timeout));

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);

    if (!dbus_timeout_get_enabled(timeout))
        return true;

    if (!QCoreApplication::instance()) {
        d->pendingTimeouts.append(timeout);
        return true;
    }
    int timerId = d->startTimer(dbus_timeout_get_interval(timeout));
    if (!timerId)
        return false;

    d->timeouts[timerId] = timeout;
    return true;
}

static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data)
{
    Q_ASSERT(timeout);
    Q_ASSERT(data);

  //  qDebug("removeTimeout");

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
    d->pendingTimeouts.removeAll(timeout);

    QDBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin();
    while (it != d->timeouts.end()) {
        if (it.value() == timeout) {
            d->killTimer(it.key());
            it = d->timeouts.erase(it);
        } else {
            ++it;
        }
    }
}

static void qDBusToggleTimeout(DBusTimeout *timeout, void *data)
{
    Q_ASSERT(timeout);
    Q_ASSERT(data);

    qDebug("ToggleTimeout");

    qDBusRemoveTimeout(timeout, data);
    qDBusAddTimeout(timeout, data);
}

static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
{
    Q_ASSERT(watch);
    Q_ASSERT(data);

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);

    int flags = dbus_watch_get_flags(watch);
    int fd = dbus_watch_get_fd(watch);

    QDBusConnectionPrivate::Watcher watcher;
    if (flags & DBUS_WATCH_READABLE) {
        qDebug("addReadWatch %d", fd);
        watcher.watch = watch;
        if (QCoreApplication::instance()) {
            watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d);
            d->connect(watcher.read, SIGNAL(activated(int)), SLOT(socketRead(int)));
        }
    }
    if (flags & DBUS_WATCH_WRITABLE) {
        qDebug("addWriteWatch %d", fd);
        watcher.watch = watch;
        if (QCoreApplication::instance()) {
            watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d);
            d->connect(watcher.write, SIGNAL(activated(int)), SLOT(socketWrite(int)));
        }
    }
    d->watchers.insertMulti(fd, watcher);

    return true;
}

static void qDBusRemoveWatch(DBusWatch *watch, void *data)
{
    Q_ASSERT(watch);
    Q_ASSERT(data);

    qDebug("remove watch");

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
    int fd = dbus_watch_get_fd(watch);

    QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
    while (i != d->watchers.end() && i.key() == fd) {
        if (i.value().watch == watch) {
            delete i.value().read;
            delete i.value().write;
            d->watchers.erase(i);
            return;
        }
        ++i;
    }
}

static void qDBusToggleWatch(DBusWatch *watch, void *data)
{
    Q_ASSERT(watch);
    Q_ASSERT(data);

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
    int fd = dbus_watch_get_fd(watch);

    QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
    while (i != d->watchers.end() && i.key() == fd) {
        if (i.value().watch == watch) {
            bool enabled = dbus_watch_get_enabled(watch);
            int flags = dbus_watch_get_flags(watch);

            qDebug("toggle watch %d to %d (write: %d, read: %d)", dbus_watch_get_fd(watch), enabled, flags & DBUS_WATCH_WRITABLE, flags & DBUS_WATCH_READABLE);

            if (flags & DBUS_WATCH_READABLE && i.value().read)
                i.value().read->setEnabled(enabled);
            if (flags & DBUS_WATCH_WRITABLE && i.value().write)
                i.value().write->setEnabled(enabled);
            return;
        }
        ++i;
    }
}

static void qDBusNewConnection(DBusServer *server, DBusConnection *c, void *data)
{
    Q_ASSERT(data); Q_ASSERT(server); Q_ASSERT(c);

    qDebug("SERVER: GOT A NEW CONNECTION"); // TODO
}

static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection,
                                           DBusMessage *message, void *data)
{
    Q_ASSERT(data);
    Q_UNUSED(connection);

    QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
    if (d->mode == QDBusConnectionPrivate::InvalidMode)
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

    int msgType = dbus_message_get_type(message);
    bool handled = false;

    QDBusMessage amsg = QDBusMessage::fromDBusMessage(message);
    qDebug() << "got message: " << dbus_message_get_type(message) << amsg;

    if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) {
        handled = d->handleSignal(message);
    } else if (msgType == DBUS_MESSAGE_TYPE_METHOD_CALL) {
        handled = d->handleObjectCall(message);
    }

    return handled ? DBUS_HANDLER_RESULT_HANDLED :
            DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static bool qInvokeDBusSlot(const QDBusConnectionPrivate::SignalHook& hook, const QDBusMessage &msg)
{
    int count = msg.count();
    if (!(count == hook.params.count()
        || (count + 1 == hook.params.count()
        && hook.params[count] == QDBusConnectionPrivate::messageMetaType)))
        return false;

    QVarLengthArray<void *, 16> params;
    params.append(0); // return value
    for (int i = 0; i < msg.count(); ++i) {
        const QVariant &v = msg.at(i);
        if (int(v.type()) != hook.params[i]) {
            return false;
        }
        params.append(const_cast<void *>(v.constData()));
    }
    if (count + 1 == hook.params.count())
        params.append(const_cast<QDBusMessage *>(&msg));
    return hook.obj->qt_metacall(QMetaObject::InvokeMetaMethod, hook.midx, params.data()) < 0;
}

static bool qInvokeDBusSlot(QObject *object, int idx, const QDBusMessage &msg)
{
    Q_ASSERT(object);

    const QMetaMethod method = object->metaObject()->method(idx);
    if (!method.signature())
        return false;

    QVarLengthArray<void *> params;
    params.append(0); // ### return type

    QList<QByteArray> parameterTypes = method.parameterTypes();

    // check parameters, the slot should have <= parameters than the message
    // also allow the QDBusMessage itself as last parameter slot
    if ((parameterTypes.count() > msg.count())
       || (parameterTypes.count() + 1 != msg.count())
          && parameterTypes.last() != "QDBusMessage") {
        qWarning("Cannot deliver asynchronous reply to object named '%s' because of parameter "
                 "mismatch. Please check your sendWithReplyAsync() statements.",
                object->objectName().toLocal8Bit().constData());
        return false;
    }

    int i;
    for (i = 0; i < parameterTypes.count(); ++i) {
        const QByteArray param = parameterTypes.at(i);
        if (param == msg.at(i).typeName()) {
            params.append(const_cast<void *>(msg.at(i).constData()));
        } else if (i == parameterTypes.count() - 1 && param == "QDBusMessage") {
            params.append(const_cast<void *>(static_cast<const void *>(&msg)));
        } else {
            qWarning("Parameter mismatch while delivering message, expected '%s', got '%s'",
                     msg.at(i).typeName(), param.constData());
            return false;
        }
    }
    return object->qt_metacall(QMetaObject::InvokeMetaMethod, idx, params.data()) < 0;
}

static bool qInvokeDBusSlot(QObject *object, QDBusMessage *msg)
{
    Q_ASSERT(object);
    Q_ASSERT(msg);

    const QMetaObject *mo = object->metaObject();
    QVarLengthArray<void *> params;
    params.append(0); // ### return type

    /* Try to find a slot with all args and the QDBusMessage */
    QByteArray slotName = msg->name().toUtf8(); // QVarLengthArray?
    slotName.append("(");
    for (int i = 0; i < msg->count(); ++i) {
        slotName.append(msg->at(i).typeName()).append(",");
        params.append(const_cast<void *>(msg->at(i).constData()));
    }
    slotName.append("QDBusMessage)");

    int idx = mo->indexOfSlot(slotName.constData());
    if (idx >= 0) {
        params.append(msg);
        return object->qt_metacall(QMetaObject::InvokeMetaMethod, idx, params.data()) < 0;
    }

    /* Try to find only args, without the QDBusMessage */
    slotName.chop(13);
    slotName[slotName.count() - 1] = ')';

    idx = mo->indexOfSlot(slotName.constData());
    if (idx >= 0 && (mo->method(idx).attributes() & QMetaMethod::Scriptable))
        return object->qt_metacall(QMetaObject::InvokeMetaMethod, idx, params.data()) < 0;

    /* Try to find a slot with only QDBusMessage */
    slotName = msg->name().toUtf8();
    slotName.append("(QDBusMessage)");

    idx = mo->indexOfSlot(slotName.constData());
    if (idx >= 0)
        return QMetaObject::invokeMethod(object, msg->name().toUtf8().constData(),
                                         Q_ARG(QDBusMessage, *msg));

    return false;
}

int QDBusConnectionPrivate::registerMessageMetaType()
{
    int tp = messageMetaType = qRegisterMetaType<QDBusMessage>("QDBusMessage");
    return tp;
}

bool QDBusConnectionPrivate::SignalHook::setSlot(const char *slotName)
{
    Q_ASSERT(static_cast<QObject *>(obj)); Q_ASSERT(slotName);

    QByteArray normalizedName = QMetaObject::normalizedSignature(slotName);
    const QMetaObject *mo = obj->metaObject();
    midx = mo->indexOfMethod(normalizedName.constData());
    if (midx < 0)
        return false;

    const QList<QByteArray> ptypes = mo->method(midx).parameterTypes();
    for (int i = 0; i < ptypes.count(); ++i) {
        int t = QVariant::nameToType(ptypes.at(i).constData());
        if (t == QVariant::UserType)
            t = QMetaType::type(ptypes.at(i).constData());
        if (t == QVariant::Invalid)
            return false;
        params.append(t);
    }

    return true;
}

QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *parent)
    : QObject(parent), ref(1), mode(InvalidMode), connection(0), server(0)
{
    static const int msgType = registerMessageMetaType();
    Q_UNUSED(msgType);

    dbus_error_init(&error);
}

QDBusConnectionPrivate::~QDBusConnectionPrivate()
{
    if (dbus_error_is_set(&error))
        dbus_error_free(&error);

    closeConnection();
}

void QDBusConnectionPrivate::closeConnection()
{
    ConnectionMode oldMode = mode;
    mode = InvalidMode; // prevent reentrancy
    if (oldMode == ServerMode) {
        if (server) {
            dbus_server_disconnect(server);
            dbus_server_unref(server);
            server = 0;
        }
    } else if (oldMode == ClientMode) {
        if (connection) {
            dbus_connection_close(connection);
            // send the "close" message
            while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS)
                ;
            dbus_connection_unref(connection);
            connection = 0;
        }
    }
}

bool QDBusConnectionPrivate::handleError()
{
    lastError = QDBusError(&error);
    if (dbus_error_is_set(&error))
        dbus_error_free(&error);
    return lastError.isValid();
}

void QDBusConnectionPrivate::bindToApplication()
{
    // Yay, now that we have an application we are in business
    // Re-add all watchers
    WatcherHash oldWatchers = watchers;
    watchers.clear();
    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(oldWatchers);
    while (it.hasNext()) {
        it.next();
        if (!it.value().read && !it.value().write) {
            qDBusAddWatch(it.value().watch, this);
        }
    }

    // Re-add all timeouts
    while (!pendingTimeouts.isEmpty())
       qDBusAddTimeout(pendingTimeouts.takeFirst(), this);
}

void QDBusConnectionPrivate::socketRead(int fd)
{
    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(watchers);
    while (it.hasNext()) {
        it.next();
        if (it.key() == fd && it.value().read && it.value().read->isEnabled()) {
            if (!dbus_watch_handle(it.value().watch, DBUS_WATCH_READABLE))
                qDebug("OUT OF MEM");
        }
    }
    if (mode == ClientMode)
        while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
        // ### break out of loop?
}

void QDBusConnectionPrivate::socketWrite(int fd)
{
    QHashIterator<int, QDBusConnectionPrivate::Watcher> it(watchers);
    while (it.hasNext()) {
        it.next();
        if (it.key() == fd && it.value().write && it.value().write->isEnabled()) {
            if (!dbus_watch_handle(it.value().watch, DBUS_WATCH_WRITABLE))
                qDebug("OUT OF MEM");
        }
    }
}

void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
{
    ObjectHookHash::iterator it = objectHooks.begin();
    while (it != objectHooks.end()) {
        if (static_cast<QObject *>(it.value().obj) == obj)
            it = objectHooks.erase(it);
        else
            ++it;
    }
    SignalHookHash::iterator sit = signalHooks.begin();
    while (sit != signalHooks.end()) {
        if (static_cast<QObject *>(sit.value().obj) == obj)
            sit = signalHooks.erase(sit);
        else
            ++sit;
    }
    obj->disconnect(this);
}

bool QDBusConnectionPrivate::handleObjectCall(DBusMessage *message) const
{
    QDBusMessage msg = QDBusMessage::fromDBusMessage(message);

    ObjectHook hook;
    ObjectHookHash::ConstIterator it = objectHooks.find(msg.path());
    while (it != objectHooks.constEnd() && it.key() == msg.path()) {
        if (it.value().interface == msg.interface()) {
            hook = it.value();
            break;
        } else if (it.value().interface.isEmpty()) {
            hook = it.value();
        }
        ++it;
    }

    if (!hook.obj) {
        qDebug("NO OBJECT for %s", msg.path().toLocal8Bit().constData());
        return false;
    }

    if (!qInvokeDBusSlot(hook.obj, &msg)) {
        qDebug("NO SUCH SLOT: %s(QDBusMessage)", msg.name().toLocal8Bit().constData());
        return false;
    }

    return true;
}

bool QDBusConnectionPrivate::handleSignal(const QString &path, const QDBusMessage &msg) const
{
    SignalHookHash::const_iterator it = signalHooks.find(path);
    qDebug("looking for: %s", path.toLocal8Bit().constData());
    qDebug() << signalHooks.keys();
    while (it != signalHooks.constEnd() && it.key() == path) {
        const SignalHook &hook = it.value();
        if ((hook.name.isEmpty() || hook.name == msg.name())
             && (hook.interface.isEmpty() || hook.interface == msg.interface()))
            qInvokeDBusSlot(hook, msg);
        ++it;
    }
    return true;
}

bool QDBusConnectionPrivate::handleSignal(DBusMessage *message) const
{
    QDBusMessage msg = QDBusMessage::fromDBusMessage(message);

    // yes, it is a single "|" below...
    return handleSignal(QString(), msg) | handleSignal(msg.path(), msg);
}

static dbus_int32_t server_slot = -1;

void QDBusConnectionPrivate::setServer(DBusServer *s)
{
    if (!server) {
        handleError();
        return;
    }

    server = s;
    mode = ServerMode;

    dbus_server_allocate_data_slot(&server_slot);
    if (server_slot < 0)
        return;

    dbus_server_set_watch_functions(server, qDBusAddWatch, qDBusRemoveWatch,
                                    qDBusToggleWatch, this, 0); // ### check return type?
    dbus_server_set_timeout_functions(server, qDBusAddTimeout, qDBusRemoveTimeout,
                                      qDBusToggleTimeout, this, 0);
    dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);

    dbus_server_set_data(server, server_slot, this, 0);
}

void QDBusConnectionPrivate::setConnection(DBusConnection *dbc)
{
    if (!dbc) {
        handleError();
        return;
    }

    connection = dbc;
    mode = ClientMode;

    dbus_connection_set_exit_on_disconnect(connection, false);
    dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
                                        qDBusToggleWatch, this, 0);
    dbus_connection_set_timeout_functions(connection, qDBusAddTimeout, qDBusRemoveTimeout,
                                          qDBusToggleTimeout, this, 0);
//    dbus_bus_add_match(connection, "type='signal',interface='com.trolltech.dbus.Signal'", &error);
//    dbus_bus_add_match(connection, "type='signal'", &error);

    dbus_bus_add_match(connection, "type='signal'", &error);
    if (handleError()) {
        closeConnection();
        return;
    }

    const char *service = dbus_bus_get_unique_name(connection);
    if (service) {
        QVarLengthArray<char, 56> filter;
        filter.append("destination='", 13);
        filter.append(service, qstrlen(service));
        filter.append("\'\0", 2);

        dbus_bus_add_match(connection, filter.constData(), &error);
        if (handleError()) {
            closeConnection();
            return;
        }
    } else {
        qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service");
    }

    dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);

    qDebug("base service: %s", service);
}

struct QDBusPendingCall
{
    QPointer<QObject> receiver;
    int methodIdx;
    DBusPendingCall *pending;
};

static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
{
    QDBusPendingCall *call = reinterpret_cast<QDBusPendingCall *>(user_data);
    Q_ASSERT(call->pending == pending);

    if (!call->receiver.isNull() && call->methodIdx != -1) {
        DBusMessage *reply = dbus_pending_call_steal_reply(pending);
        qInvokeDBusSlot(call->receiver, call->methodIdx, QDBusMessage::fromDBusMessage(reply));
    }
    dbus_pending_call_unref(pending);
    delete call;
}

int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
        const char *method) const
{
    DBusMessage *msg = message.toDBusMessage();
    if (!msg)
        return 0;

    int slotIdx = -1;
    if (receiver && method && *method) {
        QByteArray normalized = QMetaObject::normalizedSignature(method + 1);
        slotIdx = receiver->metaObject()->indexOfMethod(normalized.constData());
        if (slotIdx == -1)
            qWarning("QDBusConnection::sendWithReplyAsync: no such method: '%s'",
                     normalized.constData());
    }

    DBusPendingCall *pending = 0;
    if (dbus_connection_send_with_reply(connection, msg, &pending, message.timeout())) {
        if (slotIdx != -1) {
            QDBusPendingCall *pcall = new QDBusPendingCall;
            pcall->receiver = receiver;
            pcall->methodIdx = slotIdx;
            pcall->pending = dbus_pending_call_ref(pending);
            dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0);
        }
        return dbus_message_get_serial(msg);
    }

    return 0;
}

--- NEW FILE: qdbusmacros.h ---
/* qdbusmessage.h QDBusMessage object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSMACROS_H
#define QDBUSMACROS_H

#include <QtCore/qglobal.h>

#ifdef QDBUS_MAKEDLL
# define QDBUS_EXPORT Q_DECL_EXPORT
#else
# define QDBUS_EXPORT Q_DECL_IMPORT
#endif

#endif

--- NEW FILE: qdbusmarshall.cpp ---
/* qdbusmarshall.cpp
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qdbusmarshall.h"
#include "qdbusvariant.h"

#include <QtCore/qdebug.h>
#include <QtCore/qvariant.h>
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>

#include <dbus/dbus.h>

template <typename T>
inline T qIterGet(DBusMessageIter *it)
{
    T t;
    dbus_message_iter_get_basic(it, &t);
    return t;
}

static QStringList qFetchStringList(DBusMessageIter *arrayIt)
{
    QStringList list;

    DBusMessageIter it;
    dbus_message_iter_recurse(arrayIt, &it);

    do {
        list.append(QString::fromUtf8(qIterGet<char *>(&it)));
    } while (dbus_message_iter_next(&it));

    return list;
}

static QVariant qFetchParameter(DBusMessageIter *it)
{
    switch (dbus_message_iter_get_arg_type(it)) {
    case DBUS_TYPE_BYTE:
        return qIterGet<unsigned char>(it);
    case DBUS_TYPE_INT32:
        return qIterGet<dbus_int32_t>(it);
    case DBUS_TYPE_UINT32:
        return qIterGet<dbus_uint32_t>(it);
    case DBUS_TYPE_DOUBLE:
        return qIterGet<double>(it);
    case DBUS_TYPE_BOOLEAN:
        return qIterGet<dbus_bool_t>(it);
    case DBUS_TYPE_INT64:
        return qIterGet<dbus_int64_t>(it);
    case DBUS_TYPE_UINT64:
        return qIterGet<dbus_uint64_t>(it);
    case DBUS_TYPE_STRING:
    case DBUS_TYPE_OBJECT_PATH:
    case DBUS_TYPE_SIGNATURE:
        return QString::fromUtf8(qIterGet<char *>(it));
    case DBUS_TYPE_ARRAY: {
        int arrayType = dbus_message_iter_get_element_type(it);
        if (arrayType == DBUS_TYPE_STRING || arrayType == DBUS_TYPE_OBJECT_PATH) {
            return qFetchStringList(it);
        } else if (arrayType == DBUS_TYPE_DICT_ENTRY) {
            // ### support other types of maps?
            QMap<QString, QVariant> map;
            DBusMessageIter sub;
            dbus_message_iter_recurse(it, &sub);
            if (!dbus_message_iter_has_next(&sub))
                return map;
            do {
                DBusMessageIter itemIter;
                dbus_message_iter_recurse(&sub, &itemIter);
                Q_ASSERT(dbus_message_iter_has_next(&itemIter));
                QString key = qFetchParameter(&itemIter).toString();
                dbus_message_iter_next(&itemIter);
                map.insertMulti(key, qFetchParameter(&itemIter));
            } while (dbus_message_iter_next(&sub));
            return map;
        } else {
            QList<QVariant> list;
            DBusMessageIter sub;
            dbus_message_iter_recurse(it, &sub);
            if (!dbus_message_iter_has_next(&sub))
                return list;
            do {
                list.append(qFetchParameter(&sub));
            } while (dbus_message_iter_next(&sub));
            return list;
        }
        break; }
    case DBUS_TYPE_VARIANT: {
        QDBusVariant dvariant;
        DBusMessageIter sub;
        dbus_message_iter_recurse(it, &sub);
        dvariant.signature = QString::fromUtf8(dbus_message_iter_get_signature(&sub));
        dvariant.value = qFetchParameter(&sub);
        return qVariantFromValue(dvariant);
    }
#if 0
    case DBUS_TYPE_DICT: {
        QMap<QString, QVariant> map;
        DBusMessageIter sub;
        dbus_message
        if (dbus_message_iter_init_dict_iterator(it, &dictIt)) {
            do {
                map[QString::fromUtf8(dbus_message_iter_get_dict_key(&dictIt))] =
                    qFetchParameter(&dictIt);
            } while (dbus_message_iter_next(&dictIt));
        }
        return map;
        break; }
    case DBUS_TYPE_CUSTOM:
        return qGetCustomValue(it);
        break;
#endif
    default:
        qWarning("Don't know how to handle type %d '%c'", dbus_message_iter_get_arg_type(it), dbus_message_iter_get_arg_type(it));
        return QVariant();
        break;
    }
}

void QDBusMarshall::messageToList(QList<QVariant> &list, DBusMessage *message)
{
    Q_ASSERT(message);

    DBusMessageIter it;
    if (!dbus_message_iter_init(message, &it))
        return;

    do {
        list.append(qFetchParameter(&it));
    } while (dbus_message_iter_next(&it));
}

#define DBUS_APPEND(type,dtype,var) \
type dtype##v=(var); \
dbus_message_append_args(msg, dtype, &dtype##v, DBUS_TYPE_INVALID)
#define DBUS_APPEND_LIST(type,dtype,var,size) \
type dtype##v=(var); \
dbus_message_append_args(msg, DBUS_TYPE_ARRAY, dtype, &dtype##v, size, DBUS_TYPE_INVALID)


static void qAppendToMessage(DBusMessageIter *it, const QString &str)
{
    QByteArray ba = str.toUtf8();
    const char *cdata = ba.constData();
    dbus_message_iter_append_basic(it, DBUS_TYPE_STRING, &cdata);
}

static QVariant::Type qVariantListType(const QList<QVariant> &list)
{
    // TODO - catch lists that have a list as first parameter
    QVariant::Type tp = list.value(0).type();
    if (tp < QVariant::Int || tp > QVariant::Double)
        return QVariant::Invalid;

    for (int i = 1; i < list.count(); ++i) {
        const QVariant &var = list.at(i);
        if (var.type() != tp
               && (var.type() != QVariant::List || qVariantListType(var.toList()) != tp))
            return QVariant::Invalid;
    }
    return tp;
}

static const char *qDBusListType(const QList<QVariant> &list)
{
    static const char *DBusArgs[] = { 0, 0, DBUS_TYPE_INT32_AS_STRING, DBUS_TYPE_UINT32_AS_STRING,
            DBUS_TYPE_INT64_AS_STRING, DBUS_TYPE_UINT64_AS_STRING, DBUS_TYPE_DOUBLE_AS_STRING };

    return DBusArgs[qVariantListType(list)];
}

static void qListToIterator(DBusMessageIter *it, const QList<QVariant> &list);

static void qVariantToIterator(DBusMessageIter *it, const QVariant &var)
{
    static const int Variant2DBus[] = { DBUS_TYPE_INVALID,
        DBUS_TYPE_BOOLEAN, DBUS_TYPE_INT32, DBUS_TYPE_UINT32,
        DBUS_TYPE_INT64, DBUS_TYPE_UINT64, DBUS_TYPE_DOUBLE };

    // these really are static asserts
    Q_ASSERT(QVariant::Invalid == 0);
    Q_ASSERT(QVariant::Int == 2);
    Q_ASSERT(QVariant::Double == 6);

    switch (var.type()) {
    case QVariant::Int:
    case QVariant::UInt:
    case QVariant::LongLong:
    case QVariant::ULongLong:
    case QVariant::Double:
        dbus_message_iter_append_basic(it, Variant2DBus[var.type()],
                var.constData());
        break;
    case QVariant::String:
        qAppendToMessage(it, var.toString());
        break;
    case QVariant::StringList: {
        const QStringList list = var.toStringList();
        DBusMessageIter sub;
        dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY,
                                         DBUS_TYPE_STRING_AS_STRING, &sub);
        for (int s = 0; s < list.count(); ++s)
            qAppendToMessage(&sub, list.at(s));
        dbus_message_iter_close_container(it, &sub);
        break;
    }
    case QVariant::List: {
        const QList<QVariant> &list = var.toList();
        const char *listType = qDBusListType(list);
        if (!listType) {
            qWarning("Don't know how to marshall list.");
            break;
        }
        DBusMessageIter sub;
        dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, listType, &sub);
        qListToIterator(&sub, list);
        dbus_message_iter_close_container(it, &sub);
        break;
    }
    case QVariant::Map: {
        // ### TODO - marshall more than qstring/qstring maps
        const QMap<QString, QVariant> &map = var.toMap();
        DBusMessageIter sub;
        QVarLengthArray<char, 16> sig;
        sig.append(DBUS_DICT_ENTRY_BEGIN_CHAR);
        sig.append(DBUS_TYPE_STRING);
        sig.append(DBUS_TYPE_STRING);
        sig.append(DBUS_DICT_ENTRY_END_CHAR);
        sig.append('\0');
        qDebug() << QString::fromAscii(sig.constData());
        dbus_message_iter_open_container(it, DBUS_TYPE_ARRAY, sig.constData(), &sub);
        for (QMap<QString, QVariant>::const_iterator mit = map.constBegin();
             mit != map.constEnd(); ++mit) {
            DBusMessageIter itemIterator;
            dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, 0, &itemIterator);
            qAppendToMessage(&itemIterator, mit.key());
            qAppendToMessage(&itemIterator, mit.value().toString());
            dbus_message_iter_close_container(&sub, &itemIterator);
        }
        dbus_message_iter_close_container(it, &sub);
        break;
    }
    case QVariant::UserType: {
        if (var.userType() == QMetaTypeId<QDBusVariant>::qt_metatype_id()) {
            DBusMessageIter sub;
            QDBusVariant dvariant = qvariant_cast<QDBusVariant>(var);
            dbus_message_iter_open_container(it, DBUS_TYPE_VARIANT,
                    dvariant.signature.toUtf8().constData(), &sub);
            qVariantToIterator(&sub, dvariant.value);
            dbus_message_iter_close_container(it, &sub);
            break;
        }
    }
    // fall through
    default:
        qWarning("Don't know how to handle type %s", var.typeName());
        break;
    }
}

void qListToIterator(DBusMessageIter *it, const QList<QVariant> &list)
{
    if (list.isEmpty())
        return;

    for (int i = 0; i < list.count(); ++i)
        qVariantToIterator(it, list.at(i));
}

void QDBusMarshall::listToMessage(const QList<QVariant> &list, DBusMessage *msg)
{
    Q_ASSERT(msg);
    DBusMessageIter it;
    dbus_message_iter_init_append(msg, &it);
    qListToIterator(&it, list);
}


--- NEW FILE: qdbusmarshall.h ---
/* qdbusmarshall.h QDBusMarshall object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSMARSHALL_H
#define QDBUSMARSHALL_H

struct DBusMessage;

class QVariant;
template <typename T>
class QList;

class QDBusMarshall
{
public:
    static void listToMessage(const QList<QVariant> &list, DBusMessage *message);
    static void messageToList(QList<QVariant> &list, DBusMessage *message);
};

#endif

--- NEW FILE: qdbusmessage.cpp ---
/* qdbusmessage.cpp
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qdbusmessage.h"

#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>

#include <dbus/dbus.h>

#include "qdbusmarshall.h"
#include "qdbusmessage_p.h"

QDBusMessagePrivate::QDBusMessagePrivate(QDBusMessage *qq)
    : msg(0), reply(0), q(qq), type(DBUS_MESSAGE_TYPE_INVALID), timeout(-1), ref(1)
{
}

QDBusMessagePrivate::~QDBusMessagePrivate()
{
    if (msg)
        dbus_message_unref(msg);
    if (reply)
        dbus_message_unref(reply);
}

///////////////


QDBusMessage QDBusMessage::signal(const QString &path, const QString &interface,
                                  const QString &name)
{
    QDBusMessage message;
    message.d->type = DBUS_MESSAGE_TYPE_SIGNAL;
    message.d->path = path;
    message.d->interface = interface;
    message.d->name = name;

    return message;
}

QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &path,
                                      const QString &interface, const QString &method)
{
    QDBusMessage message;
    message.d->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
    message.d->service = service;
    message.d->path = path;
    message.d->interface = interface;
    message.d->method = method;

    return message;
}

QDBusMessage QDBusMessage::methodReply(const QDBusMessage &other)
{
    Q_ASSERT(other.d->msg);

    QDBusMessage message;
    message.d->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
    message.d->reply = dbus_message_ref(other.d->msg);

    return message;
}

QDBusMessage::QDBusMessage()
{
    d = new QDBusMessagePrivate(this);
}

QDBusMessage::QDBusMessage(const QDBusMessage &other)
    : QList<QVariant>(other)
{
    d = other.d;
    d->ref.ref();
}

QDBusMessage::~QDBusMessage()
{
    if (!d->ref.deref())
        delete d;
}

QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
{
    QList<QVariant>::operator=(other);
    qAtomicAssign(d, other.d);
    return *this;
}

DBusMessage *QDBusMessage::toDBusMessage() const
{
    DBusMessage *msg = 0;
    switch (d->type) {
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
        msg = dbus_message_new_method_call(d->service.toUtf8().constData(),
                d->path.toUtf8().constData(), d->interface.toUtf8().constData(),
                d->method.toUtf8().constData());
        break;
    case DBUS_MESSAGE_TYPE_SIGNAL:
        msg = dbus_message_new_signal(d->path.toUtf8().constData(),
                d->interface.toUtf8().constData(), d->name.toUtf8().constData());
        break;
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
        msg = dbus_message_new_method_return(d->reply);
        break;
    }
    if (!msg)
        return 0;

    QDBusMarshall::listToMessage(*this, msg);
    return msg;
}

QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg)
{
    QDBusMessage message;
    if (!dmsg)
        return message;

    message.d->type = dbus_message_get_type(dmsg);
    message.d->path = QString::fromUtf8(dbus_message_get_path(dmsg));
    message.d->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
    message.d->name = QString::fromUtf8(dbus_message_get_member(dmsg));
    message.d->sender = QString::fromUtf8(dbus_message_get_sender(dmsg));
    message.d->msg = dbus_message_ref(dmsg);

    QDBusMarshall::messageToList(message, dmsg);

    return message;
}

QString QDBusMessage::path() const
{
    return d->path;
}

QString QDBusMessage::interface() const
{
    return d->interface;
}

QString QDBusMessage::name() const
{
    return d->name;
}

QString QDBusMessage::sender() const
{
    return d->sender;
}

int QDBusMessage::timeout() const
{
    return d->timeout;
}

void QDBusMessage::setTimeout(int ms)
{
    d->timeout = ms;
}

/*!
    Returns the unique serial number assigned to this message
    or 0 if the message was not sent yet.
 */
int QDBusMessage::serialNumber() const
{
    if (!d->msg)
        return 0;
    return dbus_message_get_serial(d->msg);
}

/*!
    Returns the unique serial number assigned to the message
    that triggered this reply message.

    If this message is not a reply to another message, 0
    is returned.

 */
int QDBusMessage::replySerialNumber() const
{
    if (!d->msg)
        return 0;
    return dbus_message_get_reply_serial(d->msg);
}

QDBusMessage::MessageType QDBusMessage::type() const
{
    switch (d->type) {
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
        return MethodCallMessage;
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
        return ReplyMessage;
    case DBUS_MESSAGE_TYPE_ERROR:
        return ErrorMessage;
    case DBUS_MESSAGE_TYPE_SIGNAL:
        return SignalMessage;
    default:
        return InvalidMessage;
    }
}

#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
{
    dbg.nospace() << "QDBusMessage(" << msg.path() << ", " << msg.interface() << ", "
                  << msg.name() << ", " << msg.sender() << ", "
                  << static_cast<QList<QVariant> >(msg) << ")";
    return dbg.space();
}
#endif


--- NEW FILE: qdbusmessage.h ---
/* qdbusmessage.h QDBusMessage object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSMESSAGE_H
#define QDBUSMESSAGE_H

#include "qdbusmacros.h"
#include <QtCore/qlist.h>
#include <QtCore/qvariant.h>

#include <limits.h>

class QDBusMessagePrivate;
struct DBusMessage;

class QDBUS_EXPORT QDBusMessage: public QList<QVariant>
{
    friend class QDBusConnection;
public:
    enum { DefaultTimeout = -1, NoTimeout = INT_MAX};
    enum MessageType { InvalidMessage, MethodCallMessage, ReplyMessage,
                       ErrorMessage, SignalMessage };

    QDBusMessage();
    QDBusMessage(const QDBusMessage &other);
    ~QDBusMessage();

    QDBusMessage &operator=(const QDBusMessage &other);

    static QDBusMessage signal(const QString &path, const QString &interface,
                               const QString &name);
    static QDBusMessage methodCall(const QString &service, const QString &path,
                                   const QString &interface, const QString &method);
    static QDBusMessage methodReply(const QDBusMessage &other);

    QString path() const;
    QString interface() const;
    QString name() const; //rename to member?
    QString sender() const; //rename to service?
    MessageType type() const;

    int timeout() const;
    void setTimeout(int ms);


//protected:
    DBusMessage *toDBusMessage() const;
    static QDBusMessage fromDBusMessage(DBusMessage *dmsg);
    int serialNumber() const;
    int replySerialNumber() const;

private:
    QDBusMessagePrivate *d;
};

#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug, const QDBusMessage &);
#endif

#endif


--- NEW FILE: qdbusmessage_p.h ---
/* qdbusmessage.h QDBusMessage private object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSMESSAGE_P_H
#define QDBUSMESSAGE_P_H

#include <QtCore/qatomic.h>
#include <QtCore/qstring.h>

struct DBusMessage;

class QDBusMessagePrivate
{
public:
    QDBusMessagePrivate(QDBusMessage *qq);
    ~QDBusMessagePrivate();

    QString path, interface, name, service, method, sender;
    DBusMessage *msg;
    DBusMessage *reply;
    QDBusMessage *q;
    int type;
    int timeout;
    QAtomic ref;
};

#endif

--- NEW FILE: qdbusserver.cpp ---
/* qdbusserver.cpp
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "qdbusserver.h"
#include "qdbusconnection_p.h"

QDBusServer::QDBusServer(const QString &addr, QObject *parent)
    : QObject(parent)
{
    d = new QDBusConnectionPrivate(this);

    if (addr.isEmpty())
        return;

    d->setServer(dbus_server_listen(addr.toUtf8().constData(), &d->error));
}

bool QDBusServer::isConnected() const
{
    return d->server && dbus_server_get_is_connected(d->server);
}

QDBusError QDBusServer::lastError() const
{
    return d->lastError;
}

QString QDBusServer::address() const
{
    QString addr;
    if (d->server) {
        char *c = dbus_server_get_address(d->server);
        addr = QString::fromUtf8(c);
        dbus_free(c);
    }

    return addr;
}

#include "qdbusserver.moc"

--- NEW FILE: qdbusserver.h ---
/* qdbusserver.h QDBusServer object
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSSERVER_H
#define QDBUSSERVER_H

#include "qdbusmacros.h"
#include <QtCore/qobject.h>
#include <QtCore/qstring.h>

class QDBusConnectionPrivate;
class QDBusError;

class QDBUS_EXPORT QDBusServer: public QObject
{
    Q_OBJECT
public:
    QDBusServer(const QString &address, QObject *parent = 0);

    bool isConnected() const;
    QDBusError lastError() const;
    QString address() const;

private:
    Q_DISABLE_COPY(QDBusServer)
    QDBusConnectionPrivate *d;
};

#endif

--- NEW FILE: qdbusvariant.h ---
/* qdbusvariant.h DBUS variant struct
 *
 * Copyright (C) 2005 Harald Fernengel <harry at kdevelop.org>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef QDBUSVARIANT_H
#define QDBUSVARIANT_H

#include "qdbusmacros.h"

#include <QtCore/qmetatype.h>
#include <QtCore/qstring.h>
#include <QtCore/qvariant.h>

struct QDBUS_EXPORT QDBusVariant
{
    QString signature;
    QVariant value;
};
Q_DECLARE_METATYPE(QDBusVariant)

#endif


--- server.cpp DELETED ---

--- server.h DELETED ---



More information about the dbus-commit mailing list