From d0d0d4afe99aefa78d2371b5a1b216675e924201 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 23 Sep 2005 13:08:26 +0000 Subject: 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. --- configure.in | 53 ++--- qt/Makefile.am | 57 +++-- qt/connection.cpp | 168 ------------- qt/connection.h | 83 ------- qt/dbus-qt.h | 81 ------- qt/dbus-qthread.cpp | 163 ------------- qt/integrator.cpp | 244 ------------------- qt/integrator.h | 92 -------- qt/message.cpp | 561 -------------------------------------------- qt/message.h | 131 ----------- qt/qdbus.h | 31 +++ qt/qdbusconnection.cpp | 328 ++++++++++++++++++++++++++ qt/qdbusconnection.h | 78 +++++++ qt/qdbusconnection_p.h | 126 ++++++++++ qt/qdbuserror.cpp | 46 ++++ qt/qdbuserror.h | 48 ++++ qt/qdbusintegrator.cpp | 621 +++++++++++++++++++++++++++++++++++++++++++++++++ qt/qdbusmacros.h | 34 +++ qt/qdbusmarshall.cpp | 300 ++++++++++++++++++++++++ qt/qdbusmarshall.h | 39 ++++ qt/qdbusmessage.cpp | 233 +++++++++++++++++++ qt/qdbusmessage.h | 80 +++++++ qt/qdbusmessage_p.h | 46 ++++ qt/qdbusserver.cpp | 59 +++++ qt/qdbusserver.h | 48 ++++ qt/qdbusvariant.h | 40 ++++ qt/server.cpp | 90 ------- qt/server.h | 57 ----- 28 files changed, 2207 insertions(+), 1730 deletions(-) delete mode 100644 qt/connection.cpp delete mode 100644 qt/connection.h delete mode 100644 qt/dbus-qt.h delete mode 100644 qt/dbus-qthread.cpp delete mode 100644 qt/integrator.cpp delete mode 100644 qt/integrator.h delete mode 100644 qt/message.cpp delete mode 100644 qt/message.h create mode 100644 qt/qdbus.h create mode 100644 qt/qdbusconnection.cpp create mode 100644 qt/qdbusconnection.h create mode 100644 qt/qdbusconnection_p.h create mode 100644 qt/qdbuserror.cpp create mode 100644 qt/qdbuserror.h create mode 100644 qt/qdbusintegrator.cpp create mode 100644 qt/qdbusmacros.h create mode 100644 qt/qdbusmarshall.cpp create mode 100644 qt/qdbusmarshall.h create mode 100644 qt/qdbusmessage.cpp create mode 100644 qt/qdbusmessage.h create mode 100644 qt/qdbusmessage_p.h create mode 100644 qt/qdbusserver.cpp create mode 100644 qt/qdbusserver.h create mode 100644 qt/qdbusvariant.h delete mode 100644 qt/server.cpp delete mode 100644 qt/server.h diff --git a/configure.in b/configure.in index 1c72af4c..7ffc429e 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ AC_PREREQ(2.52) AC_INIT(dbus/dbus.h) -AM_INIT_AUTOMAKE(dbus, 0.51) +AM_INIT_AUTOMAKE(dbus, 0.37) AM_CONFIG_HEADER(config.h) @@ -859,8 +859,8 @@ AC_SUBST(DBUS_TEST_CFLAGS) AC_SUBST(DBUS_TEST_LIBS) # Glib detection -PKG_CHECK_MODULES(DBUS_GLIB, gobject-2.0 >= 2.4, have_glib=yes, have_glib=no) -PKG_CHECK_MODULES(DBUS_GLIB_THREADS, gthread-2.0 >= 2.4, have_glib_threads=yes, have_glib_threads=no) +PKG_CHECK_MODULES(DBUS_GLIB, gobject-2.0, have_glib=yes, have_glib=no) +PKG_CHECK_MODULES(DBUS_GLIB_THREADS, glib-2.0 gthread-2.0, have_glib_threads=yes, have_glib_threads=no) if test x$have_glib = xno ; then AC_MSG_WARN([GLib development libraries not found]) @@ -927,28 +927,9 @@ AC_SUBST(DBUS_GTK_LIBS) AC_SUBST(DBUS_GTK_THREADS_CFLAGS) AC_SUBST(DBUS_GTK_THREADS_LIBS) -# Qt detection -AC_PATH_PROG(QT_MOC, moc, no) -have_qt=no -AC_MSG_CHECKING([for qglobal.h]) -if test -n "$QTDIR" -a -f "$QTDIR/include/qglobal.h"; then - have_qt=yes - DBUS_QT_CXXFLAGS="-I$QTDIR/include" -else - for dir in "${prefix}/include/qt" "/usr/include/qt-3.1" "/usr/include/qt3" "/usr/include/qt" "/usr/lib/qt/include" "/usr/lib/qt-3.1/include"; do - if test -f "$dir/qglobal.h"; then - have_qt=yes - DBUS_QT_CXXFLAGS="-I$dir" - DBUS_QT_LIBS="-L$QTDIR/lib -lqt-mt" - fi - done -fi -if test x"$have_qt" = x"yes"; then - AC_MSG_RESULT([found]) -else - AC_MSG_RESULT([not found]) -fi +dnl Qt detection +PKG_CHECK_MODULES(DBUS_QT, QtCore >= 4.0, have_qt=yes, have_qt=no) if test x$have_qt = xno ; then AC_MSG_WARN([Qt development libraries not found]) @@ -962,13 +943,17 @@ fi if test x$enable_qt = xno; then have_qt=no; -fi + fi + +QT_MOC=`$PKG_CONFIG --variable=exec_prefix QtCore` +QT_MOC=${QT_MOC}/bin/moc AM_CONDITIONAL(HAVE_QT, test x$have_qt = xyes) dnl Qt flags -AC_SUBST(DBUS_QT_CXXFLAGS) +AC_SUBST(DBUS_QT_CFLAGS) AC_SUBST(DBUS_QT_LIBS) +AC_SUBST(QT_MOC) ### X11 detection AC_PATH_XTRA @@ -1228,21 +1213,13 @@ AC_SUBST(DBUS_SESSION_SOCKET_DIR) if test x$enable_python = xno; then have_python=no else - have_python_version=2.4 AC_MSG_NOTICE([Checking to see if we can build Python bindings]) have_python=no - AM_PATH_PYTHON() + AM_PATH_PYTHON(2.4) if test -z "$PYTHON" ; then AC_MSG_WARN([Python not found]) else - AC_MSG_CHECKING([whether $PYTHON version >= $have_python_version]) - AM_PYTHON_CHECK_VERSION([$PYTHON], [$have_python_version], - [have_python_version="yes"], - [have_python_version="too old"]) - - AC_MSG_RESULT($have_python_version) - AC_CHECK_PROGS(PYREX, pyrexc) if test -z "$PYREX" ; then @@ -1253,16 +1230,16 @@ else AM_CHECK_PYTHON_HEADERS(have_python_headers=yes,have_python_headers=no) - if test x$have_pyrex = xyes -a x$have_python_headers = xyes -a "x$have_python_version" = xyes ; then + if test x$have_pyrex = xyes -a x$have_python_headers = xyes ; then have_python=yes fi fi if test x$have_python = xno ; then if test x$enable_python = xyes ; then - AC_MSG_ERROR([Building python explicitly requested, but can't build python bindings because either Pyrex, Python headers or a suitable Python version was not found]) + AC_MSG_ERROR([Building python explicitly requested, but can't build python bindings]) else - AC_MSG_WARN([Couldn't find either Pyrex, the Python headers or a suitable version of Python, not building Python bindings]) + AC_MSG_WARN([Couldn't find either Pyrex or the Python headers, not building Python bindings]) fi fi fi diff --git a/qt/Makefile.am b/qt/Makefile.am index d375bcf3..71ae3527 100644 --- a/qt/Makefile.am +++ b/qt/Makefile.am @@ -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/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 - -CLEANFILES=connection.moc integrator.moc server.moc + $(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/qdbusserver.cpp: qdbusserver.moc +$(top_srcdir)/qt/qdbusconnection.cpp: qdbusconnection.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 diff --git a/qt/connection.cpp b/qt/connection.cpp deleted file mode 100644 index f426d698..00000000 --- a/qt/connection.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* connection.cpp: Qt wrapper for DBusConnection - * - * Copyright (C) 2003 Zack Rusin - * - * Licensed under the Academic Free License version 2.0 - * - * 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 "connection.h" - -using namespace DBusQt; - -#include "integrator.h" -using Internal::Integrator; - -struct Connection::Private -{ - Private( Connection *qq ); - void setConnection( DBusConnection *c ); - DBusConnection *connection; - int connectionSlot; - DBusError error; - Integrator *integrator; - int timeout; - Connection *q; -}; - -Connection::Private::Private( Connection *qq ) - : connection( 0 ), connectionSlot( 0 ), integrator( 0 ), - timeout( -1 ), q( qq ) -{ - dbus_error_init( &error ); -} - -void Connection::Private::setConnection( DBusConnection *c ) -{ - if (!c) { - qDebug( "error: %s, %s", error.name, error.message ); - dbus_error_free( &error ); - return; - } - connection = c; - integrator = new Integrator( c, q ); - connect( integrator, SIGNAL(readReady()), q, SLOT(dispatchRead()) ); -} - -Connection::Connection( QObject *parent ) - : QObject( parent ) -{ - d = new Private( this ); -} - -Connection::Connection( const QString& host, QObject *parent ) - : QObject( parent ) -{ - d = new Private( this ); - - if ( !host.isEmpty() ) - init( host ); -} - -Connection::Connection( DBusBusType type, QObject* parent ) - : QObject( parent ) -{ - d = new Private( this ); - d->setConnection( dbus_bus_get(type, &d->error) ); -} - -void Connection::init( const QString& host ) -{ - d->setConnection( dbus_connection_open( host.ascii(), &d->error) ); - //dbus_connection_allocate_data_slot( &d->connectionSlot ); - //dbus_connection_set_data( d->connection, d->connectionSlot, 0, 0 ); -} - -bool Connection::isConnected() const -{ - return dbus_connection_get_is_connected( d->connection ); -} - -bool Connection::isAuthenticated() const -{ - return dbus_connection_get_is_authenticated( d->connection ); -} - -void Connection::open( const QString& host ) -{ - if ( host.isEmpty() ) return; - - init( host ); -} - -void Connection::close() -{ - dbus_connection_disconnect( d->connection ); -} - -void Connection::flush() -{ - dbus_connection_flush( d->connection ); -} - -void Connection::dispatchRead() -{ - while ( dbus_connection_dispatch( d->connection ) == DBUS_DISPATCH_DATA_REMAINS ) - ; -} - -DBusConnection* Connection::connection() const -{ - return d->connection; -} - -Connection::Connection( DBusConnection *connection, QObject *parent ) - : QObject( parent ) -{ - d = new Private(this); - d->setConnection(connection); -} - -void Connection::send( const Message &m ) -{ - dbus_connection_send(d->connection, m.message(), 0); -} - -void Connection::sendWithReply( const Message& ) -{ -} - -Message Connection::sendWithReplyAndBlock( const Message &m ) -{ - DBusMessage *reply; - reply = dbus_connection_send_with_reply_and_block( d->connection, m.message(), d->timeout, &d->error ); - if (dbus_error_is_set(&d->error)) { - qDebug("error: %s, %s", d->error.name, d->error.message); - dbus_error_free(&d->error); - } - return Message( reply ); -} - -void* Connection::virtual_hook( int, void* ) -{ -} - -void Connection::dbus_connection_setup_with_qt_main (DBusConnection *connection) -{ - d->setConnection( connection ); -} - - - -///////////////////////////////////////////////////////// - -#include "connection.moc" diff --git a/qt/connection.h b/qt/connection.h deleted file mode 100644 index 7cb922e3..00000000 --- a/qt/connection.h +++ /dev/null @@ -1,83 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* connection.h: Qt wrapper for DBusConnection - * - * Copyright (C) 2003 Zack Rusin - * - * 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 DBUS_QT_CONNECTION_H -#define DBUS_QT_CONNECTION_H - -#include "message.h" - -#include -#include - -#include "dbus/dbus.h" - -namespace DBusQt { - namespace Internal { - class Integrator; - } - - class Connection : public QObject - { - Q_OBJECT - public: - Connection( QObject *parent =0 ); - Connection( const QString& host, - QObject *parent = 0 ); - Connection( DBusBusType type, QObject* parent = 0 ); - - bool isConnected() const; - bool isAuthenticated() const; - - Message borrowMessage(); - Message popMessage(); - void stealBorrowMessage( const Message& ); - void dbus_connection_setup_with_qt_main (DBusConnection *connection); - - public slots: - void open( const QString& ); - void close(); - void flush(); - void send( const Message& ); - void sendWithReply( const Message& ); - Message sendWithReplyAndBlock( const Message& ); - - protected slots: - void dispatchRead(); - - protected: - void init( const QString& host ); - virtual void *virtual_hook( int id, void *data ); - - private: - friend class Internal::Integrator; - DBusConnection *connection() const; - Connection( DBusConnection *connection, QObject *parent ); - - private: - struct Private; - Private *d; - }; - -} - - -#endif diff --git a/qt/dbus-qt.h b/qt/dbus-qt.h deleted file mode 100644 index 179f5355..00000000 --- a/qt/dbus-qt.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* - * dbus-qt.h Qt integration - * - * Copyright (C) 2002 DBus Developers - * - * Licensed under the Academic Free License version 2.1 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - * - */ -#ifndef DBUS_QT_H -#define DBUS_QT_H - -#include -/* - * Two approaches - one presented below a DBusQtConnection - * object which is a Qt wrapper around DBusConnection -class DBusQtConnection : public QObject { - Q_OBJECT -public: - DBusQtConnection( const char *address=0, QObject *parent=0, - const char *name=0 ); - - bool open( const char *address ); - bool isConnected() const; - int numMessages() const; - -public slots: - void disconnect(); - void flush(); - void sendMessage( DBusMessage *message ); - -signals: - void message( DBusMessage* message ); - void error( const char* error ); -private: - DBusConnection *mConnection; - QSocketNotifier *mReadNotifier; - QSocketNotifier *mWriteNotifier; -}; - * - * Second approach is to have a static Qt dispatcher like: -class DBusQtNotifier : public QObject { - Q_OBJECT -public: - static DBusQtNotifier* dbus_qt_notifier(); - void addConnection(DBusConnection* connection); -signals: - void message (DBusConnection* connection, DBusMessage* message); - -private: - DBusQtNotifier(QObject *parent); -private slots: - void processNotifiers( int socket ); -private: - //implemented in terms of QSocketNotifiers - QAsciiDict mReadNotifiers; - QAsciiDict mWriteNotifiers; -}; - * - * First one gives us a full wrapper for DBusConnection (the Qt way), - * the other exposes DBusConnection, so would be easier to maintain - * and keep up while DBus evolves. - * - */ - -#endif /* DBUS_QT_H */ diff --git a/qt/dbus-qthread.cpp b/qt/dbus-qthread.cpp deleted file mode 100644 index 72ccb155..00000000 --- a/qt/dbus-qthread.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-qthread.cpp Qt threads integration - * - * Copyright (C) 2002 Zack Rusin - * - * Licensed under the Academic Free License version 2.0 - * - * 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 -#include - -#if defined(QT_THREAD_SUPPORT) - -static DBusMutex * dbus_qmutex_new (void); -static void dbus_qmutex_free (DBusMutex *mutex); -static dbus_bool_t dbus_qmutex_lock (DBusMutex *mutex); -static dbus_bool_t dbus_qmutex_unlock (DBusMutex *mutex); - -static DBusCondVar*dbus_qcondvar_new (void); -static void dbus_qcondvar_free (DBusCondVar *cond); -static void dbus_qcondvar_wait (DBusCondVar *cond, - DBusMutex *mutex); -static dbus_bool_t dbus_qcondvar_wait_timeout (DBusCondVar *cond, - DBusMutex *mutex. - int timeout_msec); -static void dbus_qcondvar_wake_one (DBusCondVar *cond); -static void dbus_qcondvar_wake_all (DBusCondVar *cond); - - -static const DBusThreadFunctions functions = -{ - DBUS_THREAD_FUNCTIONS_NEW_MASK | - DBUS_THREAD_FUNCTIONS_FREE_MASK | - DBUS_THREAD_FUNCTIONS_LOCK_MASK | - DBUS_THREAD_FUNCTIONS_UNLOCK_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK | - DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK| - DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK, - dbus_qmutex_new, - dbus_qmutex_free, - dbus_qmutex_lock, - dbus_qmutex_unlock - dbus_qcondvar_new, - dbus_qcondvar_free, - dbus_qcondvar_wait, - dbus_qcondvar_wait_timeout, - dbus_qcondvar_wake_one, - dbus_qcondvar_wake_all -}; - -static DBusMutex * -dbus_qmutex_new (void) -{ - QMutex *mutex; - mutex = new QMutex; - return static_cast( mutex ); -} - -static void -dbus_qmutex_free (DBusMutex *mutex) -{ - QMutex * qmutex = static_cast(mutex); - delete mutex; -} - -static dbus_bool_t -dbus_qmutex_lock (DBusMutex *mutex) -{ - QMutex *qmutex = static_cast(mutex); - qmutex->lock(); - return TRUE; -} - -static dbus_bool_t -dbus_qmutex_unlock (DBusMutex *mutex) -{ - QMutex *qmutex = static_cast(mutex); - qmutex->unlock(); - return TRUE; -} - -static DBusCondVar* -dbus_qcondvar_new (void) -{ - QWaitCondition *cond; - cond = new QWaitCondition; - return static_cast( cond ); -} - -static void -dbus_qcondvar_free (DBusCondVar *cond) -{ - QWaitCondition *qcond = static_cast(cond); - delete qcond; -} - -static void -dbus_qcondvar_wait (DBusCondVar *cond, - DBusMutex *mutex) -{ - QWaitCondition *qcond = static_cast(cond); - QMutex *qmutex = static_cast(mutex); - - qcond->wait (qmutex); -} - -static dbus_bool_t -dbus_gcondvar_wait_timeout (DBusCondVar *cond, - DBusMutex *mutex, - int timeout_msec) -{ - QWaitCondition *qcond = static_cast(cond); - QMutex *qmutex = static_cast(mutex); - - return qcond->wait (qmutex, timout_msec); -} - -static void -dbus_qcondvar_wake_one (DBusCondVar *cond) -{ - QWaitCondition *qcond = static_cast(cond); - - qcond->wakeOne (qmutex); -} - -static void -dbus_qcondvar_wake_all (DBusCondVar *cond) -{ - QWaitCondition *qcond = static_cast(cond); - - qcond->wakeAll (qmutex); -} - -extern "C" { - -void -dbus_qthread_init (void) -{ - //Do we want to do anything else here? - dbus_threads_init (&functions); -} - -} - -#endif // QT_THREAD_SUPPORT diff --git a/qt/integrator.cpp b/qt/integrator.cpp deleted file mode 100644 index fff32b39..00000000 --- a/qt/integrator.cpp +++ /dev/null @@ -1,244 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* integrator.h: integrates D-BUS into Qt event loop - * - * Copyright (C) 2003 Zack Rusin - * - * Licensed under the Academic Free License version 2.0 - * - * 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 "integrator.h" -#include "connection.h" - -#include -#include -#include -#include - -namespace DBusQt -{ -namespace Internal { - -struct Watch { - Watch(): readSocket( 0 ), writeSocket( 0 ) { } - - DBusWatch *watch; - QSocketNotifier *readSocket; - QSocketNotifier *writeSocket; -}; - -////////////////////////////////////////////////////////////// -dbus_bool_t dbusAddWatch( DBusWatch *watch, void *data ) -{ - Integrator *con = static_cast( data ); - con->addWatch( watch ); - return true; -} -void dbusRemoveWatch( DBusWatch *watch, void *data ) -{ - Integrator *con = static_cast( data ); - con->removeWatch( watch ); -} - -void dbusToggleWatch( DBusWatch *watch, void *data ) -{ - Integrator *itg = static_cast( data ); - if ( dbus_watch_get_enabled( watch ) ) - itg->addWatch( watch ); - else - itg->removeWatch( watch ); -} - -dbus_bool_t dbusAddTimeout( DBusTimeout *timeout, void *data ) -{ - if ( !dbus_timeout_get_enabled(timeout) ) - return true; - - Integrator *itg = static_cast( data ); - itg->addTimeout( timeout ); - return true; -} - -void dbusRemoveTimeout( DBusTimeout *timeout, void *data ) -{ - Integrator *itg = static_cast( data ); - itg->removeTimeout( timeout ); -} - -void dbusToggleTimeout( DBusTimeout *timeout, void *data ) -{ - Integrator *itg = static_cast( data ); - - if ( dbus_timeout_get_enabled( timeout ) ) - itg->addTimeout( timeout ); - else - itg->removeTimeout( timeout ); -} - -void dbusWakeupMain( void* ) -{ -} - -void dbusNewConnection( DBusServer *server, - DBusConnection *new_connection, - void *data ) -{ - Integrator *itg = static_cast( data ); - itg->handleConnection( new_connection ); -} -///////////////////////////////////////////////////////////// - -Timeout::Timeout( QObject *parent, DBusTimeout *t ) - : QObject( parent ), m_timeout( t ) -{ - m_timer = new QTimer( this ); - connect( m_timer, SIGNAL(timeout()), - SLOT(slotTimeout()) ); -} - -void Timeout::slotTimeout() -{ - emit timeout( m_timeout ); -} - -void Timeout::start() -{ - m_timer->start( dbus_timeout_get_interval( m_timeout ) ); -} - -Integrator::Integrator( DBusConnection *conn, QObject *parent ) - : QObject( parent ), m_connection( conn ) -{ - m_timeouts.setAutoDelete( true ); - - dbus_connection_set_watch_functions( m_connection, - dbusAddWatch, - dbusRemoveWatch, - dbusToggleWatch, - this, 0 ); - dbus_connection_set_timeout_functions( m_connection, - dbusAddTimeout, - dbusRemoveTimeout, - dbusToggleTimeout, - this, 0 ); - dbus_connection_set_wakeup_main_function( m_connection, - dbusWakeupMain, - this, 0 ); -} - -Integrator::Integrator( DBusServer *server, QObject *parent ) - : QObject( parent ), m_server( server ) -{ - m_connection = reinterpret_cast( m_server ); - m_timeouts.setAutoDelete( true ); - - dbus_server_set_watch_functions( m_server, - dbusAddWatch, - dbusRemoveWatch, - dbusToggleWatch, - this, 0 ); - dbus_server_set_timeout_functions( m_server, - dbusAddTimeout, - dbusRemoveTimeout, - dbusToggleTimeout, - this, 0 ); - dbus_server_set_new_connection_function( m_server, - dbusNewConnection, - this, 0 ); -} - -void Integrator::slotRead( int fd ) -{ - QIntDictIterator it( m_watches ); - for ( ; it.current(); ++it ) - dbus_watch_handle ( it.current()->watch, DBUS_WATCH_READABLE ); - - emit readReady(); -} - -void Integrator::slotWrite( int fd ) -{ - QIntDictIterator it( m_watches ); - for ( ; it.current(); ++it ) - dbus_watch_handle ( it.current()->watch, DBUS_WATCH_WRITABLE ); -} - -void Integrator::slotTimeout( DBusTimeout *timeout ) -{ - dbus_timeout_handle( timeout ); -} - -void Integrator::addWatch( DBusWatch *watch ) -{ - if ( !dbus_watch_get_enabled( watch ) ) - return; - - Watch *qtwatch = new Watch; - qtwatch->watch = watch; - - int flags = dbus_watch_get_flags( watch ); - int fd = dbus_watch_get_fd( watch ); - - if ( flags & DBUS_WATCH_READABLE ) { - qtwatch->readSocket = new QSocketNotifier( fd, QSocketNotifier::Read, this ); - QObject::connect( qtwatch->readSocket, SIGNAL(activated(int)), SLOT(slotRead(int)) ); - } - - if (flags & DBUS_WATCH_WRITABLE) { - qtwatch->writeSocket = new QSocketNotifier( fd, QSocketNotifier::Write, this ); - QObject::connect( qtwatch->writeSocket, SIGNAL(activated(int)), SLOT(slotWrite(int)) ); - } - - m_watches.insert( fd, qtwatch ); -} - -void Integrator::removeWatch( DBusWatch *watch ) -{ - int key = dbus_watch_get_fd( watch ); - - Watch *qtwatch = m_watches.take( key ); - - if ( qtwatch ) { - delete qtwatch->readSocket; qtwatch->readSocket = 0; - delete qtwatch->writeSocket; qtwatch->writeSocket = 0; - delete qtwatch; - } -} - -void Integrator::addTimeout( DBusTimeout *timeout ) -{ - Timeout *mt = new Timeout( this, timeout ); - m_timeouts.insert( timeout, mt ); - connect( mt, SIGNAL(timeout(DBusTimeout*)), - SLOT(slotTimeout(DBusTimeout*)) ); - mt->start(); -} - -void Integrator::removeTimeout( DBusTimeout *timeout ) -{ - m_timeouts.remove( timeout ); -} - -void Integrator::handleConnection( DBusConnection *c ) -{ - Connection *con = new Connection( c, this ); - emit newConnection( con ); -} - -}//end namespace Internal -}//end namespace DBusQt - -#include "integrator.moc" diff --git a/qt/integrator.h b/qt/integrator.h deleted file mode 100644 index 70e2a7f2..00000000 --- a/qt/integrator.h +++ /dev/null @@ -1,92 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* integrator.h: integrates D-BUS into Qt event loop - * - * Copyright (C) 2003 Zack Rusin - * - * 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 DBUS_QT_INTEGRATOR_H -#define DBUS_QT_INTEGRATOR_H - -#include - -#include -#include - -#include "dbus/dbus.h" - -class QTimer; - -namespace DBusQt -{ - class Connection; - - namespace Internal - { - struct Watch; - - class Timeout : public QObject - { - Q_OBJECT - public: - Timeout( QObject *parent, DBusTimeout *t ); - public: - void start(); - signals: - void timeout( DBusTimeout* ); - protected slots: - void slotTimeout(); - private: - QTimer *m_timer; - DBusTimeout *m_timeout; - }; - - class Integrator : public QObject - { - Q_OBJECT - public: - Integrator( DBusConnection *connection, QObject *parent ); - Integrator( DBusServer *server, QObject *parent ); - - signals: - void readReady(); - void newConnection( Connection* ); - - protected slots: - void slotRead( int ); - void slotWrite( int ); - void slotTimeout( DBusTimeout *timeout ); - - public: - void addWatch( DBusWatch* ); - void removeWatch( DBusWatch* ); - - void addTimeout( DBusTimeout* ); - void removeTimeout( DBusTimeout* ); - - void handleConnection( DBusConnection* ); - private: - QIntDict m_watches; - QPtrDict m_timeouts; - DBusConnection *m_connection; - DBusServer *m_server; - }; - } -} - -#endif diff --git a/qt/message.cpp b/qt/message.cpp deleted file mode 100644 index 256c2b23..00000000 --- a/qt/message.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* -*- mode: C++; c-file-style: "gnu" -*- */ -/* message.cpp: Qt wrapper for DBusMessage - * - * Copyright (C) 2003 Zack Rusin - * - * Licensed under the Academic Free License version 2.0 - * - * 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 "message.h" - -#include - -#include - -namespace DBusQt { - -struct Message::iterator::IteratorData { - DBusMessageIter *iter; - QVariant var; - bool end; - DBusMessage *mesg; -}; - -/** - * Iterator. - */ -Message::iterator::iterator() -{ - d = new IteratorData; - d->iter = 0; d->end = true; -} - -/** - * Constructs iterator for the message. - * @param msg message whose fields we want to iterate - */ -Message::iterator::iterator( DBusMessage* msg ) -{ - d = new IteratorData; - d->mesg = msg; - d->iter = static_cast( malloc( sizeof(DBusMessageIter) ) ); - dbus_message_iter_init( d->mesg, d->iter ); - if ( !d->iter ) { - qDebug("No iterator??"); - } - fillVar(); - d->end = false; -} - -/** - * Copy constructor for the iterator. - * @param itr iterator - */ -Message::iterator::iterator( const iterator& itr ) -{ - d = new IteratorData; - d->iter = itr.d->iter; - d->var = itr.d->var; - d->end = itr.d->end; -} - -/** - * Destructor. - */ -Message::iterator::~iterator() -{ - free( d->iter ); - delete d; d=0; -} - -/** - * Creates an iterator equal to the @p itr iterator - * @param itr other iterator - * @return - */ -Message::iterator& -Message::iterator::operator=( const iterator& itr ) -{ - IteratorData *tmp = new IteratorData; - tmp->iter = itr.d->iter; - tmp->var = itr.d->var; - tmp->end = itr.d->end; - delete d; d=tmp; - return *this; -} - -/** - * Returns the constant QVariant held by the iterator. - * @return the constant reference to QVariant held by this iterator - */ -const QVariant& -Message::iterator::operator*() const -{ - return d->var; -} - -/** - * Returns the QVariant held by the iterator. - * @return reference to QVariant held by this iterator - */ -QVariant& -Message::iterator::operator*() -{ - return d->var; -} - -/** - * Moves to the next field and return a reference to itself after - * incrementing. - * @return reference to self after incrementing - */ -Message::iterator& -Message::iterator::operator++() -{ - if ( d->end ) - return *this; - - if ( dbus_message_iter_next( d->iter ) ) { - fillVar(); - } else { - d->end = true; - d->var = QVariant(); - } - return *this; -} - -/** - * Moves to the next field and returns self before incrementing. - * @return self before incrementing - */ -Message::iterator -Message::iterator::operator++(int) -{ - iterator itr( *this ); - operator++(); - return itr; -} - -/** - * Compares this iterator to @p it iterator. - * @param it the iterator to which we're comparing this one to - * @return true if they're equal, false otherwise - */ -bool -Message::iterator::operator==( const iterator& it ) -{ - if ( d->end == it.d->end ) { - if ( d->end == true ) { - return true; - } else { - return d->var == it.d->var; - } - } else - return false; -} - -/** - * Compares two iterators. - * @param it The other iterator. - * @return true if two iterators are not equal, false - * otherwise - */ -bool -Message::iterator::operator!=( const iterator& it ) -{ - return !operator==( it ); -} - -QVariant Message::iterator::marshallBaseType( DBusMessageIter* i ) -{ - QVariant ret; - switch (dbus_message_iter_get_arg_type(i)) { - case DBUS_TYPE_INT32: - { - dbus_int32_t v; - dbus_message_iter_get_basic (i, &v); - ret = QVariant( v ); - } - break; - case DBUS_TYPE_UINT32: - { - dbus_uint32_t v; - dbus_message_iter_get_basic (i, &v); - ret = QVariant( v ); - } - break; - case DBUS_TYPE_DOUBLE: - { - double v; - dbus_message_iter_get_basic (i, &v); - ret = QVariant( v ); - } - break; - case DBUS_TYPE_STRING: - { - const char *v; - dbus_message_iter_get_basic (i, &v); - ret = QVariant( v ); - } - break; - default: - ret = QVariant(); - break; - } - return ret; -} - -/** - * Fills QVariant based on what current DBusMessageIter helds. - */ -void -Message::iterator::fillVar() -{ - switch ( dbus_message_iter_get_arg_type( d->iter ) ) { - case DBUS_TYPE_INT32: - case DBUS_TYPE_UINT32: - case DBUS_TYPE_DOUBLE: - case DBUS_TYPE_STRING: - d->var = marshallBaseType( d->iter ); - break; - case DBUS_TYPE_ARRAY: { - switch ( dbus_message_iter_get_element_type( d->iter ) ) { - case DBUS_TYPE_STRING: { - QStringList tempList; - DBusMessageIter sub; - dbus_message_iter_recurse (d->iter, &sub); - while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) - { - const char *v; - dbus_message_iter_get_basic (&sub, &v); - tempList.append( QString( v ) ); - dbus_message_iter_next (&sub); - } - d->var = QVariant( tempList ); - break; - } - default: - qDebug( "Array of type not implemented" ); - d->var = QVariant(); - break; - } - break; - } -#if 0 - /* DICT is gone for now, but expected to be reintroduced, or else - * reintroduced as a flag on the introspection data that can - * apply to array of struct of two fields - */ - case DBUS_TYPE_DICT: { - qDebug( "Got a hash!" ); - QMap tempMap; - DBusMessageIter dictIter; - dbus_message_iter_init_dict_iterator( d->iter, &dictIter ); - do { - char *key = dbus_message_iter_get_dict_key( &dictIter ); - tempMap[key] = marshallBaseType( &dictIter ); - dbus_free( key ); - dbus_message_iter_next( &dictIter ); - } while( dbus_message_iter_has_next( &dictIter ) ); - d->var = QVariant( tempMap ); - break; - qDebug( "Hash/Dict type not implemented" ); - d->var = QVariant(); - break; - } -#endif - default: - qDebug( "not implemented" ); - d->var = QVariant(); - break; - } -} - -/** - * Returns a QVariant help by this iterator. - * @return QVariant held by this iterator - */ -QVariant -Message::iterator::var() const -{ - return d->var; -} - -struct Message::Private { - DBusMessage *msg; -}; - -Message::Message( DBusMessage *m ) -{ - d = new Private; - d->msg = m; -} - -/** - * - */ -Message::Message( int messageType ) -{ - d = new Private; - d->msg = dbus_message_new( messageType ); -} - -/** - * Constructs a new Message with the given service and name. - * @param service service service that the message should be sent to - * @param name name of the message - */ -Message::Message( const QString& service, const QString& path, - const QString& interface, const QString& method ) -{ - d = new Private; - d->msg = dbus_message_new_method_call( service.latin1(), path.latin1(), - interface.latin1(), method.latin1() ); -} - -/** - * Constructs a message that is a reply to some other - * message. - * @param name the name of the message - * @param replayingTo original_message the message which the created - * message is a reply to. - */ -Message::Message( const Message& replayingTo ) -{ - d = new Private; - d->msg = dbus_message_new_method_return( replayingTo.d->msg ); -} - -Message:: Message( const QString& path, const QString& interface, - const QString& name ) -{ - d = new Private; - d->msg = dbus_message_new_signal( path.ascii(), interface.ascii(), - name.ascii() ); -} - -Message::Message( const Message& replayingTo, const QString& errorName, - const QString& errorMessage ) -{ - d = new Private; - d->msg = dbus_message_new_error( replayingTo.d->msg, errorName.utf8(), - errorMessage.utf8() ); -} - -Message Message::operator=( const Message& other ) -{ - //FIXME: ref the other.d->msg instead of copying it? -} -/** - * Destructs message. - */ -Message::~Message() -{ - if ( d->msg ) { - dbus_message_unref( d->msg ); - } - delete d; d=0; -} - -int Message::type() const -{ - return dbus_message_get_type( d->msg ); -} - -void Message::setPath( const QString& path ) -{ - dbus_message_set_path( d->msg, path.ascii() ); -} - -QString Message::path() const -{ - return dbus_message_get_path( d->msg ); -} - -void Message::setInterface( const QString& iface ) -{ - dbus_message_set_interface( d->msg, iface.ascii() ); -} - -QString Message::interface() const -{ - return dbus_message_get_interface( d->msg ); -} - -void Message::setMember( const QString& member ) -{ - dbus_message_set_member( d->msg, member.ascii() ); -} - -QString Message::member() const -{ - return dbus_message_get_member( d->msg ); -} - -void Message::setErrorName( const QString& err ) -{ - dbus_message_set_error_name( d->msg, err ); -} - -QString Message::errorName() const -{ - return dbus_message_get_error_name( d->msg ); -} - -void Message::setDestination( const QString& dest ) -{ - dbus_message_set_destination( d->msg, dest ); -} - -QString Message::destination() const -{ - return dbus_message_get_destination( d->msg ); -} - -/** - * Sets the message sender. - * @param sender the sender - * @return false if unsuccessful - */ -bool -Message::setSender( const QString& sender ) -{ - return dbus_message_set_sender( d->msg, sender.latin1() ); -} - -/** - * Returns sender of this message. - * @return sender - */ -QString -Message::sender() const -{ - return dbus_message_get_sender( d->msg ); -} - -QString Message::signature() const -{ - return dbus_message_get_signature( d->msg ); -} - - -/** - * Returns the starting iterator for the fields of this - * message. - * @return starting iterator - */ -Message::iterator -Message::begin() const -{ - return iterator( d->msg ); -} - -/** - * Returns the ending iterator for the fields of this - * message. - * @return ending iterator - */ -Message::iterator -Message::end() const -{ - return iterator(); -} - -/** - * Returns the field at position @p i - * @param i position of the wanted field - * @return QVariant at position @p i or an empty QVariant - */ -QVariant -Message::at( int i ) -{ - iterator itr( d->msg ); - - while ( i-- ) { - if ( itr == end() ) - return QVariant();//nothing there - ++itr; - } - return *itr; -} - -/** - * The underlying DBusMessage of this class. - * @return DBusMessage pointer. - */ -DBusMessage* -Message::message() const -{ - return d->msg; -} - -Message& Message::operator<<( bool b ) -{ - const dbus_bool_t right_size_bool = b; - dbus_message_append_args( d->msg, DBUS_TYPE_BOOLEAN, &right_size_bool, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( Q_INT8 byte ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_BYTE, &byte, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( Q_INT32 num ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_INT32, &num, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( Q_UINT32 num ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_UINT32, &num, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( Q_INT64 num ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_INT64, &num, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( Q_UINT64 num ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_UINT64, &num, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( double num ) -{ - dbus_message_append_args( d->msg, DBUS_TYPE_DOUBLE, &num, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( const QString& str ) -{ - const char *u = str.utf8(); - dbus_message_append_args( d->msg, DBUS_TYPE_STRING, &u, - DBUS_TYPE_INVALID ); -} - -Message& Message::operator<<( const QVariant& custom ) -{ - //FIXME: imeplement -} - -} diff --git a/qt/message.h b/qt/message.h deleted file mode 100644 index 5e26b819..00000000 --- a/qt/message.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- mode: C++; c-file-style: "gnu" -*- */ -/* message.h: Qt wrapper for DBusMessage - * - * Copyright (C) 2003 Zack Rusin - * - * 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 DBUS_QT_MESSAGE_H -#define DBUS_QT_MESSAGE_H - -#include -#include -#include - -#include "dbus/dbus.h" - -namespace DBusQt { - - class Message - { - public: - class iterator { - public: - iterator(); - iterator( const iterator& ); - iterator( DBusMessage* msg ); - ~iterator(); - - iterator& operator=( const iterator& ); - const QVariant& operator*() const; - QVariant& operator*(); - iterator& operator++(); - iterator operator++(int); - bool operator==( const iterator& it ); - bool operator!=( const iterator& it ); - - QVariant var() const; - protected: - QVariant marshallBaseType( DBusMessageIter* i ); - void fillVar(); - struct IteratorData; - IteratorData *d; - }; - - Message( int messageType ); - Message( DBusMessage * );//hide this one from the public implementation - Message( const QString& service, const QString& path, - const QString& interface, const QString& method ); - Message( const Message& replayingTo ); - Message( const QString& path, const QString& interface, - const QString& name ); - Message( const Message& replayingTo, const QString& errorName, - const QString& errorMessage ); - - Message operator=( const Message& other ); - - virtual ~Message(); - - int type() const; - - void setPath( const QString& ); - QString path() const; - - void setInterface( const QString& ); - QString interface() const; - - void setMember( const QString& ); - QString member() const; - - void setErrorName( const QString& ); - QString errorName() const; - - void setDestination( const QString& ); - QString destination() const; - - bool setSender( const QString& sender ); - QString sender() const; - - QString signature() const; - - iterator begin() const; - iterator end() const; - - QVariant at( int i ); - - - public: - Message& operator<<( bool ); - Message& operator<<( Q_INT8 ); - Message& operator<<( Q_INT32 ); - Message& operator<<( Q_UINT32 ); - Message& operator<<( Q_INT64 ); - Message& operator<<( Q_UINT64 ); - Message& operator<<( double ); - Message& operator<<( const QString& ); - Message& operator<<( const QVariant& ); - //Message& operator<<(); - //Message& operator<<(); - //Message& operator<<(); - //Message& operator<<(); - //Message& operator<<(); - //Message& operator<<(); - //Message& operator<<(); - - protected: - friend class Connection; - DBusMessage* message() const; - - private: - struct Private; - Private *d; - }; - -} - -#endif diff --git a/qt/qdbus.h b/qt/qdbus.h new file mode 100644 index 00000000..35454219 --- /dev/null +++ b/qt/qdbus.h @@ -0,0 +1,31 @@ +/* qdbus.h precompiled header + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include +#include +#include + +#endif diff --git a/qt/qdbusconnection.cpp b/qt/qdbusconnection.cpp new file mode 100644 index 00000000..6493ef2a --- /dev/null +++ b/qt/qdbusconnection.cpp @@ -0,0 +1,328 @@ +/* qdbusconnection.cpp + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include + +#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 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::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::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( + 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(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" diff --git a/qt/qdbusconnection.h b/qt/qdbusconnection.h new file mode 100644 index 00000000..16ab2b1a --- /dev/null +++ b/qt/qdbusconnection.h @@ -0,0 +1,78 @@ +/* qdbusconnection.h QDBusConnection object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 + +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 diff --git a/qt/qdbusconnection_p.h b/qt/qdbusconnection_p.h new file mode 100644 index 00000000..38acbdc3 --- /dev/null +++ b/qt/qdbusconnection_p.h @@ -0,0 +1,126 @@ +/* qdbusconnection_p.h QDBusConnection private object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include +#include +#include +#include + +#include + +#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 WatcherHash; + WatcherHash watchers; + + typedef QHash TimeoutHash; + TimeoutHash timeouts; + + struct SignalHook + { + QString interface, name; + QPointer obj; + int midx; + QVarLengthArray params; + + bool setSlot(const char *slotName); + }; + + typedef QMultiHash SignalHookHash; + SignalHookHash signalHooks; + + struct ObjectHook + { + QString interface; + QPointer obj; + }; + typedef QMultiHash ObjectHookHash; + ObjectHookHash objectHooks; + QList pendingTimeouts; +}; diff --git a/qt/qdbuserror.cpp b/qt/qdbuserror.cpp new file mode 100644 index 00000000..0f7dc92c --- /dev/null +++ b/qt/qdbuserror.cpp @@ -0,0 +1,46 @@ +/* qdbuserror.h QDBusError object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 + +#include + +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 + + diff --git a/qt/qdbuserror.h b/qt/qdbuserror.h new file mode 100644 index 00000000..d554426d --- /dev/null +++ b/qt/qdbuserror.h @@ -0,0 +1,48 @@ +/* qdbuserror.h QDBusError object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 + +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 diff --git a/qt/qdbusintegrator.cpp b/qt/qdbusintegrator.cpp new file mode 100644 index 00000000..4a19d33e --- /dev/null +++ b/qt/qdbusintegrator.cpp @@ -0,0 +1,621 @@ +/* qdbusintegrator.cpp QDBusConnection private implementation + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include +#include +#include +#include + +#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(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(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(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(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(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(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 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(v.constData())); + } + if (count + 1 == hook.params.count()) + params.append(const_cast(&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 params; + params.append(0); // ### return type + + QList 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(msg.at(i).constData())); + } else if (i == parameterTypes.count() - 1 && param == "QDBusMessage") { + params.append(const_cast(static_cast(&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 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(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"); + return tp; +} + +bool QDBusConnectionPrivate::SignalHook::setSlot(const char *slotName) +{ + Q_ASSERT(static_cast(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 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 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 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 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(it.value().obj) == obj) + it = objectHooks.erase(it); + else + ++it; + } + SignalHookHash::iterator sit = signalHooks.begin(); + while (sit != signalHooks.end()) { + if (static_cast(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 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 receiver; + int methodIdx; + DBusPendingCall *pending; +}; + +static void qDBusResultReceived(DBusPendingCall *pending, void *user_data) +{ + QDBusPendingCall *call = reinterpret_cast(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; +} diff --git a/qt/qdbusmacros.h b/qt/qdbusmacros.h new file mode 100644 index 00000000..ee88cdfa --- /dev/null +++ b/qt/qdbusmacros.h @@ -0,0 +1,34 @@ +/* qdbusmessage.h QDBusMessage object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 + +#ifdef QDBUS_MAKEDLL +# define QDBUS_EXPORT Q_DECL_EXPORT +#else +# define QDBUS_EXPORT Q_DECL_IMPORT +#endif + +#endif diff --git a/qt/qdbusmarshall.cpp b/qt/qdbusmarshall.cpp new file mode 100644 index 00000000..8afcb9f3 --- /dev/null +++ b/qt/qdbusmarshall.cpp @@ -0,0 +1,300 @@ +/* qdbusmarshall.cpp + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +template +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(&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(it); + case DBUS_TYPE_INT32: + return qIterGet(it); + case DBUS_TYPE_UINT32: + return qIterGet(it); + case DBUS_TYPE_DOUBLE: + return qIterGet(it); + case DBUS_TYPE_BOOLEAN: + return qIterGet(it); + case DBUS_TYPE_INT64: + return qIterGet(it); + case DBUS_TYPE_UINT64: + return qIterGet(it); + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + return QString::fromUtf8(qIterGet(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 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 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 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 &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 &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 &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 &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 &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 &map = var.toMap(); + DBusMessageIter sub; + QVarLengthArray 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::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::qt_metatype_id()) { + DBusMessageIter sub; + QDBusVariant dvariant = qvariant_cast(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 &list) +{ + if (list.isEmpty()) + return; + + for (int i = 0; i < list.count(); ++i) + qVariantToIterator(it, list.at(i)); +} + +void QDBusMarshall::listToMessage(const QList &list, DBusMessage *msg) +{ + Q_ASSERT(msg); + DBusMessageIter it; + dbus_message_iter_init_append(msg, &it); + qListToIterator(&it, list); +} + diff --git a/qt/qdbusmarshall.h b/qt/qdbusmarshall.h new file mode 100644 index 00000000..4fc1a1ab --- /dev/null +++ b/qt/qdbusmarshall.h @@ -0,0 +1,39 @@ +/* qdbusmarshall.h QDBusMarshall object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +class QList; + +class QDBusMarshall +{ +public: + static void listToMessage(const QList &list, DBusMessage *message); + static void messageToList(QList &list, DBusMessage *message); +}; + +#endif diff --git a/qt/qdbusmessage.cpp b/qt/qdbusmessage.cpp new file mode 100644 index 00000000..a77c22f0 --- /dev/null +++ b/qt/qdbusmessage.cpp @@ -0,0 +1,233 @@ +/* qdbusmessage.cpp + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include + +#include + +#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(other) +{ + d = other.d; + d->ref.ref(); +} + +QDBusMessage::~QDBusMessage() +{ + if (!d->ref.deref()) + delete d; +} + +QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other) +{ + QList::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 >(msg) << ")"; + return dbg.space(); +} +#endif + diff --git a/qt/qdbusmessage.h b/qt/qdbusmessage.h new file mode 100644 index 00000000..5f70182c --- /dev/null +++ b/qt/qdbusmessage.h @@ -0,0 +1,80 @@ +/* qdbusmessage.h QDBusMessage object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include + +#include + +class QDBusMessagePrivate; +struct DBusMessage; + +class QDBUS_EXPORT QDBusMessage: public QList +{ + 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 + diff --git a/qt/qdbusmessage_p.h b/qt/qdbusmessage_p.h new file mode 100644 index 00000000..9655c9d9 --- /dev/null +++ b/qt/qdbusmessage_p.h @@ -0,0 +1,46 @@ +/* qdbusmessage.h QDBusMessage private object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include + +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 diff --git a/qt/qdbusserver.cpp b/qt/qdbusserver.cpp new file mode 100644 index 00000000..08fea26d --- /dev/null +++ b/qt/qdbusserver.cpp @@ -0,0 +1,59 @@ +/* qdbusserver.cpp + * + * Copyright (C) 2005 Harald Fernengel + * + * 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" diff --git a/qt/qdbusserver.h b/qt/qdbusserver.h new file mode 100644 index 00000000..55607860 --- /dev/null +++ b/qt/qdbusserver.h @@ -0,0 +1,48 @@ +/* qdbusserver.h QDBusServer object + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include + +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 diff --git a/qt/qdbusvariant.h b/qt/qdbusvariant.h new file mode 100644 index 00000000..1a92a600 --- /dev/null +++ b/qt/qdbusvariant.h @@ -0,0 +1,40 @@ +/* qdbusvariant.h DBUS variant struct + * + * Copyright (C) 2005 Harald Fernengel + * + * 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 +#include +#include + +struct QDBUS_EXPORT QDBusVariant +{ + QString signature; + QVariant value; +}; +Q_DECLARE_METATYPE(QDBusVariant) + +#endif + diff --git a/qt/server.cpp b/qt/server.cpp deleted file mode 100644 index 5d6c3ba1..00000000 --- a/qt/server.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* server.h: Qt wrapper for DBusServer - * - * Copyright (C) 2003 Zack Rusin - * - * Licensed under the Academic Free License version 2.0 - * - * 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 "server.h" -#include "connection.h" - -#include "integrator.h" -using DBusQt::Internal::Integrator; - -namespace DBusQt -{ - -struct Server::Private { - Private() : integrator( 0 ), server( 0 ) - {} - - Integrator *integrator; - DBusServer *server; - DBusError error; -}; - -Server::Server( const QString& addr, QObject *parent ) - : QObject( parent ) -{ - d = new Private; - - if ( !addr.isEmpty() ) { - init( addr ); - } -} - -Server::~Server() -{ - delete d; -} - -bool Server::isConnected() const -{ - return dbus_server_get_is_connected( d->server ); -} - -void Server::disconnect() -{ - dbus_server_disconnect( d->server ); -} - -QString Server::address() const -{ - //FIXME: leak? - return dbus_server_get_address( d->server ); -} - -void Server::listen( const QString& addr ) -{ - if ( !d->server ) { - init( addr ); - } -} - -void Server::init( const QString& addr ) -{ - d->server = dbus_server_listen( addr.ascii(), &d->error ); - d->integrator = new Integrator( d->server, this ); - connect( d->integrator, SIGNAL(newConnection(Connection*)), - SIGNAL(newConnection(Connection*)) ); -} - -} - - -#include "server.moc" diff --git a/qt/server.h b/qt/server.h deleted file mode 100644 index 36c729ab..00000000 --- a/qt/server.h +++ /dev/null @@ -1,57 +0,0 @@ -// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*- -/* server.h: Qt wrapper for DBusServer - * - * Copyright (C) 2003 Zack Rusin - * - * 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 DBUS_QT_SERVER_H -#define DBUS_QT_SERVER_H - -#include - -#include "dbus/dbus.h" - -namespace DBusQt -{ - class Connection; - class Server : public QObject - { - Q_OBJECT - public: - Server( const QString& addr = QString::null, QObject *parent=0 ); - ~Server(); - - bool isConnected() const; - QString address() const; - - public slots: - void listen( const QString& addr ); - void disconnect(); - signals: - void newConnection( Connection* ); - - private: - void init( const QString& addr ); - private: - struct Private; - Private *d; - }; -} - -#endif -- cgit