##// 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 46 #include "PythonQtSlot.h"
47 47 #include "PythonQtClassInfo.h"
48 48 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
49 50
50 51 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
51 52 {
@@ -93,8 +94,39 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
93 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 126 static PyMethodDef PythonQtClassWrapper_methods[] = {
127 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
128 "Return the classname of the object"
129 },
98 130 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
99 131 "Return the classname of the object"
100 132 },
@@ -109,17 +141,44 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
109 141 {
110 142 const char *attributeName;
111 143 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
112
144
113 145 if ((attributeName = PyString_AsString(name)) == NULL) {
114 146 return NULL;
115 147 }
148 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
149 return NULL;
150 }
116 151
117 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
118 if (member._type == PythonQtMemberInfo::EnumValue) {
119 return PyInt_FromLong(member._enumValue);
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;
120 172 }
121 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
122 return PythonQtSlotFunction_New(member._slot, obj, NULL);
173
174 if (wrapper->classInfo()) {
175 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
176 if (member._type == PythonQtMemberInfo::EnumValue) {
177 return PyInt_FromLong(member._enumValue);
178 } else
179 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
180 return PythonQtSlotFunction_New(member._slot, obj, NULL);
181 }
123 182 }
124 183
125 184 // look for the interal methods (className(), help())
@@ -129,15 +188,10 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
129 188 }
130 189 PyErr_Clear();
131 190
132 if (qstrcmp(attributeName, "__dict__")==0) {
133 QStringList l = wrapper->classInfo()->memberList(true);
134 PyObject* dict = PyDict_New();
135 foreach (QString name, l) {
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;
191 // look in super
192 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
193 if (superAttr) {
194 return superAttr;
141 195 }
142 196
143 197 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
@@ -211,8 +265,8 PyTypeObject PythonQtClassWrapper_Type = {
211 265 0, /* tp_weaklistoffset */
212 266 0, /* tp_iter */
213 267 0, /* tp_iternext */
214 0, /* tp_methods */
215 0, /* tp_members */
268 0, /* tp_methods */
269 0, /* tp_members */
216 270 0, /* tp_getset */
217 271 0, /* tp_base */
218 272 0, /* tp_dict */
@@ -134,7 +134,7 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * args
134 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 139 PyObject* result = NULL;
140 140
@@ -247,29 +247,34 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
247 247 }
248 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 250 if (qstrcmp(attributeName, "__dict__")==0) {
262 251 QStringList l = wrapper->classInfo()->memberList(false);
263 252 PyObject* dict = PyDict_New();
264 253 foreach (QString name, l) {
265 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
254 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
266 255 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
267 //Py_DECREF(o);
256 Py_DECREF(o);
268 257 }
269 258 // Note: we do not put children into the dict, is would look confusing?!
270 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 279 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
275 280 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
@@ -332,6 +337,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
332 337 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
333 338 {
334 339 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
340 const char* typeName = obj->ob_type->tp_name;
335 341 QObject *qobj = wrapper->_obj;
336 342 if (wrapper->_wrappedPtr) {
337 343 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
@@ -339,28 +345,30 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
339 345 return PyString_FromFormat("%s", str.toLatin1().constData());
340 346 } else
341 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 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 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 357 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
352 358 {
353 359 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
360 const char* typeName = obj->ob_type->tp_name;
361
354 362 QObject *qobj = wrapper->_obj;
355 363 if (wrapper->_wrappedPtr) {
356 364 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
357 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 367 } else
360 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 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 373 } else {
366 374 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
@@ -88,5 +88,6 typedef struct PythonQtInstanceWrapperStruct {
88 88
89 89 } PythonQtInstanceWrapper;
90 90
91 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
91 92
92 93 #endif No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now