dbus/qt3 .cvsignore, NONE, 1.1 Makefile.am, NONE, 1.1 connection.cpp, NONE, 1.1 connection.h, NONE, 1.1 dbus-qt.h, NONE, 1.1 dbus-qthread.cpp, NONE, 1.1 integrator.cpp, NONE, 1.1 integrator.h, NONE, 1.1 message.cpp, NONE, 1.1 message.h, NONE, 1.1 server.cpp, NONE, 1.1 server.h, NONE, 1.1

Harald Fernengel harry at freedesktop.org
Fri Sep 30 08:20:10 PDT 2005


Update of /cvs/dbus/dbus/qt3
In directory gabe:/tmp/cvs-serv22758/qt3

Added Files:
	.cvsignore Makefile.am connection.cpp connection.h dbus-qt.h 
	dbus-qthread.cpp integrator.cpp integrator.h message.cpp 
	message.h server.cpp server.h 
Log Message:
bring Qt3 library back. Some apps that are not in the KDE trunk are using it.


--- NEW FILE: .cvsignore ---
.deps
.libs
Makefile
Makefile.in
*.lo
*.la
*.bb
*.bbg
*.da
*.gcov
*.moc

--- NEW FILE: Makefile.am ---
if HAVE_QT3
INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_QT3_CXXFLAGS)

dbusincludedir=$(includedir)/dbus-1.0/dbus

lib_LTLIBRARIES=libdbus-qt-1.la

dbusinclude_HEADERS=				\
	dbus-qt.h message.h connection.h        \
	server.h

libdbus_qt_1_la_SOURCES = 			\
	$(top_srcdir)/qt3/dbus-qthread.cpp \
	$(top_srcdir)/qt3/message.cpp \
	$(top_srcdir)/qt3/connection.cpp \
	$(top_srcdir)/qt3/integrator.cpp \
	$(top_srcdir)/qt3/server.cpp \
	$(top_srcdir)/qt3/connection.h \
	$(top_srcdir)/qt3/integrator.h \
	$(top_srcdir)/qt3/server.h


$(top_srcdir)/qt3/connection.cpp: connection.moc
$(top_srcdir)/qt3/integrator.cpp: integrator.moc
$(top_srcdir)/qt3/server.cpp: server.moc
$(top_srcdir)/qt3/connection.h: connection.moc
$(top_srcdir)/qt3/integrator.h: integrator.moc
$(top_srcdir)/qt3/server.h: server.moc

CLEANFILES=connection.moc integrator.moc server.moc

libdbus_qt_1_la_LIBADD= $(DBUS_QT3_LIBS) $(top_builddir)/dbus/libdbus-1.la
libdbus_qt_1_la_LDFLAGS= -version-info 1:0 -no-undefined

%.moc: %.h
	$(QT3_MOC) $< > $@
endif

--- NEW FILE: connection.cpp ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* connection.cpp: Qt wrapper for DBusConnection
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * 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"

--- NEW FILE: connection.h ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* connection.h: Qt wrapper for DBusConnection
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifndef DBUS_QT_CONNECTION_H
#define DBUS_QT_CONNECTION_H

#include "message.h"

#include <qobject.h>
#include <qstring.h>

#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

--- NEW FILE: dbus-qt.h ---
/* -*- 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 <dbus/dbus.h>
/*
 * 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<DBusConnection> mReadNotifiers;
  QAsciiDict<DBusConnection> 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 */

--- NEW FILE: dbus-qthread.cpp ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-qthread.cpp  Qt threads integration
 *
 * Copyright (C) 2002  Zack Rusin <zack at kde.org>
 *
 * 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 <dbus/dbus.h>
#include <qmutex.h>

#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<DBusMutex*>( mutex );
}

static void
dbus_qmutex_free (DBusMutex *mutex)
{
  QMutex * qmutex = static_cast<QMutex*>(mutex);
  delete mutex;
}

static dbus_bool_t
dbus_qmutex_lock   (DBusMutex *mutex)
{
  QMutex *qmutex = static_cast<QMutex*>(mutex);
  qmutex->lock();
  return TRUE;
}

static dbus_bool_t
dbus_qmutex_unlock (DBusMutex *mutex)
{
  QMutex *qmutex = static_cast<QMutex*>(mutex);
  qmutex->unlock();
  return TRUE;
}

