kexi

metamethod.cpp

00001 /***************************************************************************
00002  * This file is part of the KDE project
00003  * copyright (C) 2005 by Sebastian Sauer (mail@dipe.org)
00004  * copyright (C) 2005 by Tobi Krebs (tobi.krebs@gmail.com)
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 "metamethod.h"
00021 #include "metaobject.h"
00022 #include "metaparameter.h"
00023 #include "variable.h"
00024 #include "exception.h"
00025 
00026 #include <qobject.h>
00027 #include <qmetaobject.h>
00028 
00029 // to access the Qt3 QUObject API.
00030 #include <private/qucom_p.h>
00031 #include <private/qucomextra_p.h>
00032 
00033 #include <kdebug.h>
00034 
00035 using namespace KoMacro;
00036 
00037 namespace KoMacro {
00038 
00043     class MetaMethod::Private
00044     {
00045         public:
00046 
00050             QString signature;
00051 
00055             QString signaturetag;
00056 
00060             QString signaturearguments;
00061 
00066             MetaParameter::List arguments;
00067 
00073             KSharedPtr<MetaObject> object;
00074 
00079             MetaMethod::Type type;
00080     };
00081 
00082 }
00083 
00084 MetaMethod::MetaMethod(const QString& signature, Type type, KSharedPtr<MetaObject> object)
00085     : KShared()
00086     , d( new Private() ) // create the private d-pointer instance.
00087 {
00088     d->signature = signature;
00089     d->object = object;
00090     d->type = type;
00091 
00092     int startpos = d->signature.find("(");
00093     int endpos = d->signature.findRev(")");
00094     if(startpos < 0 || startpos > endpos) {
00095         throw Exception(QString("Invalid signature \"%1\"").arg(d->signature));
00096     }
00097 
00098     d->signaturetag = d->signature.left(startpos).stripWhiteSpace();
00099     if(d->signaturetag.isEmpty()) {
00100         throw Exception(QString("Invalid tagname in signature \"%1\"").arg(d->signature));
00101     }
00102 
00103     d->signaturearguments = d->signature.mid(startpos + 1, endpos - startpos - 1).stripWhiteSpace();
00104 
00105     do {
00106         int commapos = d->signaturearguments.find(",");
00107         int starttemplatepos = d->signaturearguments.find("<");
00108         if(starttemplatepos >= 0 && (commapos < 0 || starttemplatepos < commapos)) {
00109             int endtemplatepos = d->signaturearguments.find(">", starttemplatepos);
00110             if(endtemplatepos <= 0) {
00111                 throw Exception(QString("No closing template-definiton in signature \"%1\"").arg(d->signature));
00112             }
00113             commapos = d->signaturearguments.find(",", endtemplatepos);
00114         }
00115 
00116         if(commapos > 0) {
00117             QString s = d->signaturearguments.left(commapos).stripWhiteSpace();
00118             if(! s.isEmpty()) {
00119                 d->arguments.append( new MetaParameter(s) );
00120             }
00121             d->signaturearguments = d->signaturearguments.right(d->signaturearguments.length() - commapos - 1);
00122         }
00123         else {
00124             QString s = d->signaturearguments.stripWhiteSpace();
00125             if(! s.isEmpty()) {
00126                 d->arguments.append( new MetaParameter(s) );
00127             }
00128             break;
00129         }
00130     } while(true);
00131 }
00132 
00133 MetaMethod::~MetaMethod()
00134 {
00135     delete d;
00136 }
00137 
00138 KSharedPtr<MetaObject> const MetaMethod::object() const
00139 {
00140     return d->object;
00141 }
00142 
00143 const QString MetaMethod::signature() const
00144 {
00145     return d->signature;
00146 }
00147 
00148 const QString MetaMethod::signatureTag() const
00149 {
00150     return d->signaturetag;
00151 }
00152 
00153 const QString MetaMethod::signatureArguments() const
00154 {
00155     return d->signaturearguments;
00156 }
00157 
00158 MetaMethod::Type MetaMethod::type() const
00159 {
00160     return d->type;
00161 }
00162 
00163 MetaParameter::List MetaMethod::arguments() const
00164 {
00165     return d->arguments;
00166 }
00167 
00168 QUObject* MetaMethod::toQUObject(Variable::List arguments)
00169 {
00170     uint argsize = d->arguments.size();
00171 
00172     if(arguments.size() <= argsize) {
00173         throw Exception(QString("To less arguments for slot with siganture \"%1\"").arg(d->signature));
00174     }
00175 
00176     // The first item in the QUObject-array is for the returnvalue
00177     // while everything >=1 are the passed parameters.
00178     QUObject* uo = new QUObject[ argsize + 1 ];
00179 
00180     uo[0] = QUObject(); // empty placeholder for the returnvalue.
00181 
00182     for(uint i = 0; i < argsize; i++) {
00183         KSharedPtr<MetaParameter> metaargument = d->arguments[i];
00184         KSharedPtr<Variable> variable = arguments[i + 1];
00185 
00186         if ( !variable ) {
00187             throw Exception(QString("Variable is undefined !"));
00188         }
00189     
00190         if(metaargument->type() != variable->type()) {
00191             throw Exception(QString("Wrong variable type in method \"%1\". Expected \"%2\" but got \"%3\"").arg(d->signature).arg(metaargument->type()).arg(variable->type()));
00192         }
00193 
00194         switch(metaargument->type()) {
00195 
00196             case Variable::TypeNone: {
00197                 kdDebug() << "Variable::TypeNone" << endl;
00198                 uo[i + 1] = QUObject();
00199             } break;
00200 
00201             case Variable::TypeVariant:  {
00202                 kdDebug() << "Variable::TypeVariant" << endl;
00203 
00204                 const QVariant variant = variable->variant();
00205                 switch(metaargument->variantType()) {
00206                     case QVariant::String: {
00207                         const QString s = variant.toString();
00208                         static_QUType_QString.set( &(uo[i + 1]), s );
00209                     } break;
00210                     case QVariant::Int: {
00211                         const int j = variant.toInt();
00212                         static_QUType_int.set( &(uo[i + 1]), j );
00213                     } break;
00214                     case QVariant::Bool: {
00215                         const bool b = variant.toBool();
00216                         static_QUType_bool.set( &(uo[i + 1]), b );
00217                     } break;
00218                     case QVariant::Double: {
00219                         const double d = variant.toDouble();
00220                         static_QUType_double.set( &(uo[i + 1]), d );
00221                     } break;
00222                     case QVariant::Invalid: {
00223                         static_QUType_QVariant.set( &(uo[i + 1]), variant );
00224                     }
00225 
00226                     /*FIXME
00227                     static_QUType_charstar
00228                     static_QUType_ptr.get(uo); QObject *qobj = (QObject *)(ptr);
00229                     */
00230 
00231                     default: {
00232                         throw Exception(QString("Invalid parameter !!!!!!!!!!!!!!!!!!!!!!!"));
00233                     } break;
00234                 }
00235             } break;
00236 
00237             case Variable::TypeObject:  {
00238                 kdDebug() << "Variable::TypeObject" << endl;
00239 
00240                 const QObject* obj = arguments[i + 1]->object();
00241                 if(! obj) { //FIXME: move check to MetaParameter?!
00242                     throw Exception(QString("No QObject !"));
00243                 }
00244                 static_QUType_ptr.set( &(uo[i + 1]), obj );
00245             } break;
00246 
00247             default:  {
00248                 throw Exception(QString("Invalid variable type"));
00249             } break;
00250         }
00251 
00252     }
00253 
00254     return uo;
00255 }
00256 
00257 KSharedPtr<Variable> MetaMethod::toVariable(QUObject* uo)
00258 {
00259     const QString desc( uo->type->desc() );
00260 
00261     if(desc == "null") {
00262         return new Variable();
00263     }
00264 
00265     if(desc == "QString") {
00266         const QString s = static_QUType_QString.get(uo);
00267         return new Variable(s);
00268     }
00269 
00270     if(desc == "int") {
00271         const int j = static_QUType_int.get(uo);
00272         return new Variable(j);
00273     }
00274 
00275     if(desc == "bool") {
00276         const bool b = static_QUType_bool.get(uo);
00277         return new Variable(b);
00278     }
00279 
00280     if(desc == "double") {
00281         const double d = static_QUType_double.get(uo);
00282         return new Variable(d);
00283     }
00284 
00285     if(desc == "QVariant") {
00286         QVariant v = static_QUType_QVariant.get(uo);
00287         return new Variable(v);
00288     }
00289 
00290     throw Exception(QString("Invalid parameter '%1'").arg(desc));
00291 }
00292 
00293 Variable::List MetaMethod::toVariableList(QUObject* uo)
00294 {
00295     Variable::List list;
00296 
00297     MetaParameter::List::ConstIterator it, end( d->arguments.constEnd() );
00298     for( it = d->arguments.constBegin(); it != end; ++it) {
00299         list.append( toVariable(uo) );
00300         uo++;
00301     }
00302 
00303     return list;
00304 }
00305 
00306 KSharedPtr<Variable> MetaMethod::invoke(Variable::List arguments)
00307 {
00308     kdDebug() << "KSharedPtr<Variable> MetaMethod::invoke(Variable::List arguments)" << endl; 
00309 
00310     if(! d->object) {
00311         throw Exception("MetaObject is undefined.");
00312     }
00313 
00314     QObject* obj = d->object->object();
00315     KSharedPtr<Variable> returnvalue;
00316     QUObject* qu = 0;
00317 
00318     try {
00319         qu = toQUObject(arguments);
00320 
00321         switch( d->type ) {
00322             case Signal: {
00323                 int index = d->object->indexOfSignal( d->signature.latin1() );
00324                 obj->qt_emit(index, qu);
00325             } break;
00326             case Slot: {
00327                 int index = d->object->indexOfSlot( d->signature.latin1() );
00328                 obj->qt_invoke(index, qu);
00329             } break;
00330             default: {
00331                 throw Exception("Unknown type.");
00332             } break;
00333         }
00334         returnvalue = toVariable( &qu[0] );
00335     }
00336     catch(Exception& e) {
00337         delete [] qu; // free the QUObject array and
00338         kdDebug() << "EXCEPTION in KoMacro::MetaMethod::invoke(Variable::List)" << endl;
00339         throw Exception(e); // re-throw exception
00340     }
00341 
00342     delete [] qu;
00343     return returnvalue;
00344 }
KDE Home | KDE Accessibility Home | Description of Access Keys