##// END OF EJS Templates
changed implementation to allow deriving python classes from PythonQt classes...
florianlink -
r22:29d38290403f
parent child
Show More
@@ -46,6 +46,7
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
49
50
50 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
51 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
51 {
52 {
@@ -93,8 +94,39 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
93 return PythonQt::self()->helpCalled(type->classInfo());
94 return PythonQt::self()->helpCalled(type->classInfo());
94 }
95 }
95
96
97 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
98 {
99 Py_ssize_t argc = PyTuple_Size(args);
100 if (argc>0) {
101 // we need to call __init__ of the instance
102 PyObject* self = PyTuple_GET_ITEM(args, 0);
103 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
104 PyObject* newargs = PyTuple_New(argc-1);
105 for (int i = 0;i<argc-1; i++) {
106 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
107 }
108 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
109 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
110 Py_DECREF(newargs);
111 if (result==0) {
112 Py_INCREF(Py_None);
113 return Py_None;
114 } else {
115 // init failed!
116 }
117 } else {
118 // self not of correct type!
119 }
120 } else {
121 // wrong number of args
122 }
123 return NULL;
124 }
96
125
97 static PyMethodDef PythonQtClassWrapper_methods[] = {
126 static PyMethodDef PythonQtClassWrapper_methods[] = {
127 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
128 "Return the classname of the object"
129 },
98 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
130 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
99 "Return the classname of the object"
131 "Return the classname of the object"
100 },
132 },
@@ -113,14 +145,41 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
113 if ((attributeName = PyString_AsString(name)) == NULL) {
145 if ((attributeName = PyString_AsString(name)) == NULL) {
114 return NULL;
146 return NULL;
115 }
147 }
148 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
149 return NULL;
150 }
151
152 if (qstrcmp(attributeName, "__dict__")==0) {
153 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
154 if (!wrapper->classInfo()) {
155 Py_INCREF(dict);
156 return dict;
157 }
158 dict = PyDict_Copy(dict);
159
160 QStringList l = wrapper->classInfo()->memberList(true);
161 foreach (QString name, l) {
162 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
163 PyDict_SetItemString(dict, name.toLatin1().data(), o);
164 Py_DECREF(o);
165 }
166 if (wrapper->classInfo()->constructors()) {
167 PyDict_SetItemString(dict, "__init__", PyCFunction_New(&PythonQtClassWrapper_methods[0], obj));
168 }
169 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[1].ml_name, PyCFunction_New(&PythonQtClassWrapper_methods[1], obj));
170 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[2].ml_name, PyCFunction_New(&PythonQtClassWrapper_methods[2], obj));
171 return dict;
172 }
116
173
174 if (wrapper->classInfo()) {
117 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
175 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
118 if (member._type == PythonQtMemberInfo::EnumValue) {
176 if (member._type == PythonQtMemberInfo::EnumValue) {
119 return PyInt_FromLong(member._enumValue);
177 return PyInt_FromLong(member._enumValue);
120 }
178 } else
121 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
179 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
122 return PythonQtSlotFunction_New(member._slot, obj, NULL);
180 return PythonQtSlotFunction_New(member._slot, obj, NULL);
123 }
181 }
182 }
124
183
125 // look for the interal methods (className(), help())
184 // look for the interal methods (className(), help())
126 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
185 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
@@ -129,15 +188,10 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
129 }
188 }
130 PyErr_Clear();
189 PyErr_Clear();
131
190
132 if (qstrcmp(attributeName, "__dict__")==0) {
191 // look in super
133 QStringList l = wrapper->classInfo()->memberList(true);
192 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
134 PyObject* dict = PyDict_New();
193 if (superAttr) {
135 foreach (QString name, l) {
194 return superAttr;
136 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
137 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
138 //Py_DECREF(o);
139 }
140 return dict;
141 }
195 }
142
196
143 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
197 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
@@ -134,7 +134,7 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * args
134 return (PyObject *)self;
134 return (PyObject *)self;
135 }
135 }
136
136
137 static int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
137 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
138 {
138 {
139 PyObject* result = NULL;
139 PyObject* result = NULL;
140
140
@@ -247,29 +247,34 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
247 }
247 }
248 PyErr_Clear();
248 PyErr_Clear();
249
249
250 if (wrapper->_obj) {
251 // look for a child
252 QObjectList children = wrapper->_obj->children();
253 for (int i = 0; i < children.count(); i++) {
254 QObject *child = children.at(i);
255 if (child->objectName() == attributeName) {
256 return PythonQt::self()->priv()->wrapQObject(child);
257 }
258 }
259 }
260
261 if (qstrcmp(attributeName, "__dict__")==0) {
250 if (qstrcmp(attributeName, "__dict__")==0) {
262 QStringList l = wrapper->classInfo()->memberList(false);
251 QStringList l = wrapper->classInfo()->memberList(false);
263 PyObject* dict = PyDict_New();
252 PyObject* dict = PyDict_New();
264 foreach (QString name, l) {
253 foreach (QString name, l) {
265 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
254 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
266 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
255 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
267 //Py_DECREF(o);
256 Py_DECREF(o);
268 }
257 }
269 // Note: we do not put children into the dict, is would look confusing?!
258 // Note: we do not put children into the dict, is would look confusing?!
270 return dict;
259 return dict;
271 }
260 }
272
261
262 // look in super
263 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
264 if (superAttr) {
265 return superAttr;
266 }
267
268 if (wrapper->_obj) {
269 // look for a child
270 QObjectList children = wrapper->_obj->children();
271 for (int i = 0; i < children.count(); i++) {
272 QObject *child = children.at(i);
273 if (child->objectName() == attributeName) {
274 return PythonQt::self()->priv()->wrapQObject(child);
275 }
276 }
277 }
273
278
274 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
279 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
275 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
280 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
@@ -332,6 +337,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
332 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
337 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
333 {
338 {
334 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
339 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
340 const char* typeName = obj->ob_type->tp_name;
335 QObject *qobj = wrapper->_obj;
341 QObject *qobj = wrapper->_obj;
336 if (wrapper->_wrappedPtr) {
342 if (wrapper->_wrappedPtr) {
337 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
343 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
@@ -339,28 +345,30 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
339 return PyString_FromFormat("%s", str.toLatin1().constData());
345 return PyString_FromFormat("%s", str.toLatin1().constData());
340 } else
346 } else
341 if (wrapper->_obj) {
347 if (wrapper->_obj) {
342 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
348 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
343 } else {
349 } else {
344 return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr);
350 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
345 }
351 }
346 } else {
352 } else {
347 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
353 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
348 }
354 }
349 }
355 }
350
356
351 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
357 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
352 {
358 {
353 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
359 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
360 const char* typeName = obj->ob_type->tp_name;
361
354 QObject *qobj = wrapper->_obj;
362 QObject *qobj = wrapper->_obj;
355 if (wrapper->_wrappedPtr) {
363 if (wrapper->_wrappedPtr) {
356 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
364 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
357 if (!str.isEmpty()) {
365 if (!str.isEmpty()) {
358 return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wrapper->classInfo()->metaTypeId()), str.toLatin1().constData(), wrapper->_wrappedPtr);
366 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
359 } else
367 } else
360 if (wrapper->_obj) {
368 if (wrapper->_obj) {
361 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
369 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
362 } else {
370 } else {
363 return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr);
371 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
364 }
372 }
365 } else {
373 } else {
366 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
374 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
@@ -88,5 +88,6 typedef struct PythonQtInstanceWrapperStruct {
88
88
89 } PythonQtInstanceWrapper;
89 } PythonQtInstanceWrapper;
90
90
91 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
91
92
92 #endif No newline at end of file
93 #endif
General Comments 0
You need to be logged in to leave comments. Login now