static DBusCondVar*
dbus_qcondvar_new (void)
{
  QWaitCondition *cond;
  cond = new QWaitCondition;
  return static_cast<DBusCondVar*>( cond );
}

static void
dbus_qcondvar_free (DBusCondVar *cond)
{
  QWaitCondition *qcond = static_cast<QWaitCondition*>(cond);
  delete qcond;
}

static void
dbus_qcondvar_wait (DBusCondVar *cond,
		    DBusMutex   *mutex)
{
  QWaitCondition *qcond = static_cast<QWaitCondition*>(cond);
  QMutex *qmutex = static_cast<QMutex*>(mutex);

  qcond->wait (qmutex);
}

static dbus_bool_t
dbus_gcondvar_wait_timeout (DBusCondVar *cond,
			    DBusMutex   *mutex,
			    int         timeout_msec)
{
  QWaitCondition *qcond = static_cast<QWaitCondition*>(cond);
  QMutex *qmutex = static_cast<QMutex*>(mutex);

  return qcond->wait (qmutex, timout_msec);
}

static void
dbus_qcondvar_wake_one (DBusCondVar *cond)
{
  QWaitCondition *qcond = static_cast<QWaitCondition*>(cond);

  qcond->wakeOne (qmutex);
}

static void
dbus_qcondvar_wake_all (DBusCondVar *cond)
{
  QWaitCondition *qcond = static_cast<QWaitCondition*>(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

--- NEW FILE: integrator.cpp ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* integrator.h: integrates D-BUS into Qt event loop
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * 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 <qtimer.h>
#include <qsocketnotifier.h>
#include <qintdict.h>
#include <qptrlist.h>

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<Integrator*>( data );
  con->addWatch( watch );
  return true;
}
void dbusRemoveWatch( DBusWatch *watch, void *data )
{
  Integrator *con = static_cast<Integrator*>( data );
  con->removeWatch( watch );
}

void dbusToggleWatch( DBusWatch *watch, void *data )
{
  Integrator *itg = static_cast<Integrator*>( 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<Integrator*>( data );
  itg->addTimeout( timeout );
  return true;
}

void dbusRemoveTimeout( DBusTimeout *timeout, void *data )
{
  Integrator *itg = static_cast<Integrator*>( data );
  itg->removeTimeout( timeout );
}

void dbusToggleTimeout( DBusTimeout *timeout, void *data )
{
  Integrator *itg = static_cast<Integrator*>( 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<Integrator*>( 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<DBusConnection*>( 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<Watch>	it( m_watches );
  for ( ; it.current(); ++it )
    dbus_watch_handle ( it.current()->watch, DBUS_WATCH_READABLE );

  emit readReady();
}

void Integrator::slotWrite( int fd )
{
  QIntDictIterator<Watch>       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"

--- NEW FILE: integrator.h ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* integrator.h: integrates D-BUS into Qt event loop
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifndef DBUS_QT_INTEGRATOR_H
#define DBUS_QT_INTEGRATOR_H

#include <qobject.h>

#include <qintdict.h>
#include <qptrdict.h>

#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<Watch> m_watches;
      QPtrDict<Timeout> m_timeouts;
      DBusConnection *m_connection;
      DBusServer *m_server;
    };
  }
}

#endif

--- NEW FILE: message.cpp ---
/* -*- mode: C++; c-file-style: "gnu" -*- */
/* message.cpp: Qt wrapper for DBusMessage
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * 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 <qmap.h>

#include <cstdlib>

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<DBusMessageIter *>( 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<QString, QVariant> 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
}

}

--- NEW FILE: message.h ---
/* -*- mode: C++; c-file-style: "gnu" -*- */
/* message.h: Qt wrapper for DBusMessage
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifndef DBUS_QT_MESSAGE_H
#define DBUS_QT_MESSAGE_H

#include <qvariant.h>
#include <qstring.h>
#include <qstringlist.h>

#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

--- NEW FILE: server.cpp ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* server.h: Qt wrapper for DBusServer
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * 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"

--- NEW FILE: server.h ---
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
/* server.h: Qt wrapper for DBusServer
 *
 * Copyright (C) 2003  Zack Rusin <zack at kde.org>
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifndef DBUS_QT_SERVER_H
#define DBUS_QT_SERVER_H

#include <qobject.h>

#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



More information about the dbus-commit mailing list