/*
*
* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: MeVis Research GmbH, Universitaetsallee 29,
* 28359 Bremen, Germany or:
*
* http://www.mevis.de
*
*/
//----------------------------------------------------------------------------------
/*!
// \file PythonQtSlot.cpp
// \author Florian Link
// \author Last changed by $Author: florian $
// \date 2006-05
*/
//----------------------------------------------------------------------------------
#include "PythonQt.h"
#include "PythonQtSlot.h"
#include "PythonQtWrapper.h"
#include "PythonQtClassInfo.h"
#include "PythonQtMisc.h"
#include "PythonQtConversion.h"
#include <iostream>
#define PYTHONQT_MAX_ARGS 32
PyObject* PythonQtCallSlot(PythonQtWrapper* self, PyObject* args, bool strict, PythonQtSlotInfo* info)
{
static unsigned int recursiveEntry = 0;
if (recursiveEntry == 0) {
//EXTRA: maybe don't do it on each call?
PythonQtConv::resetParameterStorage();
}
recursiveEntry++;
// the arguments that are passed to qt_metacall
void* argList[PYTHONQT_MAX_ARGS];
PyObject* result = NULL;
int argc = info->parameterCount();
const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
if (returnValueParam.typeId != PythonQtSlotInfo::Void) {
// create empty default value for the return value
argList[0] = PythonQtConv::CreateQtReturnValue(params.at(0));
} else {
argList[0] = NULL;
}
bool ok = true;
for (int i = 1; i<argc && ok; i++) {
const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
//std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict);
if (argList[i]==NULL) {
ok = false;
break;
}
}
if (ok) {
self->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
}
recursiveEntry--;
return result;
}
//-----------------------------------------------------------------------------------
static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
{
PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
PythonQtSlotInfo* info = f->m_ml;
PythonQtWrapper* self = (PythonQtWrapper*) f->m_self;
int argc = PyTuple_Size(args);
//std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
PyObject* r = NULL;
if (info->nextInfo()) {
// overloaded slot call, try on all slots with strict conversion first
PythonQtSlotInfo* i = info;
while (i && r==NULL) {
if (i->parameterCount()-1 == argc) {
r = PythonQtCallSlot(self, args, true, i);
}
i = i->nextInfo();
}
if (!r) {
// try on all slots with non-strict conversion
i = info;
while (i && r==NULL) {
if (i->parameterCount()-1 == argc) {
r = PythonQtCallSlot(self, args, false, i);
}
i = i->nextInfo();
}
}
if (r==0) {
QString e = QString("Could not find matching overload. The following slots are available:\n");
PythonQtSlotInfo* i = info;
while (i) {
e += QString(i->fullSignature()) + "\n";
i = i->nextInfo();
}
PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
}
} else {
// simple (non-overloaded) slot call
if (info->parameterCount()-1 == argc) {
r = PythonQtCallSlot(self, args, false, info);
if (!r) {
QString e = QString("Called ") + info->fullSignature() + " with wrong arguments.";
PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
}
} else {
QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments.";
PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
}
}
return r;
}
PyObject *
PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
{
PythonQtSlotFunctionObject *op;
op = pythonqtslot_free_list;
if (op != NULL) {
pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
PyObject_INIT(op, &PythonQtSlotFunction_Type);
}
else {
op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
if (op == NULL)
return NULL;
}
op->m_ml = ml;
Py_XINCREF(self);
op->m_self = self;
Py_XINCREF(module);
op->m_module = module;
PyObject_GC_Track(op);
return (PyObject *)op;
}
PythonQtSlotInfo*
PythonQtSlotFunction_GetSlotInfo(PyObject *op)
{
if (!PythonQtSlotFunction_Check(op)) {
PyErr_BadInternalCall();
return NULL;
}
return ((PythonQtSlotFunctionObject *)op) -> m_ml;
}
PyObject *
PythonQtSlotFunction_GetSelf(PyObject *op)
{
if (!PythonQtSlotFunction_Check(op)) {
PyErr_BadInternalCall();
return NULL;
}
return ((PythonQtSlotFunctionObject *)op) -> m_self;
}
/* Methods (the standard built-in methods, that is) */
static void
meth_dealloc(PythonQtSlotFunctionObject *m)
{
PyObject_GC_UnTrack(m);
Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module);
m->m_self = (PyObject *)pythonqtslot_free_list;
pythonqtslot_free_list = m;
}
static PyObject *
meth_get__doc__(PythonQtSlotFunctionObject *m, void *closure)
{
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
meth_get__name__(PythonQtSlotFunctionObject *m, void *closure)
{
return PyString_FromString(m->m_ml->metaMethod()->signature());
}
static int
meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
{
int err;
if (m->m_self != NULL) {
err = visit(m->m_self, arg);
if (err)
return err;
}
if (m->m_module != NULL) {
err = visit(m->m_module, arg);
if (err)
return err;
}
return 0;
}
static PyObject *
meth_get__self__(PythonQtSlotFunctionObject *m, void *closure)
{
PyObject *self;
if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError,
"method.__self__ not accessible in restricted mode");
return NULL;
}
self = m->m_self;
if (self == NULL)
self = Py_None;
Py_INCREF(self);
return self;
}
static PyGetSetDef meth_getsets [] = {
{"__doc__", (getter)meth_get__doc__, NULL, NULL},
{"__name__", (getter)meth_get__name__, NULL, NULL},
{"__self__", (getter)meth_get__self__, NULL, NULL},
{0}
};
#define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
static PyMemberDef meth_members[] = {
{"__module__", T_OBJECT, OFF(m_module), WRITE_RESTRICTED},
{NULL}
};
static PyObject *
meth_repr(PythonQtSlotFunctionObject *m)
{
return PyString_FromFormat("<built-in qt slot %s of %s object at %p>",
m->m_ml->metaMethod()->signature(),
m->m_self->ob_type->tp_name,
m->m_self);
}
static int
meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
{
if (a->m_self != b->m_self)
return (a->m_self < b->m_self) ? -1 : 1;
if (a->m_ml == b->m_ml)
return 0;
if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
return -1;
else
return 1;
}
static long
meth_hash(PythonQtSlotFunctionObject *a)
{
long x,y;
if (a->m_self == NULL)
x = 0;
else {
x = PyObject_Hash(a->m_self);
if (x == -1)
return -1;
}
y = _Py_HashPointer((void*)(a->m_ml));
if (y == -1)
return -1;
x ^= y;
if (x == -1)
x = -2;
return x;
}
PyTypeObject PythonQtSlotFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"builtin_qt_slot",
sizeof(PythonQtSlotFunctionObject),
0,
(destructor)meth_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)meth_compare, /* tp_compare */
(reprfunc)meth_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)meth_hash, /* tp_hash */
PythonQtSlotFunction_Call, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)meth_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
meth_members, /* tp_members */
meth_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
/* Clear out the free list */
void
PythonQtSlotFunction_Fini(void)
{
while (pythonqtslot_free_list) {
PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
PyObject_GC_Del(v);
}
}