Commit a47475d6 authored by Sebastian Sauer's avatar Sebastian Sauer
Browse files

* Extended kspread/Functions.* to be able to dynamic add functions from within a plugin.

* Initial implementation of "Scripting Functions" which are KSpread Function's that will be able to reference scripts. It's disabled and will stay till I refactored package-handling to provide trusted scripts.
* cleanup, unittest++, etc.

CC_MAIL: allan@curtisnz.com


svn path=/trunk/koffice/; revision=600284
parent 3ecae5a5
......@@ -4,13 +4,6 @@ Always valid:
* more performance
* more documentations, tutorials, examples, ...
* more unittests
* maybe one day we like to be able to execute untrusted scripts what
in turn means, that we could need a secure interpreter-backend.
KjsEmbed does not fit into that category currently and is insecure
like Python. Ruby comes at least with security-levels. So, either
extend KjsEmbed to be as secure as Kjs, eval and propably use Ruby
security-levels, reintroduce Zope's RestrictedPython for python or
just implement a Java-backend and use it's strong sandbox.
* add Kross-support to other KOffice-applications.
Core:
......@@ -18,11 +11,14 @@ Core:
functions a script provides either as KActionCollection where each
function is a KAction or let Action dynamicly build slots where
each slot represents a function.
Modules:
* add KConfig-module to provide persistent configurations where all
scripts are able to operate on.
* add KStandardDirs-module to be able to reuse e.g. the resource-stuff
from within all scripts without much pain.
* extend forms
* add KPart module to optional load KPart's.
* extend forms, e.g. with a wizard?!
Ruby:
* support access to the QObject-hierachy. That means each RubyExtension
......@@ -43,3 +39,5 @@ Python:
KjsEmbed:
* work has started but still misses a lot of functionality to have it as
first class citizen like Python or Ruby within Kross.
* extend KjsEmbed to be able to deal with untrusted scripts coming from
untrusted sources like e.g. via internet distributed OpenDocument files.
......@@ -60,7 +60,7 @@ namespace Kross {
if( linevalue && linevalue->type() == KJS::NumberType )
lineno = linevalue->toInt32(exec);
}
const QString message = QString("%1%2: %3").arg( type ).arg( (lineno >= 0) ? QString(" line%1").arg(lineno) : "" ).arg( value->toString(exec).qstring() );
const QString message = QString("%1%2: %3").arg( type ).arg((lineno >= 0) ? QString(" line %1").arg(lineno) : "").arg(value->toString(exec).qstring());
ErrorInterface err;
err.setError(message, QString::null, lineno);
......@@ -72,11 +72,11 @@ namespace Kross {
{
KJS::JSObject* obj = engine->addObject(object, name.isEmpty() ? object->objectName() : name);
if( ! obj ) {
krossdebug( QString("Failed to publish the QObject name=\"%1\" objectName=\"%2\" restricted=\"%3\"").arg(name).arg(object ? object->objectName() : "NULL").arg(restricted) );
krosswarning( QString("Failed to publish the QObject name=\"%1\" objectName=\"%2\" restricted=\"%3\"").arg(name).arg(object ? object->objectName() : "NULL").arg(restricted) );
return;
}
if( restricted ) {
if( restricted ) {
/*FIXME needs fix for #include <kjs/object.h> which does #include "internal.h"
KJSEmbed::QObjectBinding* objImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, obj);
objImp->setAccess(
......@@ -92,7 +92,6 @@ namespace Kross {
KJSEmbed::QObjectBinding::ChildObjects
);
*/
}
}
......@@ -173,13 +172,16 @@ void KjsScript::finalize()
void KjsScript::execute()
{
if(! initialize()) {
krossdebug( QString("KjsScript::execute aborted cause initialize failed.") );
krosswarning( QString("KjsScript::execute aborted cause initialize failed.") );
return;
}
KJS::UString code = action()->code();
QString code = action()->code();
if(code.startsWith("#!")) // remove optional shebang-line
code.remove(0, code.indexOf('\n'));
//krossdebug( QString("KjsScript::execute code=\n%1").arg(code.qstring()) );
KJSEmbed::Engine::ExitStatus exitstatus = d->engine->execute(code);
KJSEmbed::Engine::ExitStatus exitstatus = d->engine->execute( KJS::UString(code) );
KJS::Completion completion = d->engine->completion();
if(exitstatus != KJSEmbed::Engine::Success) {
......
......@@ -51,8 +51,10 @@ namespace Kross {
// this number only if you really know what you're doing.
#define KROSS_PYTHON_VERSION 1
// Enable debugging for Kross::PythonInterpreter
//#define KROSS_PYTHON_INTERPRETER_DEBUG
// Enable debugging for Kross::PythonScript
//#define KROSS_PYTHON_SCRIPT_CTOR_DEBUG
//#define KROSS_PYTHON_SCRIPT_DTOR_DEBUG
//#define KROSS_PYTHON_SCRIPT_INIT_DEBUG
......@@ -61,20 +63,17 @@ namespace Kross {
//#define KROSS_PYTHON_SCRIPT_CALLFUNC_DEBUG
//#define KROSS_PYTHON_SCRIPT_CLASSINSTANCE_DEBUG
// Enable debugging for Kross::Python::PythonModule
// Enable debugging for Kross::PythonModule
//#define KROSS_PYTHON_MODULE_DEBUG
// Enable debugging for Kross::Python::PythonExtension
//#define KROSS_PYTHON_EXTENSION_CTOR_DEBUG
//#define KROSS_PYTHON_EXTENSION_DTOR_DEBUG
// Enable debugging for Kross::PythonExtension
//#define KROSS_PYTHON_EXTENSION_CTORDTOR_DEBUG
//#define KROSS_PYTHON_EXTENSION_TOPYOBJECT_DEBUG
//#define KROSS_PYTHON_EXTENSION_GETATTR_DEBUG
//#define KROSS_PYTHON_EXTENSION_SETATTR_DEBUG
//#define KROSS_PYTHON_EXTENSION_CALL_DEBUG
// Enable debugging for Kross::PythonType and Kross::PythonMetaTypeFactory
//#define KROSS_PYTHON_VARIANT_DEBUG
}
......
......@@ -27,38 +27,67 @@
using namespace Kross;
namespace Kross {
/// \internal d-pointer class.
class PythonExtension::Private
{
public:
/// The QObject this PythonExtension wraps.
QPointer<QObject> object;
#ifdef KROSS_PYTHON_EXTENSION_CTORDTOR_DEBUG
/// \internal string for debugging.
QString debuginfo;
#endif
/// The cached list of methods.
QHash<QByteArray, Py::Object> methods;
/// The cached list of properties.
QHash<QByteArray, QMetaProperty> properties;
/// The cached list of enumerations.
QHash<QByteArray, int> enumerations;
/// The cached list of methodnames.
Py::List methodnames;
/// The cached list of membernames.
Py::List membernames;
/// The proxymethod which will handle all calls to our \a PythonExtension instance.
Py::MethodDefExt<PythonExtension>* proxymethod;
};
}
PythonExtension::PythonExtension(QObject* object)
: Py::PythonExtension<PythonExtension>()
, m_object(object)
, m_debuginfo(object ? QString("%1(%2)").arg(object->objectName()).arg(object->metaObject()->className()) : "NULL")
, d( new Private() )
{
#ifdef KROSS_PYTHON_EXTENSION_CTOR_DEBUG
krossdebug( QString("PythonExtension::Constructor object=%1").arg(m_debuginfo) );
d->object = object;
#ifdef KROSS_PYTHON_EXTENSION_CTORDTOR_DEBUG
d->debuginfo = object ? QString("%1 (%2)").arg(object->objectName()).arg(object->metaObject()->className()) : "NULL";
krossdebug( QString("PythonExtension::Constructor object=%1").arg(d->debuginfo) );
#endif
behaviors().name("KrossPythonExtension");
/*
behaviors().doc(
"The common KrossPythonExtension object enables passing "
"of Kross::Object's from C/C++ to Python and "
"backwards in a transparent way."
);
*/
behaviors().doc("The KrossPythonExtension object wraps a QObject into the world of python.");
//behaviors().supportRepr();
behaviors().supportGetattr();
behaviors().supportSetattr();
behaviors().supportSequenceType();
behaviors().supportMappingType();
m_proxymethod = new Py::MethodDefExt<PythonExtension>(
d->proxymethod = new Py::MethodDefExt<PythonExtension>(
"", // methodname, not needed cause we use the method only internaly.
0, // method that should handle the callback, not needed cause proxyhandler will handle it.
Py::method_varargs_call_handler_t( proxyhandler ), // callback handler
"" // documentation
);
if(m_object) {
const QMetaObject* metaobject = m_object->metaObject();
if(d->object) {
const QMetaObject* metaobject = d->object->metaObject();
{ // initialize methods.
const int count = metaobject->methodCount();
......@@ -66,14 +95,14 @@ PythonExtension::PythonExtension(QObject* object)
QMetaMethod member = metaobject->method(i);
const QString signature = member.signature();
const QByteArray name = signature.left(signature.indexOf('(')).toLatin1();
if(! m_methods.contains(name)) {
if(! d->methods.contains(name)) {
Py::Tuple self(3);
self[0] = Py::Object(this); // reference to this instance
self[1] = Py::Int(i); // the first index used for faster access
self[2] = Py::String(name); // the name of the method
m_methods.insert(name, Py::Object(PyCFunction_New( &m_proxymethod->ext_meth_def, self.ptr() ), true));
m_methodnames.append(self[2]);
d->methods.insert(name, Py::Object(PyCFunction_New( &d->proxymethod->ext_meth_def, self.ptr() ), true));
d->methodnames.append(self[2]);
}
}
}
......@@ -82,8 +111,8 @@ PythonExtension::PythonExtension(QObject* object)
const int count = metaobject->propertyCount();
for(int i = 0; i < count; ++i) {
QMetaProperty prop = metaobject->property(i);
m_properties.insert(prop.name(), prop);
m_membernames.append( Py::String(prop.name()) );
d->properties.insert(prop.name(), prop);
d->membernames.append( Py::String(prop.name()) );
}
}
......@@ -94,8 +123,8 @@ PythonExtension::PythonExtension(QObject* object)
const int kc = e.keyCount();
for(int k = 0; k < kc; ++k) {
const QByteArray name = /*e.name() +*/ e.key(k);
m_enumerations.insert(name, e.value(k));
m_membernames.append( Py::String(name) );
d->enumerations.insert(name, e.value(k));
d->membernames.append( Py::String(name) );
}
}
}
......@@ -104,15 +133,16 @@ PythonExtension::PythonExtension(QObject* object)
PythonExtension::~PythonExtension()
{
#ifdef KROSS_PYTHON_EXTENSION_DTOR_DEBUG
krossdebug( QString("PythonExtension::Destructor object=%1").arg(m_debuginfo) );
#ifdef KROSS_PYTHON_EXTENSION_CTORDTOR_DEBUG
krossdebug( QString("PythonExtension::Destructor object=%1").arg(d->debuginfo) );
#endif
delete m_proxymethod;
delete d->proxymethod;
delete d;
}
QObject* PythonExtension::object() const
{
return m_object;
return d->object;
}
Py::Object PythonExtension::getattr(const char* n)
......@@ -124,19 +154,19 @@ Py::Object PythonExtension::getattr(const char* n)
// handle internal methods
if(n[0] == '_') {
if(strcmp(n,"__methods__") == 0)
return m_methodnames;
return d->methodnames;
if(strcmp(n,"__members__") == 0)
return m_membernames;
return d->membernames;
//if(strcmp(n,"__dict__") == 0)
// return PythonType<QStringList>::toPyObject( QStringList() );
if(strcmp(n,"__name__") == 0)
return PythonType<QString>::toPyObject( m_object->objectName() );
return PythonType<QString>::toPyObject( d->object->objectName() );
if(strcmp(n,"__class__") == 0)
return PythonType<QString>::toPyObject( m_object->metaObject()->className() );
return PythonType<QString>::toPyObject( d->object->metaObject()->className() );
/*
if(strcmp(n,"__toPointer__") == 0) {
PyObject* qobjectptr = PyLong_FromVoidPtr( (void*) m_object.data() );
PyObject* qobjectptr = PyLong_FromVoidPtr( (void*) d->object.data() );
//PyObject* o = Py_BuildValue ("N", mw);
return Py::asObject( qobjectptr );
//PythonPyQtExtension* pyqtextension = new PythonPyQtExtension(self, args);
......@@ -149,22 +179,22 @@ Py::Object PythonExtension::getattr(const char* n)
}
// look if the attribute is a method
if(m_methods.contains(n)) {
if(d->methods.contains(n)) {
#ifdef KROSS_PYTHON_EXTENSION_GETATTR_DEBUG
krossdebug( QString("PythonExtension::getattr name='%1' is a method.").arg(n) );
#endif
return m_methods[n];
return d->methods[n];
}
// look if the attribute is a property
if(m_properties.contains(n) && m_object) {
QMetaProperty property = m_properties[n];
if(d->properties.contains(n) && d->object) {
QMetaProperty property = d->properties[n];
#ifdef KROSS_PYTHON_EXTENSION_GETATTR_DEBUG
krossdebug( QString("PythonExtension::getattr name='%1' is a property: type=%2 valid=%3 readable=%4 scriptable=%5 writable=%6 usertype=%7")
.arg(n).arg(property.typeName()).arg(property.isValid())
.arg(property.isReadable()).arg(property.isScriptable(m_object)).arg(property.isWritable())
.arg(property.isUser(m_object)).arg(property.userType())
.arg(property.isReadable()).arg(property.isScriptable(d->object)).arg(property.isWritable())
.arg(property.isUser(d->object)).arg(property.userType())
);
#endif
......@@ -173,12 +203,12 @@ Py::Object PythonExtension::getattr(const char* n)
return Py::None();
}
return PythonType<QVariant>::toPyObject( property.read(m_object) );
return PythonType<QVariant>::toPyObject( property.read(d->object) );
}
// look if the attribute is an enumerator
if(m_enumerations.contains(n)) {
return Py::Int(m_enumerations[n]);
if(d->enumerations.contains(n)) {
return Py::Int(d->enumerations[n]);
}
// finally redirect the unhandled attribute-request...
......@@ -189,14 +219,14 @@ Py::Object PythonExtension::getattr(const char* n)
int PythonExtension::setattr(const char* n, const Py::Object& value)
{
// look if the attribute is a property
if(m_properties.contains(n) && m_object) {
QMetaProperty property = m_properties[n];
if(d->properties.contains(n) && d->object) {
QMetaProperty property = d->properties[n];
#ifdef KROSS_PYTHON_EXTENSION_SETATTR_DEBUG
krossdebug( QString("PythonExtension::setattr name='%1' is a property: type=%2 valid=%3 readable=%4 scriptable=%5 writable=%6 usertype=%7")
.arg(n).arg(property.typeName()).arg(property.isValid())
.arg(property.isReadable()).arg(property.isScriptable(m_object)).arg(property.isWritable())
.arg(property.isUser(m_object)).arg(property.userType())
.arg(property.isReadable()).arg(property.isScriptable(d->object)).arg(property.isWritable())
.arg(property.isUser(d->object)).arg(property.userType())
);
#endif
......@@ -206,7 +236,7 @@ int PythonExtension::setattr(const char* n, const Py::Object& value)
}
QVariant v = PythonType<QVariant>::toVariant(value);
if(! property.write(m_object, v)) {
if(! property.write(d->object, v)) {
Py::AttributeError( QString("Setting attribute \"%1\" failed.").arg(n).toLatin1().constData() );
return -1; // indicate error
}
......@@ -237,12 +267,12 @@ PyObject* PythonExtension::proxyhandler(PyObject *_self_and_name_tuple, PyObject
Py::Tuple argstuple(args);
const int argssize = int( argstuple.size() );
QMetaMethod metamethod = self->m_object->metaObject()->method( methodindex );
QMetaMethod metamethod = self->d->object->metaObject()->method( methodindex );
if(metamethod.parameterTypes().size() != argssize) {
bool found = false;
const int count = self->m_object->metaObject()->methodCount();
const int count = self->d->object->metaObject()->methodCount();
for(++methodindex; methodindex < count; ++methodindex) {
metamethod = self->m_object->metaObject()->method( methodindex );
metamethod = self->d->object->metaObject()->method( methodindex );
const QString signature = metamethod.signature();
const QByteArray name = signature.left(signature.indexOf('(')).toLatin1();
if(name == methodname) {
......@@ -331,7 +361,7 @@ PyObject* PythonExtension::proxyhandler(PyObject *_self_and_name_tuple, PyObject
}
// call the method now
int r = self->m_object->qt_metacall(QMetaObject::InvokeMetaMethod, methodindex,
int r = self->d->object->qt_metacall(QMetaObject::InvokeMetaMethod, methodindex,
&voidstarargs[0]);
#ifdef KROSS_PYTHON_EXTENSION_CALL_DEBUG
krossdebug( QString("RESULT nr=%1").arg(r) );
......@@ -373,7 +403,7 @@ PyObject* PythonExtension::proxyhandler(PyObject *_self_and_name_tuple, PyObject
int PythonExtension::sequence_length()
{
return m_object->children().count();
return d->object->children().count();
}
Py::Object PythonExtension::sequence_concat(const Py::Object& obj)
......@@ -388,8 +418,8 @@ Py::Object PythonExtension::sequence_repeat(int index)
Py::Object PythonExtension::sequence_item(int index)
{
if(index < m_object->children().count())
return Py::asObject(new PythonExtension( m_object->children().at(index) ));
if(index < d->object->children().count())
return Py::asObject(new PythonExtension( d->object->children().at(index) ));
return Py::asObject( Py::new_reference_to( NULL ) );
}
......@@ -397,9 +427,9 @@ Py::Object PythonExtension::sequence_slice(int from, int to)
{
Py::List list;
if(from >= 0) {
const int count = m_object->children().count();
const int count = d->object->children().count();
for(int i = from; i <= to && i < count; ++i)
list.append( Py::asObject(new PythonExtension( m_object->children().at(i) )) );
list.append( Py::asObject(new PythonExtension( d->object->children().at(i) )) );
}
return list;
}
......@@ -416,15 +446,15 @@ int PythonExtension::sequence_ass_slice(int from, int to, const Py::Object& obj)
int PythonExtension::mapping_length()
{
return m_object->children().count();
return d->object->children().count();
}
Py::Object PythonExtension::mapping_subscript(const Py::Object& obj)
{
QString name = Py::String(obj).as_string().c_str();
QObject* object = m_object->findChild< QObject* >( name );
QObject* object = d->object->findChild< QObject* >( name );
if(! object) {
foreach(QObject* o, m_object->children()) {
foreach(QObject* o, d->object->children()) {
if(name == o->metaObject()->className()) {
object = o;
break;
......
......@@ -94,26 +94,10 @@ namespace Kross {
virtual int mapping_ass_subscript(const Py::Object&, const Py::Object&);
private:
/// The QObject this PythonExtension wraps.
QPointer<QObject> m_object;
/// \internal string for debugging.
QString m_debuginfo;
/// The cached list of methods.
QHash<QByteArray, Py::Object> m_methods;
/// The cached list of properties.
QHash<QByteArray, QMetaProperty> m_properties;
/// The cached list of enumerations.
QHash<QByteArray, int> m_enumerations;
/// The cached list of methodnames.
Py::List m_methodnames;
/// The cached list of membernames.
Py::List m_membernames;
/// The proxymethod which will handle all calls to our \a PythonExtension instance.
Py::MethodDefExt<PythonExtension>* m_proxymethod;
/// \internal d-pointer class.
class Private;
/// \internal d-pointer instance.
Private* const d;
/**
* The static proxy-handler which will be used to dispatch
......
......@@ -22,7 +22,7 @@
#include "rubyvariant.h"
#include "../core/metatype.h"
#include <st.h>
//#include <st.h>
#include <QMap>
#include <QString>
......@@ -45,7 +45,6 @@ namespace Kross {
/// The wrapped krossobject VALUE type.
static VALUE s_krossObject;
//static VALUE s_krossException;
/// The cached list of methods.
......@@ -79,9 +78,8 @@ RubyExtension::RubyExtension(QObject* object)
QMetaMethod member = metaobject->method(i);
const QString signature = member.signature();
const QByteArray name = signature.left(signature.indexOf('(')).toLatin1();
if(! d->m_methods.contains(name)) {
if(! d->m_methods.contains(name))
d->m_methods.insert(name, i);
}
}
}
......@@ -124,9 +122,8 @@ QObject* RubyExtension::object() const
VALUE RubyExtension::method_missing(int argc, VALUE *argv, VALUE self)
{
if(argc < 1) {
if( argc < 1 )
return 0;
}
#ifdef KROSS_RUBY_EXTENSION_DEBUG
krossdebug("RubyExtension::method_missing Converting self to RubyExtension");
......@@ -135,15 +132,15 @@ VALUE RubyExtension::method_missing(int argc, VALUE *argv, VALUE self)
RubyExtension* extension;
Data_Get_Struct(self, RubyExtension, extension);
Q_ASSERT(extension);
return RubyExtension::call_method(extension, argc, argv);
return RubyExtension::call_method_missing(extension, argc, argv);
}
VALUE RubyExtension::callMethod(const QByteArray& funcname, int argc, VALUE *argv)
VALUE RubyExtension::callMetaMethod(const QByteArray& funcname, int argc, VALUE *argv)
{
const int argumentcount = argc - 1;
#ifdef KROSS_RUBY_EXTENSION_DEBUG
krossdebug(QString("RubyExtension::callMethod method=%1 argumentcount=%2").arg(funcname.constData()).arg(argumentcount));
krossdebug(QString("RubyExtension::callMetaMethod method=%1 argumentcount=%2").arg(funcname.constData()).arg(argumentcount));
for(int i = 1; i < argc; i++) {
QVariant v = RubyType<QVariant>::toVariant(argv[i]);
krossdebug(QString(" argument #%1: variant.toString=%2 variant.typeName=%3").arg(i).arg(v.toString()).arg(v.typeName()));
......@@ -197,7 +194,7 @@ VALUE RubyExtension::callMethod(const QByteArray& funcname, int argc, VALUE *arg
int typeId = QVariant::nameToType( metamethod.typeName() );
if(typeId != QVariant::Invalid) {
#ifdef KROSS_RUBY_EXTENSION_DEBUG
krossdebug( QString("RubyExtension::callMethod typeName=%1 variant.typeid=%2").arg(metamethod.typeName()).arg(typeId) );
krossdebug( QString("RubyExtension::callMetaMethod typeName=%1 variant.typeid=%2").arg(metamethod.typeName()).arg(typeId) );
#endif
returntype = new MetaTypeVariant< QVariant >( QVariant( (QVariant::Type) typeId ) );
}
......@@ -205,13 +202,13 @@ VALUE RubyExtension::callMethod(const QByteArray& funcname, int argc, VALUE *arg
typeId = QMetaType::type( metamethod.typeName() );
if(typeId == QMetaType::Void) {
#ifdef KROSS_RUBY_EXTENSION_DEBUG
krossdebug( QString("RubyExtension::callMethod typeName=%1 metatype.typeid is QMetaType::Void").arg(metamethod.typeName()) );
krossdebug( QString("RubyExtension::callMetaMethod typeName=%1 metatype.typeid is QMetaType::Void").arg(metamethod.typeName()) );
#endif
returntype = new MetaTypeVariant< QVariant >( QVariant() );
}
else {
#ifdef KROSS_RUBY_EXTENSION_DEBUG
krossdebug( QString("RubyExtension::callMethod typeName=%1 metatype.typeid=%2").arg(metamethod.typeName()).arg(typeId) );
krossdebug( QString("RubyExtension::callMetaMethod typeName=%1 metatype.typeid=%2").arg(metamethod.typeName()).arg(typeId) );
#endif
//if (id != -1) {
void* myClassPtr = QMetaType::construct(typeId, 0);
......@@ -234,7 +231,7 @@ VALUE RubyExtension::callMethod(const QByteArray& funcname, int argc, VALUE *arg
MetaType* metatype = RubyMetaTypeFactory::create(typelist[idx - 1].constData(), argv[idx]);
if(! metatype) {
// Seems RubyMetaTypeFactory::create returned an invalid RubyType.
krosswarning( QString("RubyExtension::callMethod Aborting cause RubyMetaTypeFactory::create returned NULL.") );
krosswarning( QString("RubyExtension::callMetaMethod Aborting cause RubyMetaTypeFactory::create returned NULL.") );
for(int i = 0; i < idx; ++i) // Clear already allocated instances.
delete variantargs[i];
return Qfalse; // abort execution.
......@@ -272,13 +269,13 @@ VALUE RubyExtension::callMethod(const QByteArray& funcname, int argc, VALUE *arg
return result.isNull() ? 0 : RubyType<QVariant>::toVALUE(result);
}
VALUE RubyExtension::call_method(RubyExtension* extension, int argc, VALUE *argv)
VALUE RubyExtension::call_method_missing(RubyExtension* extension, int argc, VALUE *argv)
{
QByteArray name = rb_id2name(SYM2ID(argv[0]));
// look if the name is a method
if( extension->d->m_methods.contains(name) ) {
return extension->callMethod(name, argc, argv);
return extension->callMetaMethod(name, argc, argv);
}
// look if the name is a property
......@@ -306,7 +303,7 @@ VALUE RubyExtension::call_method(RubyExtension* extension, int argc, VALUE *argv
}
}
// look if the name is a enumeration
// look if the name is an enumeration
if( extension->d->m_enumerations.contains(name) ) {
return RubyType<int>::toVALUE( extension->d->m_enumerations[name] );
}
......@@ -347,8 +344,7 @@ bool RubyExtension::isOfExceptionType(VALUE value)
}
Kross::Exception* RubyExtension::convertToException(VALUE value)
{
if( isOfExceptionType(value) )
{
if( isOfExceptionType(value) ) {
Kross::Exception* exception;
Data_Get_Struct(value, Kross::Exception, exception);
return exception;
......@@ -358,9 +354,7 @@ Kross::Exception* RubyExtension::convertToException(VALUE value)
VALUE RubyExtension::convertFromException(Kross::Exception::Ptr exc)
{
if(RubyExtensionPrivate::s_krossException == 0)
{
RubyExtensionPrivate::s_krossException = rb_define_class("KrossException", rb_eRuntimeError);
}
//exc->_KShared_ref(); //TODO
return Data_Wrap_Struct(RubyExtensionPrivate::s_krossException, 0, RubyExtension::delete_exception, exc.data() );
}
......@@ -374,11 +368,10 @@ VALUE RubyExtension::toVALUE(RubyExtension* extension)
krossdebug( QString("RubyExtension::toVALUE RubyExtension.QObject=%1").arg( object ? QString("%1 %2").arg(object->objectName()).arg(object->metaObject()->className()) : "NULL" ) );
#endif
if(! object) {
if( ! object )
return 0;
}
if(RubyExtensionPrivate::s_krossObject == 0) {