Logo Search packages:      
Sourcecode: kdbus version File versions  Download package

dbusdispatcher.cpp

/***************************************************************************
 *   Copyright (C) 2006 by Rohan McGovern                                  *
 *   rohan.pm@gmail.com                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <kdebug.h>
#include <klocale.h>
#include <klistview.h>
#include <klineedit.h>
#include <qtextedit.h>
#include <qtimer.h>
#include <stdexcept>

#include "dbusdispatcher.h"
#include "dbustreewidget.h"
#include "dbusmethod.h"
#include "dbusutil.h"
#include "dbusmethodargument.h"
#include "dbus/qdbusmessage.h"
#include "dbus/qdbuserror.h"
#include "dbus/qdbusproxy.h"

class DBusDispatcher::Private {
public:
    DBusTreeWidget * parent;
    QDBusProxy * proxy;
};

00043 DBusDispatcher::DBusDispatcher(
  DBusTreeWidget * parent,
  QDBusProxy * proxy
)
 : QObject(parent), d( new DBusDispatcher::Private() )
{
    d->parent = parent;
    d->proxy = proxy;
}

00053 void DBusDispatcher::executeMethod() const {
    // Get currently selected item
    DBusMethod * method =
      dynamic_cast< DBusMethod * >(d->parent->listView()->selectedItem());

    if ( !method )
        throw std::logic_error( "Selected item isn't DBusMethod!" );

    QPtrList< DBusMethodArgument > inArgs = method->inArgs();
    QPtrList< DBusMethodArgument > outArgs = method->outArgs();

    if ( inArgs.count() != method->inputBoxes().count() )
        throw std::logic_error( "Mismatch in amount of input args" );

    if ( outArgs.count() != method->outputBoxes().count() )
        throw std::logic_error( "Mismatch in amount of output args" );

    if ( !d->proxy->canSend() ) {
        d->parent->statusMessage(
          i18n(
            "Failed to call method: connection to D-BUS broken!"
          )
        );
        return;
    }

    QValueList< QVariant > params;

    for ( unsigned int i = 0; i < inArgs.count(); i++ ) {
        QString text = method->inputBoxes().at(i)->text();
        QString type = inArgs.at(i)->niceType();

        bool ok = true;

        if ( type == "STRING" )
            params.append( text );
        else if ( type == "BOOLEAN" ) {
            if ( text.lower() == "true" )
                params.append( true );
            else if ( text.lower() == "false" )
                params.append( false );
            else
                ok = false;
        }
        else if ( type == "BYTE" ) {
            short unsigned int myShort = text.toUShort( &ok );
            if ( ok ) {
                if ( myShort > 255 )
                    ok = false;
                if ( ok )
                    params.append( (Q_INT8)myShort );
            }
        }
        else if ( type == "INT32" )
            params.append( (Q_INT32)text.toInt( &ok ) );
        else if ( type == "UINT32" )
            params.append( (Q_UINT32)text.toUInt( &ok ) );
        else if ( type == "INT64" )
            params.append( (Q_INT64)text.toLongLong( &ok ) );
        else if ( type == "UINT64" )
            params.append( (Q_UINT64)text.toULongLong( &ok ) );
        else if ( type == "DOUBLE" )
            params.append( (double)text.toDouble( &ok ) );
        else if ( type == "VARIANT" )
            // Have to just hope this is OK...
            params.append( text );
        else {
            // Oops, we can't handle this!
            d->parent->statusMessage(
              i18n(
                "Sorry, sending messages with argument type '%1' is not "
                "yet supported!"
              ).arg( type )
            );
            return;
        }

        if ( !ok ) {
            d->parent->statusMessage(
              i18n(
                "Argument '%1' is not of required type '%2'!"
              ).arg( text ).arg( type )
            );
            return;
        }
    }

    d->parent->statusMessage(
      i18n(
        "Calling method %1.%2 ..."
      ).arg( method->interface() ).arg( method->name() )
    );

    try {
        d->proxy->setService( method->service() );
        d->proxy->setPath( method->object() );
        d->proxy->setInterface( method->interface() );
        DBusUtil::mutex.lock();
        QDBusMessage reply = d->proxy->sendWithReply(
          method->name(),
          params
        );
        DBusUtil::mutex.unlock();
        // For purposes of listening for signals, we should always return to
        // the org.freedesktop.DBus object.
        d->proxy->setService( "org.freedesktop.DBus" );
        d->proxy->setPath( "/org/freedesktop/DBus" );
        d->proxy->setInterface( "org.freedesktop.DBus" );

        if ( reply.type() == QDBusMessage::InvalidMessage )
            throw QDBusSendError(
                QString("%1: %2")
                .arg( d->proxy->lastError().name() )
                .arg( d->proxy->lastError().message() )
            );

        kdDebug() << "Got reply" << endl;

        kdDebug() << "Expecting " << method->outputBoxes().count()
                  << " outputs." << endl;

        for (
          int i = 0;
          !reply[i].isNull();
          i++
        ) {

            kdDebug() << "Handling output element " << i << endl;

            QString output = reply[i].toString();
            if ( output.isNull() ) {
                if ( reply[i].toStringList().count() > 0 )
                    output = reply[i].toStringList().join(", ");
                else
                    output =
                      i18n(
                        "(kdbus doesn't know how to display this data type!)"
                      );
            }
            
            if ( i > (signed int)method->outputBoxes().count()-1 )
                throw std::runtime_error(
                    i18n("Got more output than expected: %1").arg( output )
                );
            
            method->outputBoxes().at(i)->setText( output );
            int desiredHeight = method->outputBoxes().at(i)->heightForWidth(
                method->outputBoxes().at(i)->width()
            ) + 4;

            int maxHeight = 200;
            
            if ( desiredHeight > maxHeight )
                desiredHeight = maxHeight;
            
            method->outputBoxes().at(i)->setFixedHeight(
              desiredHeight
            );

            kdDebug() << reply[i].toString() << endl;
        } // for
       
    } // try
    catch ( std::runtime_error const & e ) {
        d->parent->statusMessage(
          i18n(
            "Error while executing: %1"
          ).arg( e.what() )
        );
        return;
    }

    d->parent->statusMessage(
      i18n(
        "Successfully called method %1.%2"
      ).arg( method->interface() ).arg( method->name() )
    );

    QTimer::singleShot( 0, d->parent, SLOT(resizeSplitter()) );
}

DBusDispatcher::~DBusDispatcher() {
    delete d;
}

#include "dbusdispatcher.moc"

Generated by  Doxygen 1.6.0   Back to index