From 29d38290403f6966aa92ae9c8880b0924ff0897d 2009-04-15 11:49:47 From: florianlink Date: 2009-04-15 11:49:47 Subject: [PATCH] changed implementation to allow deriving python classes from PythonQt classes (it is still work in progress and is not very useful yet without having shell classes that reimplement the C++ virtual functions) git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@58 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQtClassWrapper.cpp b/src/PythonQtClassWrapper.cpp index 8dd46d5..15d4381 100644 --- a/src/PythonQtClassWrapper.cpp +++ b/src/PythonQtClassWrapper.cpp @@ -46,6 +46,7 @@ #include "PythonQtSlot.h" #include "PythonQtClassInfo.h" #include "PythonQtConversion.h" +#include "PythonQtInstanceWrapper.h" static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems) { @@ -93,8 +94,39 @@ static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type) return PythonQt::self()->helpCalled(type->classInfo()); } +PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args) +{ + Py_ssize_t argc = PyTuple_Size(args); + if (argc>0) { + // we need to call __init__ of the instance + PyObject* self = PyTuple_GET_ITEM(args, 0); + if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) { + PyObject* newargs = PyTuple_New(argc-1); + for (int i = 0;iclassInfo()->member(attributeName); - if (member._type == PythonQtMemberInfo::EnumValue) { - return PyInt_FromLong(member._enumValue); + if (qstrcmp(attributeName, "__dict__")==0) { + PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict; + if (!wrapper->classInfo()) { + Py_INCREF(dict); + return dict; + } + dict = PyDict_Copy(dict); + + QStringList l = wrapper->classInfo()->memberList(true); + foreach (QString name, l) { + PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data()); + PyDict_SetItemString(dict, name.toLatin1().data(), o); + Py_DECREF(o); + } + if (wrapper->classInfo()->constructors()) { + PyDict_SetItemString(dict, "__init__", PyCFunction_New(&PythonQtClassWrapper_methods[0], obj)); + } + PyDict_SetItemString(dict, PythonQtClassWrapper_methods[1].ml_name, PyCFunction_New(&PythonQtClassWrapper_methods[1], obj)); + PyDict_SetItemString(dict, PythonQtClassWrapper_methods[2].ml_name, PyCFunction_New(&PythonQtClassWrapper_methods[2], obj)); + return dict; } - if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) { - return PythonQtSlotFunction_New(member._slot, obj, NULL); + + if (wrapper->classInfo()) { + PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName); + if (member._type == PythonQtMemberInfo::EnumValue) { + return PyInt_FromLong(member._enumValue); + } else + if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) { + return PythonQtSlotFunction_New(member._slot, obj, NULL); + } } // look for the interal methods (className(), help()) @@ -129,15 +188,10 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) } PyErr_Clear(); - if (qstrcmp(attributeName, "__dict__")==0) { - QStringList l = wrapper->classInfo()->memberList(true); - PyObject* dict = PyDict_New(); - foreach (QString name, l) { - //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data()); - PyDict_SetItemString(dict, name.toLatin1().data(), Py_None); - //Py_DECREF(o); - } - return dict; + // look in super + PyObject* superAttr = PyType_Type.tp_getattro(obj, name); + if (superAttr) { + return superAttr; } QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'"; @@ -211,8 +265,8 @@ PyTypeObject PythonQtClassWrapper_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ + 0, /* tp_methods */ + 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ diff --git a/src/PythonQtInstanceWrapper.cpp b/src/PythonQtInstanceWrapper.cpp index f6c9dc9..bbccb90 100644 --- a/src/PythonQtInstanceWrapper.cpp +++ b/src/PythonQtInstanceWrapper.cpp @@ -134,7 +134,7 @@ static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * args return (PyObject *)self; } -static int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds) +int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds) { PyObject* result = NULL; @@ -247,29 +247,34 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) } PyErr_Clear(); - if (wrapper->_obj) { - // look for a child - QObjectList children = wrapper->_obj->children(); - for (int i = 0; i < children.count(); i++) { - QObject *child = children.at(i); - if (child->objectName() == attributeName) { - return PythonQt::self()->priv()->wrapQObject(child); - } - } - } - if (qstrcmp(attributeName, "__dict__")==0) { QStringList l = wrapper->classInfo()->memberList(false); PyObject* dict = PyDict_New(); foreach (QString name, l) { - //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data()); + PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data()); PyDict_SetItemString(dict, name.toLatin1().data(), Py_None); - //Py_DECREF(o); + Py_DECREF(o); } // Note: we do not put children into the dict, is would look confusing?! return dict; } + // look in super + PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name); + if (superAttr) { + return superAttr; + } + + if (wrapper->_obj) { + // look for a child + QObjectList children = wrapper->_obj->children(); + for (int i = 0; i < children.count(); i++) { + QObject *child = children.at(i); + if (child->objectName() == attributeName) { + return PythonQt::self()->priv()->wrapQObject(child); + } + } + } QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'"; PyErr_SetString(PyExc_AttributeError, error.toLatin1().data()); @@ -332,6 +337,7 @@ static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec static PyObject * PythonQtInstanceWrapper_str(PyObject * obj) { PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj; + const char* typeName = obj->ob_type->tp_name; QObject *qobj = wrapper->_obj; if (wrapper->_wrappedPtr) { QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr); @@ -339,28 +345,30 @@ static PyObject * PythonQtInstanceWrapper_str(PyObject * obj) return PyString_FromFormat("%s", str.toLatin1().constData()); } else if (wrapper->_obj) { - return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); + return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); } else { - return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr); + return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr); } } else { - return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj); + return PyString_FromFormat("%s (QObject %p)", typeName, qobj); } } static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj) { PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj; + const char* typeName = obj->ob_type->tp_name; + QObject *qobj = wrapper->_obj; if (wrapper->_wrappedPtr) { QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr); if (!str.isEmpty()) { - return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wrapper->classInfo()->metaTypeId()), str.toLatin1().constData(), wrapper->_wrappedPtr); + return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr); } else if (wrapper->_obj) { - return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); + return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); } else { - return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr); + return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr); } } else { return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj); diff --git a/src/PythonQtInstanceWrapper.h b/src/PythonQtInstanceWrapper.h index e04644b..5da2ad7 100644 --- a/src/PythonQtInstanceWrapper.h +++ b/src/PythonQtInstanceWrapper.h @@ -88,5 +88,6 @@ typedef struct PythonQtInstanceWrapperStruct { } PythonQtInstanceWrapper; +int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds); #endif \ No newline at end of file