lib

qtobject.cpp

00001 /***************************************************************************
00002  * qtobject.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this program; see the file COPYING.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  ***************************************************************************/
00019 
00020 #include "qtobject.h"
00021 #include "object.h"
00022 #include "variant.h"
00023 #include "event.h"
00024 
00025 #include "../main/manager.h"
00026 #include "eventslot.h"
00027 #include "eventsignal.h"
00028 
00029 #include <qobject.h>
00030 #include <qsignal.h>
00031 //#include <qglobal.h>
00032 //#include <qobjectdefs.h>
00033 #include <qmetaobject.h>
00034 #include <private/qucom_p.h> // for the Qt QUObject API.
00035 
00036 using namespace Kross::Api;
00037 
00038 QtObject::QtObject(QObject* object, const QString& name)
00039     : Kross::Api::Class<QtObject>(name.isEmpty() ? object->name() : name)
00040     , m_object(object)
00041 {
00042     // Walk through the signals and slots the QObject has
00043     // and attach them as events to this QtObject.
00044 
00045     QStrList slotnames = m_object->metaObject()->slotNames(false);
00046     for(char* c = slotnames.first(); c; c = slotnames.next()) {
00047         QCString s = c;
00048         addChild(s, new EventSlot(s, object, s) );
00049     }
00050 
00051     QStrList signalnames = m_object->metaObject()->signalNames(false);
00052     for(char* c = signalnames.first(); c; c = signalnames.next()) {
00053         QCString s = c;
00054         addChild(s, new EventSignal(s, object, s) );
00055     }
00056 
00057     // Add functions to wrap QObject methods into callable
00058     // Kross objects.
00059 
00060     addFunction("propertyNames", &QtObject::propertyNames);
00061     addFunction("hasProperty", &QtObject::hasProperty);
00062     addFunction("getProperty", &QtObject::getProperty);
00063     addFunction("setProperty", &QtObject::setProperty);
00064 
00065     addFunction("slotNames", &QtObject::slotNames);
00066     addFunction("hasSlot", &QtObject::hasSlot);
00067     addFunction("slot", &QtObject::callSlot);
00068 
00069     addFunction("signalNames", &QtObject::signalNames);
00070     addFunction("hasSignal", &QtObject::hasSignal);
00071     addFunction("signal", &QtObject::emitSignal);
00072 
00073     addFunction("connect", &QtObject::connectSignal);
00074     addFunction("disconnect", &QtObject::disconnectSignal);
00075 }
00076 
00077 QtObject::~QtObject()
00078 {
00079 }
00080 
00081 const QString QtObject::getClassName() const
00082 {
00083     return "Kross::Api::QtObject";
00084 }
00085 
00086 QObject* QtObject::getObject()
00087 {
00088     return m_object;
00089 }
00090 
00091 QUObject* QtObject::toQUObject(const QString& signature, List::Ptr arguments)
00092 {
00093     int startpos = signature.find("(");
00094     int endpos = signature.findRev(")");
00095     if(startpos < 0 || startpos > endpos)
00096         throw Exception::Ptr( new Exception(QString("Invalid Qt signal or slot signature '%1'").arg(signature)) );
00097 
00098     //QString sig = signature.left(startpos);
00099     QString params = signature.mid(startpos + 1, endpos - startpos - 1);
00100     QStringList paramlist = QStringList::split(",", params); // this will fail on something like myslot(QMap<QString,QString> arg), but we don't care jet.
00101     uint paramcount = paramlist.size();
00102 
00103     // The first item in the QUObject-array is for the returnvalue
00104     // while everything >=1 are the passed parameters.
00105     QUObject* uo = new QUObject[ paramcount + 1 ];
00106     uo[0] = QUObject(); // empty placeholder for the returnvalue.
00107 
00108 //QString t;
00109 //for(int j=0; j<argcount; j++) t += "'" + Variant::toString(arguments->item(j)) + "' ";
00110 //krossdebug( QString("1 ---------------------: (%1) %2").arg(argcount).arg(t) );
00111 
00112     // Fill parameters.
00113     uint argcount = arguments ? arguments->count() : 0;
00114     for(uint i = 0; i < paramcount; i++) {
00115         if(paramlist[i].find("QString") >= 0) {
00116             const QString s = (argcount > i) ? Variant::toString(arguments->item(i)) : QString::null;
00117             //krossdebug(QString("EventSlot::toQUObject s=%1").arg(s));
00118             static_QUType_QString.set( &(uo[i + 1]), s );
00119         }
00120         //TODO handle int, long, char*, QStringList, etc.
00121         else {
00122             throw Exception::Ptr( new Exception(QString("Unknown Qt signal or slot argument '%1' in signature '%2'.").arg(paramlist[i]).arg(signature)) );
00123         }
00124     }
00125 
00126     return uo;
00127 }
00128 
00129 Kross::Api::Object::Ptr QtObject::propertyNames(Kross::Api::List::Ptr)
00130 {
00131     return new Kross::Api::Variant(
00132         QStringList::fromStrList(m_object->metaObject()->propertyNames(false)));
00133 }
00134 
00135 Kross::Api::Object::Ptr QtObject::hasProperty(Kross::Api::List::Ptr args)
00136 {
00137     return new Kross::Api::Variant(
00138         m_object->metaObject()->findProperty(Kross::Api::Variant::toString(args->item(0)).latin1(), false));
00139 }
00140 
00141 Kross::Api::Object::Ptr QtObject::getProperty(Kross::Api::List::Ptr args)
00142 {
00143     QVariant variant = m_object->property(Kross::Api::Variant::toString(args->item(0)).latin1());
00144     if(variant.type() == QVariant::Invalid)
00145         return 0;
00146     return new Kross::Api::Variant(variant);
00147 }
00148 
00149 Kross::Api::Object::Ptr QtObject::setProperty(Kross::Api::List::Ptr args)
00150 {
00151     return new Kross::Api::Variant(
00152            m_object->setProperty(
00153                Kross::Api::Variant::toString(args->item(0)).latin1(),
00154                Kross::Api::Variant::toVariant(args->item(1))
00155            ));
00156 }
00157 
00158 Kross::Api::Object::Ptr QtObject::slotNames(Kross::Api::List::Ptr)
00159 {
00160     return new Kross::Api::Variant(
00161            QStringList::fromStrList(m_object->metaObject()->slotNames(false)));
00162 }
00163 
00164 Kross::Api::Object::Ptr QtObject::hasSlot(Kross::Api::List::Ptr args)
00165 {
00166     return new Kross::Api::Variant(
00167            bool(m_object->metaObject()->slotNames(false).find(
00168                Kross::Api::Variant::toString(args->item(0)).latin1()
00169            ) != -1));
00170 }
00171 
00172 Kross::Api::Object::Ptr QtObject::callSlot(Kross::Api::List::Ptr args)
00173 {
00174 //TODO just call the child event ?!
00175     QString name = Kross::Api::Variant::toString(args->item(0));
00176     int slotid = m_object->metaObject()->findSlot(name.latin1(), false);
00177     if(slotid < 0)
00178         throw Exception::Ptr( new Exception(QString("No such slot '%1'.").arg(name)) );
00179 
00180     QUObject* uo = QtObject::toQUObject(name, args);
00181     m_object->qt_invoke(slotid, uo);
00182     delete [] uo;
00183 
00184     return new Variant( QVariant(true,0) );
00185 }
00186 
00187 Kross::Api::Object::Ptr QtObject::signalNames(Kross::Api::List::Ptr)
00188 {
00189     return new Kross::Api::Variant(
00190            QStringList::fromStrList(m_object->metaObject()->signalNames(false)));
00191 }
00192 
00193 Kross::Api::Object::Ptr QtObject::hasSignal(Kross::Api::List::Ptr args)
00194 {
00195     return new Kross::Api::Variant(
00196            bool(m_object->metaObject()->signalNames(false).find(
00197                Kross::Api::Variant::toString(args->item(0)).latin1()
00198            ) != -1));
00199 }
00200 
00201 Kross::Api::Object::Ptr QtObject::emitSignal(Kross::Api::List::Ptr args)
00202 {
00203     QString name = Kross::Api::Variant::toString(args->item(0));
00204     int signalid = m_object->metaObject()->findSignal(name.latin1(), false);
00205     if(signalid < 0)
00206         throw Exception::Ptr( new Exception(QString("No such signal '%1'.").arg(name)) );
00207     m_object->qt_invoke(signalid, 0); //TODO convert Kross::Api::List::Ptr => QUObject*
00208     return 0;
00209 }
00210 
00211 Kross::Api::Object::Ptr QtObject::connectSignal(Kross::Api::List::Ptr args)
00212 {
00213     QString signalname = Kross::Api::Variant::toString(args->item(0));
00214     QString signalsignatur = QString("2%1").arg(signalname);
00215     const char* signalsig = signalsignatur.latin1();
00216 
00217     QtObject* obj = Kross::Api::Object::fromObject<Kross::Api::QtObject>(args->item(1));
00218     QObject* o = obj->getObject();
00219     if(! o)
00220         throw Exception::Ptr( new Exception(QString("No such QObject receiver in '%1'.").arg(obj->getName())) );
00221 
00222     QString slotname = Kross::Api::Variant::toString(args->item(2));
00223     QString slotsignatur = QString("1%1").arg(slotname);
00224     const char* slotsig = slotsignatur.latin1();
00225 
00226     return new Kross::Api::Variant(
00227            QObject::connect(m_object, signalsig, o, slotsig));
00228 }
00229 
00230 Kross::Api::Object::Ptr QtObject::disconnectSignal(Kross::Api::List::Ptr)
00231 {
00232     //TODO
00233     return 0;
00234 }
00235 
KDE Home | KDE Accessibility Home | Description of Access Keys