You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
8.8 KiB
345 lines
8.8 KiB
/***************************************************************************
|
|
* This file is part of the KDE project
|
|
* copyright (C) 2005 by Sebastian Sauer (mail@dipe.org)
|
|
* copyright (C) 2005 by Tobi Krebs (tobi.krebs@gmail.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library 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
|
|
* Library General Public License for more details.
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
***************************************************************************/
|
|
|
|
#include "metamethod.h"
|
|
#include "metaobject.h"
|
|
#include "metaparameter.h"
|
|
#include "variable.h"
|
|
#include "exception.h"
|
|
|
|
#include <tqobject.h>
|
|
#include <tqmetaobject.h>
|
|
|
|
// to access the TQt3 TQUObject API.
|
|
#include <private/tqucom_p.h>
|
|
#include <private/tqucomextra_p.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
using namespace KoMacro;
|
|
|
|
namespace KoMacro {
|
|
|
|
/**
|
|
* @internal d-pointer class to be more flexible on future extension of the
|
|
* functionality without to much risk to break the binary compatibility.
|
|
*/
|
|
class MetaMethod::Private
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* The signature this @a MetaMethod has.
|
|
*/
|
|
TQString signature;
|
|
|
|
/**
|
|
* The signature tagname this @a MetaMethod has.
|
|
*/
|
|
TQString signaturetag;
|
|
|
|
/**
|
|
* The signature arguments this @a MetaMethod has.
|
|
*/
|
|
TQString signaturearguments;
|
|
|
|
/**
|
|
* Cached signature arguments parsed into a list
|
|
* of @a MetaParameter instances.
|
|
*/
|
|
MetaParameter::List arguments;
|
|
|
|
/**
|
|
* The @a MetaObject this @a MetaMethod belongs to or is NULL
|
|
* if this @a MetaMethod doesn't belong to any @a MetaObject
|
|
* yet.
|
|
*/
|
|
KSharedPtr<MetaObject> object;
|
|
|
|
/**
|
|
* The @a MetaMethod::Type this method provides access
|
|
* to.
|
|
*/
|
|
MetaMethod::Type type;
|
|
};
|
|
|
|
}
|
|
|
|
MetaMethod::MetaMethod(const TQString& signature, Type type, KSharedPtr<MetaObject> object)
|
|
: KShared()
|
|
, d( new Private() ) // create the private d-pointer instance.
|
|
{
|
|
d->signature = signature;
|
|
d->object = object;
|
|
d->type = type;
|
|
|
|
int startpos = d->signature.find("(");
|
|
int endpos = d->signature.findRev(")");
|
|
if(startpos < 0 || startpos > endpos) {
|
|
throw Exception(TQString("Invalid signature \"%1\"").arg(d->signature));
|
|
}
|
|
|
|
d->signaturetag = d->signature.left(startpos).stripWhiteSpace();
|
|
if(d->signaturetag.isEmpty()) {
|
|
throw Exception(TQString("Invalid tagname in signature \"%1\"").arg(d->signature));
|
|
}
|
|
|
|
d->signaturearguments = d->signature.mid(startpos + 1, endpos - startpos - 1).stripWhiteSpace();
|
|
|
|
do {
|
|
int commapos = d->signaturearguments.find(",");
|
|
int starttemplatepos = d->signaturearguments.find("<");
|
|
if(starttemplatepos >= 0 && (commapos < 0 || starttemplatepos < commapos)) {
|
|
int endtemplatepos = d->signaturearguments.find(">", starttemplatepos);
|
|
if(endtemplatepos <= 0) {
|
|
throw Exception(TQString("No closing template-definiton in signature \"%1\"").arg(d->signature));
|
|
}
|
|
commapos = d->signaturearguments.find(",", endtemplatepos);
|
|
}
|
|
|
|
if(commapos > 0) {
|
|
TQString s = d->signaturearguments.left(commapos).stripWhiteSpace();
|
|
if(! s.isEmpty()) {
|
|
d->arguments.append( new MetaParameter(s) );
|
|
}
|
|
d->signaturearguments = d->signaturearguments.right(d->signaturearguments.length() - commapos - 1);
|
|
}
|
|
else {
|
|
TQString s = d->signaturearguments.stripWhiteSpace();
|
|
if(! s.isEmpty()) {
|
|
d->arguments.append( new MetaParameter(s) );
|
|
}
|
|
break;
|
|
}
|
|
} while(true);
|
|
}
|
|
|
|
MetaMethod::~MetaMethod()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
KSharedPtr<MetaObject> const MetaMethod::object() const
|
|
{
|
|
return d->object;
|
|
}
|
|
|
|
const TQString MetaMethod::signature() const
|
|
{
|
|
return d->signature;
|
|
}
|
|
|
|
const TQString MetaMethod::signatureTag() const
|
|
{
|
|
return d->signaturetag;
|
|
}
|
|
|
|
const TQString MetaMethod::signatureArguments() const
|
|
{
|
|
return d->signaturearguments;
|
|
}
|
|
|
|
MetaMethod::Type MetaMethod::type() const
|
|
{
|
|
return d->type;
|
|
}
|
|
|
|
MetaParameter::List MetaMethod::arguments() const
|
|
{
|
|
return d->arguments;
|
|
}
|
|
|
|
TQUObject* MetaMethod::toTQUObject(Variable::List arguments)
|
|
{
|
|
uint argsize = d->arguments.size();
|
|
|
|
if(arguments.size() <= argsize) {
|
|
throw Exception(TQString("To less arguments for slot with siganture \"%1\"").arg(d->signature));
|
|
}
|
|
|
|
// The first item in the TQUObject-array is for the returnvalue
|
|
// while everything >=1 are the passed parameters.
|
|
TQUObject* uo = new TQUObject[ argsize + 1 ];
|
|
|
|
uo[0] = TQUObject(); // empty placeholder for the returnvalue.
|
|
|
|
for(uint i = 0; i < argsize; i++) {
|
|
KSharedPtr<MetaParameter> metaargument = d->arguments[i];
|
|
KSharedPtr<Variable> variable = arguments[i + 1];
|
|
|
|
if ( !variable ) {
|
|
throw Exception(TQString("Variable is undefined !"));
|
|
}
|
|
|
|
if(metaargument->type() != variable->type()) {
|
|
throw Exception(TQString("Wrong variable type in method \"%1\". Expected \"%2\" but got \"%3\"").arg(d->signature).arg(metaargument->type()).arg(variable->type()));
|
|
}
|
|
|
|
switch(metaargument->type()) {
|
|
|
|
case Variable::TypeNone: {
|
|
kdDebug() << "Variable::TypeNone" << endl;
|
|
uo[i + 1] = TQUObject();
|
|
} break;
|
|
|
|
case Variable::TypeVariant: {
|
|
kdDebug() << "Variable::TypeVariant" << endl;
|
|
|
|
const TQVariant variant = variable->variant();
|
|
switch(metaargument->variantType()) {
|
|
case TQVariant::String: {
|
|
const TQString s = variant.toString();
|
|
static_TQUType_TQString.set( &(uo[i + 1]), s );
|
|
} break;
|
|
case TQVariant::Int: {
|
|
const int j = variant.toInt();
|
|
static_TQUType_int.set( &(uo[i + 1]), j );
|
|
} break;
|
|
case TQVariant::Bool: {
|
|
const bool b = variant.toBool();
|
|
static_TQUType_bool.set( &(uo[i + 1]), b );
|
|
} break;
|
|
case TQVariant::Double: {
|
|
const double d = variant.toDouble();
|
|
static_TQUType_double.set( &(uo[i + 1]), d );
|
|
} break;
|
|
case TQVariant::Invalid: {
|
|
static_TQUType_TQVariant.set( &(uo[i + 1]), variant );
|
|
}
|
|
|
|
/*FIXME
|
|
static_TQUType_charstar
|
|
static_TQUType_ptr.get(uo); TQObject *qobj = (TQObject *)(ptr);
|
|
*/
|
|
|
|
default: {
|
|
throw Exception(TQString("Invalid parameter !!!!!!!!!!!!!!!!!!!!!!!"));
|
|
} break;
|
|
}
|
|
} break;
|
|
|
|
case Variable::TypeObject: {
|
|
kdDebug() << "Variable::TypeObject" << endl;
|
|
|
|
const TQObject* obj = arguments[i + 1]->object();
|
|
if(! obj) { //FIXME: move check to MetaParameter?!
|
|
throw Exception(TQString("No TQObject !"));
|
|
}
|
|
static_TQUType_ptr.set( &(uo[i + 1]), obj );
|
|
} break;
|
|
|
|
default: {
|
|
throw Exception(TQString("Invalid variable type"));
|
|
} break;
|
|
}
|
|
|
|
}
|
|
|
|
return uo;
|
|
}
|
|
|
|
KSharedPtr<Variable> MetaMethod::toVariable(TQUObject* uo)
|
|
{
|
|
const TQString desc( uo->type->desc() );
|
|
|
|
if(desc == "null") {
|
|
return new Variable();
|
|
}
|
|
|
|
if(desc == TQSTRING_OBJECT_NAME_STRING) {
|
|
const TQString s = static_TQUType_TQString.get(uo);
|
|
return new Variable(s);
|
|
}
|
|
|
|
if(desc == "int") {
|
|
const int j = static_TQUType_int.get(uo);
|
|
return new Variable(j);
|
|
}
|
|
|
|
if(desc == "bool") {
|
|
const bool b = static_TQUType_bool.get(uo);
|
|
return new Variable(b);
|
|
}
|
|
|
|
if(desc == "double") {
|
|
const double d = static_TQUType_double.get(uo);
|
|
return new Variable(d);
|
|
}
|
|
|
|
if(desc == "TQVariant") {
|
|
TQVariant v = static_TQUType_TQVariant.get(uo);
|
|
return new Variable(v);
|
|
}
|
|
|
|
throw Exception(TQString("Invalid parameter '%1'").arg(desc));
|
|
}
|
|
|
|
Variable::List MetaMethod::toVariableList(TQUObject* uo)
|
|
{
|
|
Variable::List list;
|
|
|
|
MetaParameter::List::ConstIterator it, end( d->arguments.constEnd() );
|
|
for( it = d->arguments.constBegin(); it != end; ++it) {
|
|
list.append( toVariable(uo) );
|
|
uo++;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
KSharedPtr<Variable> MetaMethod::invoke(Variable::List arguments)
|
|
{
|
|
kdDebug() << "KSharedPtr<Variable> MetaMethod::invoke(Variable::List arguments)" << endl;
|
|
|
|
if(! d->object) {
|
|
throw Exception("MetaObject is undefined.");
|
|
}
|
|
|
|
TQObject* obj = d->object->object();
|
|
KSharedPtr<Variable> returnvalue;
|
|
TQUObject* qu = 0;
|
|
|
|
try {
|
|
qu = toTQUObject(arguments);
|
|
|
|
switch( d->type ) {
|
|
case Signal: {
|
|
int index = d->object->indexOfSignal( d->signature.latin1() );
|
|
obj->qt_emit(index, qu);
|
|
} break;
|
|
case Slot: {
|
|
int index = d->object->indexOfSlot( d->signature.latin1() );
|
|
obj->qt_invoke(index, qu);
|
|
} break;
|
|
default: {
|
|
throw Exception("Unknown type.");
|
|
} break;
|
|
}
|
|
returnvalue = toVariable( &qu[0] );
|
|
}
|
|
catch(Exception& e) {
|
|
delete [] qu; // free the TQUObject array and
|
|
kdDebug() << "EXCEPTION in KoMacro::MetaMethod::invoke(Variable::List)" << endl;
|
|
throw Exception(e); // re-throw exception
|
|
}
|
|
|
|
delete [] qu;
|
|
return returnvalue;
|
|
}
|