/***************************************************************************
* 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 - > tqt_emit ( index , qu ) ;
} break ;
case Slot : {
int index = d - > object - > indexOfSlot ( d - > signature . latin1 ( ) ) ;
obj - > tqt_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 ;
}