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(Object::Ptr parent, QObject* object, const QString& name)
00039     : Kross::Api::Class<QtObject>(name.isEmpty() ? object->name() : name, parent)
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( new EventSlot(s, this, 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( new EventSignal(s, this, 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         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00063     addFunction("getProperty", &QtObject::getProperty,
00064         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00065     addFunction("setProperty", &QtObject::setProperty,
00066         Kross::Api::ArgumentList()
00067             << Kross::Api::Argument("Kross::Api::Variant::String")
00068             << Kross::Api::Argument("Kross::Api::Variant"));
00069 
00070     addFunction("slotNames", &QtObject::slotNames);
00071     addFunction("hasSlot", &QtObject::hasSlot,
00072         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00073     addFunction("slot", &QtObject::callSlot,
00074         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00075 
00076     addFunction("signalNames", &QtObject::signalNames);
00077     addFunction("hasSignal", &QtObject::hasSignal,
00078         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00079     addFunction("signal", &QtObject::emitSignal,
00080         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00081 
00082     addFunction("connect", &QtObject::connectSignal,
00083         Kross::Api::ArgumentList()
00084             << Kross::Api::Argument("Kross::Api::Variant::String")
00085             << Kross::Api::Argument("Kross::Api::QtObject")
00086             << Kross::Api::Argument("Kross::Api::Variant::String"));
00087     addFunction("disconnect", &QtObject::disconnectSignal,
00088         Kross::Api::ArgumentList() << Kross::Api::Argument("Kross::Api::Variant::String"));
00089 }
00090 
00091 QtObject::~QtObject()
00092 {
00093 }
00094 
00095 const QString QtObject::getClassName() const
00096 {
00097     return "Kross::Api::QtObject";
00098 }
00099 
00100 QObject* QtObject::getObject()
00101 {
00102     return m_object;
00103 }
00104 
00105 QUObject* QtObject::toQUObject(const QString& signature, List::Ptr arguments)
00106 {
00107     int startpos = signature.find("(");
00108     int endpos = signature.findRev(")");
00109     if(startpos < 0 || startpos > endpos)
00110         throw Exception::Ptr( new Exception(QString("Invalid Qt signal or slot signature '%1'").arg(signature)) );
00111 
00112     //QString sig = signature.left(startpos);
00113     QString params = signature.mid(startpos + 1, endpos - startpos - 1);
00114     QStringList paramlist = QStringList::split(",", params); // this will fail on something like myslot(QMap<QString,QString> arg), but we don't care jet.
00115     uint paramcount = paramlist.size();
00116 
00117     // The first item in the QUObject-array is for the returnvalue
00118     // while everything >=1 are the passed parameters.
00119     QUObject* uo = new QUObject[ paramcount + 1 ];
00120     uo[0] = QUObject(); // empty placeholder for the returnvalue.
00121 
00122 //QString t;
00123 //for(int j=0; j<argcount; j++) t += "'" + Variant::toString(arguments->item(j)) + "' ";
00124 //kdDebug()<<"1 --------------------- ("<<argcount<<"): "<<t<<endl;
00125 
00126     // Fill parameters.
00127     uint argcount = arguments ? arguments->count() : 0;
00128     for(uint i = 0; i < paramcount; i++) {
00129         if(paramlist[i].find("QString") >= 0) {
00130             const QString s = (argcount > i) ? Variant::toString(arguments->item(i)) : QString::null;
00131             //kdDebug()<<"EventSlot::toQUObject s="<<s<<endl;
00132             static_QUType_QString.set( &(uo[i + 1]), s );
00133         }
00134         //TODO handle int, long, char*, QStringList, etc.
00135         else {
00136             throw Exception::Ptr( new Exception(QString("Unknown Qt signal or slot argument '%1' in signature '%2'.").arg(paramlist[i]).arg(signature)) );
00137         }
00138     }
00139 
00140 //kdDebug()<<"2 --------------------- "<<endl;
00141     return uo;
00142 }
00143 
00144 Kross::Api::Object::Ptr QtObject::propertyNames(Kross::Api::List::Ptr)
00145 {
00146     return new Kross::Api::Variant(
00147         QStringList::fromStrList(m_object->metaObject()->propertyNames(false)),
00148         "Kross::Api::QtObject::propertyNames::Variant::StringList");
00149 }
00150 
00151 Kross::Api::Object::Ptr QtObject::hasProperty(Kross::Api::List::Ptr args)
00152 {
00153     return new Kross::Api::Variant(
00154         m_object->metaObject()->findProperty(Kross::Api::Variant::toString(args->item(0)).latin1(), false),
00155         "Kross::Api::QtObject::hasProperty::Variant::Bool");
00156 }
00157 
00158 Kross::Api::Object::Ptr QtObject::getProperty(Kross::Api::List::Ptr args)
00159 {
00160     QVariant variant = m_object->property(Kross::Api::Variant::toString(args->item(0)).latin1());
00161     if(variant.type() == QVariant::Invalid)
00162         return 0;
00163     return new Kross::Api::Variant(variant, "Kross::Api::QtObject::getProperty::Variant");
00164 }
00165 
00166 Kross::Api::Object::Ptr QtObject::setProperty(Kross::Api::List::Ptr args)
00167 {
00168     return new Kross::Api::Variant(
00169            m_object->setProperty(
00170                Kross::Api::Variant::toString(args->item(0)).latin1(),
00171                Kross::Api::Variant::toVariant(args->item(1))
00172            ),
00173            "Kross::Api::QtObject::setProperty::Variant::Bool");
00174 }
00175 
00176 Kross::Api::Object::Ptr QtObject::slotNames(Kross::Api::List::Ptr)
00177 {
00178     return new Kross::Api::Variant(
00179            QStringList::fromStrList(m_object->metaObject()->slotNames(false)),
00180            "Kross::Api::QtObject::slotNames::Variant::StringList");
00181 }
00182 
00183 Kross::Api::Object::Ptr QtObject::hasSlot(Kross::Api::List::Ptr args)
00184 {
00185     return new Kross::Api::Variant(
00186            bool(m_object->metaObject()->slotNames(false).find(
00187                Kross::Api::Variant::toString(args->item(0)).latin1()
00188            ) != -1),
00189            "Kross::Api::QtObject::hasSlot::Variant::Bool");
00190 }
00191 
00192 Kross::Api::Object::Ptr QtObject::callSlot(Kross::Api::List::Ptr args)
00193 {
00194 //TODO just call the child event ?!
00195     QString name = Kross::Api::Variant::toString(args->item(0));
00196     int slotid = m_object->metaObject()->findSlot(name.latin1(), false);
00197     if(slotid < 0)
00198         throw Exception::Ptr( new Exception(QString("No such slot '%1'.").arg(name)) );
00199 
00200     QUObject* uo = QtObject::toQUObject(name, args);
00201     m_object->qt_invoke(slotid, uo);
00202     delete [] uo;
00203 
00204     return new Variant(true, "Kross::Api::QtObject::Bool");
00205 }
00206 
00207 Kross::Api::Object::Ptr QtObject::signalNames(Kross::Api::List::Ptr)
00208 {
00209     return new Kross::Api::Variant(
00210            QStringList::fromStrList(m_object->metaObject()->signalNames(false)),
00211            "Kross::Api::QtObject::signalNames::Variant::StringList");
00212 }
00213 
00214 Kross::Api::Object::Ptr QtObject::hasSignal(Kross::Api::List::Ptr args)
00215 {
00216     return new Kross::Api::Variant(
00217            bool(m_object->metaObject()->signalNames(false).find(
00218                Kross::Api::Variant::toString(args->item(0)).latin1()
00219            ) != -1),
00220            "Kross::Api::QtObject::hasSignal::Variant::Bool");
00221 }
00222 
00223 Kross::Api::Object::Ptr QtObject::emitSignal(Kross::Api::List::Ptr args)
00224 {
00225     QString name = Kross::Api::Variant::toString(args->item(0));
00226     int signalid = m_object->metaObject()->findSignal(name.latin1(), false);
00227     if(signalid < 0)
00228         throw Exception::Ptr( new Exception(QString("No such signal '%1'.").arg(name)) );
00229     m_object->qt_invoke(signalid, 0); //TODO convert Kross::Api::List::Ptr => QUObject*
00230     return 0;
00231 }
00232 
00233 Kross::Api::Object::Ptr QtObject::connectSignal(Kross::Api::List::Ptr args)
00234 {
00235     QString signalname = Kross::Api::Variant::toString(args->item(0));
00236     QString signalsignatur = QString("2%1").arg(signalname);
00237     const char* signalsig = signalsignatur.latin1();
00238 
00239     QtObject* obj = Kross::Api::Object::fromObject<Kross::Api::QtObject>(args->item(1));
00240     QObject* o = obj->getObject();
00241     if(! o)
00242         throw Exception::Ptr( new Exception(QString("No such QObject receiver in '%1'.").arg(obj->getName())) );
00243 
00244     QString slotname = Kross::Api::Variant::toString(args->item(2));
00245     QString slotsignatur = QString("1%1").arg(slotname);
00246     const char* slotsig = slotsignatur.latin1();
00247 
00248     return new Kross::Api::Variant(
00249            QObject::connect(m_object, signalsig, o, slotsig),
00250            "Kross::Api::QtObject::connect::Bool");
00251 }
00252 
00253 Kross::Api::Object::Ptr QtObject::disconnectSignal(Kross::Api::List::Ptr)
00254 {
00255     //TODO
00256     return 0;
00257 }
00258 
KDE Home | KDE Accessibility Home | Description of Access Keys