summaryrefslogtreecommitdiffstats
path: root/kexi/plugins/macros/lib/metamethod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/plugins/macros/lib/metamethod.cpp')
-rw-r--r--kexi/plugins/macros/lib/metamethod.cpp344
1 files changed, 344 insertions, 0 deletions
diff --git a/kexi/plugins/macros/lib/metamethod.cpp b/kexi/plugins/macros/lib/metamethod.cpp
new file mode 100644
index 00000000..8aa4dc54
--- /dev/null
+++ b/kexi/plugins/macros/lib/metamethod.cpp
@@ -0,0 +1,344 @@
+/***************************************************************************
+ * This file is part of the KDE project
+ * copyright (C) 2005 by Sebastian Sauer ([email protected])
+ * copyright (C) 2005 by Tobi Krebs ([email protected])
+ *
+ * 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 <qobject.h>
+#include <qmetaobject.h>
+
+// to access the Qt3 QUObject API.
+#include <private/qucom_p.h>
+#include <private/qucomextra_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.
+ */
+ QString signature;
+
+ /**
+ * The signature tagname this @a MetaMethod has.
+ */
+ QString signaturetag;
+
+ /**
+ * The signature arguments this @a MetaMethod has.
+ */
+ QString 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 QString& 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(QString("Invalid signature \"%1\"").arg(d->signature));
+ }
+
+ d->signaturetag = d->signature.left(startpos).stripWhiteSpace();
+ if(d->signaturetag.isEmpty()) {
+ throw Exception(QString("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(QString("No closing template-definiton in signature \"%1\"").arg(d->signature));
+ }
+ commapos = d->signaturearguments.find(",", endtemplatepos);
+ }
+
+ if(commapos > 0) {
+ QString 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 {
+ QString 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 QString MetaMethod::signature() const
+{
+ return d->signature;
+}
+
+const QString MetaMethod::signatureTag() const
+{
+ return d->signaturetag;
+}
+
+const QString MetaMethod::signatureArguments() const
+{
+ return d->signaturearguments;
+}
+
+MetaMethod::Type MetaMethod::type() const
+{
+ return d->type;
+}
+
+MetaParameter::List MetaMethod::arguments() const
+{
+ return d->arguments;
+}
+
+QUObject* MetaMethod::toQUObject(Variable::List arguments)
+{
+ uint argsize = d->arguments.size();
+
+ if(arguments.size() <= argsize) {
+ throw Exception(QString("To less arguments for slot with siganture \"%1\"").arg(d->signature));
+ }
+
+ // The first item in the QUObject-array is for the returnvalue
+ // while everything >=1 are the passed parameters.
+ QUObject* uo = new QUObject[ argsize + 1 ];
+
+ uo[0] = QUObject(); // 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(QString("Variable is undefined !"));
+ }
+
+ if(metaargument->type() != variable->type()) {
+ throw Exception(QString("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] = QUObject();
+ } break;
+
+ case Variable::TypeVariant: {
+ kdDebug() << "Variable::TypeVariant" << endl;
+
+ const QVariant variant = variable->variant();
+ switch(metaargument->variantType()) {
+ case QVariant::String: {
+ const QString s = variant.toString();
+ static_QUType_QString.set( &(uo[i + 1]), s );
+ } break;
+ case QVariant::Int: {
+ const int j = variant.toInt();
+ static_QUType_int.set( &(uo[i + 1]), j );
+ } break;
+ case QVariant::Bool: {
+ const bool b = variant.toBool();
+ static_QUType_bool.set( &(uo[i + 1]), b );
+ } break;
+ case QVariant::Double: {
+ const double d = variant.toDouble();
+ static_QUType_double.set( &(uo[i + 1]), d );
+ } break;
+ case QVariant::Invalid: {
+ static_QUType_QVariant.set( &(uo[i + 1]), variant );
+ }
+
+ /*FIXME
+ static_QUType_charstar
+ static_QUType_ptr.get(uo); QObject *qobj = (QObject *)(ptr);
+ */
+
+ default: {
+ throw Exception(QString("Invalid parameter !!!!!!!!!!!!!!!!!!!!!!!"));
+ } break;
+ }
+ } break;
+
+ case Variable::TypeObject: {
+ kdDebug() << "Variable::TypeObject" << endl;
+
+ const QObject* obj = arguments[i + 1]->object();
+ if(! obj) { //FIXME: move check to MetaParameter?!
+ throw Exception(QString("No QObject !"));
+ }
+ static_QUType_ptr.set( &(uo[i + 1]), obj );
+ } break;
+
+ default: {
+ throw Exception(QString("Invalid variable type"));
+ } break;
+ }
+
+ }
+
+ return uo;
+}
+
+KSharedPtr<Variable> MetaMethod::toVariable(QUObject* uo)
+{
+ const QString desc( uo->type->desc() );
+
+ if(desc == "null") {
+ return new Variable();
+ }
+
+ if(desc == "QString") {
+ const QString s = static_QUType_QString.get(uo);
+ return new Variable(s);
+ }
+
+ if(desc == "int") {
+ const int j = static_QUType_int.get(uo);
+ return new Variable(j);
+ }
+
+ if(desc == "bool") {
+ const bool b = static_QUType_bool.get(uo);
+ return new Variable(b);
+ }
+
+ if(desc == "double") {
+ const double d = static_QUType_double.get(uo);
+ return new Variable(d);
+ }
+
+ if(desc == "QVariant") {
+ QVariant v = static_QUType_QVariant.get(uo);
+ return new Variable(v);
+ }
+
+ throw Exception(QString("Invalid parameter '%1'").arg(desc));
+}
+
+Variable::List MetaMethod::toVariableList(QUObject* 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.");
+ }
+
+ QObject* obj = d->object->object();
+ KSharedPtr<Variable> returnvalue;
+ QUObject* qu = 0;
+
+ try {
+ qu = toQUObject(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 QUObject array and
+ kdDebug() << "EXCEPTION in KoMacro::MetaMethod::invoke(Variable::List)" << endl;
+ throw Exception(e); // re-throw exception
+ }
+
+ delete [] qu;
+ return returnvalue;
+}