##// END OF EJS Templates
Updated from current MeVisLab development...
florianlink -
r173:7f1e2590af31
parent child
Show More
@@ -0,0 +1,350
1 /*
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
28 *
29 * http://www.mevis.de
30 *
31 */
32
33 //----------------------------------------------------------------------------------
34 /*!
35 // \file PythonQtSignal.cpp
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
38 // \date 2012-02
39 */
40 //----------------------------------------------------------------------------------
41
42 #include "PythonQt.h"
43 #include "PythonQtSignal.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtSlot.h"
49
50 #include <iostream>
51
52 #include <exception>
53 #include <stdexcept>
54
55 #include <QByteArray>
56
57 //-----------------------------------------------------------------------------------
58
59 static PythonQtSignalFunctionObject *PythonQtSignal_free_list = NULL;
60
61 PyObject *PythonQtSignalFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
62 {
63 PythonQtSignalFunctionObject* f = (PythonQtSignalFunctionObject*)func;
64 return PythonQtMemberFunction_Call(f->m_ml, f->m_self, args, kw);
65 }
66
67 PyObject *
68 PythonQtSignalFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
69 {
70 PythonQtSignalFunctionObject *op;
71 op = PythonQtSignal_free_list;
72 if (op != NULL) {
73 PythonQtSignal_free_list = (PythonQtSignalFunctionObject *)(op->m_self);
74 PyObject_INIT(op, &PythonQtSignalFunction_Type);
75 }
76 else {
77 op = PyObject_GC_New(PythonQtSignalFunctionObject, &PythonQtSignalFunction_Type);
78 if (op == NULL)
79 return NULL;
80 }
81 op->m_ml = ml;
82 Py_XINCREF(self);
83 op->m_self = self;
84 Py_XINCREF(module);
85 op->m_module = module;
86 PyObject_GC_Track(op);
87 return (PyObject *)op;
88 }
89
90 /* Methods (the standard built-in methods, that is) */
91
92 static void
93 meth_dealloc(PythonQtSignalFunctionObject *m)
94 {
95 PyObject_GC_UnTrack(m);
96 Py_XDECREF(m->m_self);
97 Py_XDECREF(m->m_module);
98 m->m_self = (PyObject *)PythonQtSignal_free_list;
99 PythonQtSignal_free_list = m;
100 }
101
102 static PyObject *
103 meth_get__doc__(PythonQtSignalFunctionObject * /*m*/, void * /*closure*/)
104 {
105 Py_INCREF(Py_None);
106 return Py_None;
107 }
108
109 static PyObject *
110 meth_get__name__(PythonQtSignalFunctionObject *m, void * /*closure*/)
111 {
112 return PyString_FromString(m->m_ml->metaMethod()->signature());
113 }
114
115 static int
116 meth_traverse(PythonQtSignalFunctionObject *m, visitproc visit, void *arg)
117 {
118 int err;
119 if (m->m_self != NULL) {
120 err = visit(m->m_self, arg);
121 if (err)
122 return err;
123 }
124 if (m->m_module != NULL) {
125 err = visit(m->m_module, arg);
126 if (err)
127 return err;
128 }
129 return 0;
130 }
131
132 static PyObject *
133 meth_get__self__(PythonQtSignalFunctionObject *m, void * /*closure*/)
134 {
135 PyObject *self;
136 if (PyEval_GetRestricted()) {
137 PyErr_SetString(PyExc_RuntimeError,
138 "method.__self__ not accessible in restricted mode");
139 return NULL;
140 }
141 self = m->m_self;
142 if (self == NULL)
143 self = Py_None;
144 Py_INCREF(self);
145 return self;
146 }
147
148 static PyGetSetDef meth_getsets [] = {
149 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
150 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
151 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
152 {NULL, NULL, NULL,NULL},
153 };
154
155 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
156 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
157 #endif
158
159 #define OFF(x) offsetof(PythonQtSignalFunctionObject, x)
160
161 static PyMemberDef meth_members[] = {
162 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
163 {NULL}
164 };
165
166 static PyObject *PythonQtSignalFunction_parameterTypes(PythonQtSignalFunctionObject* type)
167 {
168 return PythonQtMemberFunction_parameterTypes(type->m_ml);
169 }
170
171 static PyObject *PythonQtSignalFunction_parameterNames(PythonQtSignalFunctionObject* type)
172 {
173 return PythonQtMemberFunction_parameterNames(type->m_ml);
174 }
175
176 static PyObject *PythonQtSignalFunction_typeName(PythonQtSignalFunctionObject* type)
177 {
178 return PythonQtMemberFunction_typeName(type->m_ml);
179 }
180
181 static PyObject *PythonQtSignalFunction_connect(PythonQtSignalFunctionObject* type, PyObject *args)
182 {
183 if (PyObject_TypeCheck(type->m_self, &PythonQtInstanceWrapper_Type)) {
184 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) type->m_self;
185 if (self->_obj) {
186 Py_ssize_t argc = PyTuple_Size(args);
187 if (argc==1) {
188 // connect with Python callable
189 PyObject* callable = PyTuple_GET_ITEM(args, 0);
190 bool result = PythonQt::self()->addSignalHandler(self->_obj, QByteArray("2") + type->m_ml->metaMethod()->signature(), callable);
191 return PythonQtConv::GetPyBool(result);
192 } else {
193 PyErr_SetString(PyExc_ValueError, "Called connect with wrong number of arguments");
194 }
195 }
196 }
197 return NULL;
198 }
199
200 static PyObject *PythonQtSignalFunction_disconnect(PythonQtSignalFunctionObject* type, PyObject *args)
201 {
202 if (PyObject_TypeCheck(type->m_self, &PythonQtInstanceWrapper_Type)) {
203 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) type->m_self;
204 if (self->_obj) {
205 Py_ssize_t argc = PyTuple_Size(args);
206 QByteArray signal = QByteArray("2") + type->m_ml->metaMethod()->signature();
207 if (argc==1) {
208 // disconnect with Python callable
209 PyObject* callable = PyTuple_GET_ITEM(args, 0);
210 bool result = PythonQt::self()->removeSignalHandler(self->_obj, signal, callable);
211 return PythonQtConv::GetPyBool(result);
212 } else if (argc==0) {
213 bool result = PythonQt::self()->removeSignalHandler(self->_obj, signal, NULL);
214 result |= QObject::disconnect(self->_obj, signal, NULL, NULL);
215 return PythonQtConv::GetPyBool(result);
216 } else {
217 PyErr_SetString(PyExc_ValueError, "Called disconnect with wrong number of arguments");
218 }
219 }
220 }
221 return NULL;
222 }
223
224 static PyObject *PythonQtSignalFunction_emit(PythonQtSignalFunctionObject* func, PyObject *args)
225 {
226 PythonQtSignalFunctionObject* f = (PythonQtSignalFunctionObject*)func;
227 return PythonQtMemberFunction_Call(f->m_ml, f->m_self, args, NULL);
228 }
229
230 static PyMethodDef meth_methods[] = {
231 {"parameterTypes", (PyCFunction)PythonQtSignalFunction_parameterTypes, METH_NOARGS,
232 "Returns a tuple of tuples of the C++ parameter types for all overloads of the signal"
233 },
234 {"parameterNames", (PyCFunction)PythonQtSignalFunction_parameterNames, METH_NOARGS,
235 "Returns a tuple of tuples of the C++ parameter type names (if available), for all overloads of the signal"
236 },
237 {"typeName", (PyCFunction)PythonQtSignalFunction_typeName, METH_NOARGS,
238 "Returns a tuple of the C++ return value types of each signal overload"
239 },
240 {"connect", (PyCFunction)PythonQtSignalFunction_connect, METH_VARARGS,
241 "Connects the signal to the Python callable"
242 },
243 {"disconnect", (PyCFunction)PythonQtSignalFunction_disconnect, METH_VARARGS,
244 "Disconnects the signal from the given Python callable or disconnects all if no argument is passed."
245 },
246 {"emit", (PyCFunction)PythonQtSignalFunction_emit, METH_VARARGS,
247 "Emits the signal with given arguments"
248 },
249 {NULL, NULL, 0 , NULL} /* Sentinel */
250 };
251
252 static PyObject *
253 meth_repr(PythonQtSignalFunctionObject *f)
254 {
255 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
256 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
257 return PyString_FromFormat("<unbound qt signal %s of %s type>",
258 f->m_ml->slotName().data(),
259 self->classInfo()->className());
260 } else {
261 return PyString_FromFormat("<qt signal %s of %s instance at %p>",
262 f->m_ml->slotName().data(),
263 f->m_self->ob_type->tp_name,
264 f->m_self);
265 }
266 }
267
268 static int
269 meth_compare(PythonQtSignalFunctionObject *a, PythonQtSignalFunctionObject *b)
270 {
271 if (a->m_self != b->m_self)
272 return (a->m_self < b->m_self) ? -1 : 1;
273 if (a->m_ml == b->m_ml)
274 return 0;
275 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
276 return -1;
277 else
278 return 1;
279 }
280
281 static long
282 meth_hash(PythonQtSignalFunctionObject *a)
283 {
284 long x,y;
285 if (a->m_self == NULL)
286 x = 0;
287 else {
288 x = PyObject_Hash(a->m_self);
289 if (x == -1)
290 return -1;
291 }
292 y = _Py_HashPointer((void*)(a->m_ml));
293 if (y == -1)
294 return -1;
295 x ^= y;
296 if (x == -1)
297 x = -2;
298 return x;
299 }
300
301
302 PyTypeObject PythonQtSignalFunction_Type = {
303 PyObject_HEAD_INIT(&PyType_Type)
304 0,
305 "builtin_qt_signal",
306 sizeof(PythonQtSignalFunctionObject),
307 0,
308 (destructor)meth_dealloc, /* tp_dealloc */
309 0, /* tp_print */
310 0, /* tp_getattr */
311 0, /* tp_setattr */
312 (cmpfunc)meth_compare, /* tp_compare */
313 (reprfunc)meth_repr, /* tp_repr */
314 0, /* tp_as_number */
315 0, /* tp_as_sequence */
316 // TODO: implement tp_as_mapping to support overload resolution on the signal
317 0, /* tp_as_mapping */
318 (hashfunc)meth_hash, /* tp_hash */
319 PythonQtSignalFunction_Call, /* tp_call */
320 0, /* tp_str */
321 PyObject_GenericGetAttr, /* tp_getattro */
322 0, /* tp_setattro */
323 0, /* tp_as_buffer */
324 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
325 0, /* tp_doc */
326 (traverseproc)meth_traverse, /* tp_traverse */
327 0, /* tp_clear */
328 0, /* tp_richcompare */
329 0, /* tp_weaklistoffset */
330 0, /* tp_iter */
331 0, /* tp_iternext */
332 meth_methods, /* tp_methods */
333 meth_members, /* tp_members */
334 meth_getsets, /* tp_getset */
335 0, /* tp_base */
336 0, /* tp_dict */
337 };
338
339 /* Clear out the free list */
340
341 void
342 PythonQtSignalFunction_Fini(void)
343 {
344 while (PythonQtSignal_free_list) {
345 PythonQtSignalFunctionObject *v = PythonQtSignal_free_list;
346 PythonQtSignal_free_list = (PythonQtSignalFunctionObject *)(v->m_self);
347 PyObject_GC_Del(v);
348 }
349 }
350
@@ -0,0 +1,68
1 #ifndef _PythonQtSignal_H
2 #define _PythonQtSignal_H
3
4 /*
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
31 *
32 * http://www.mevis.de
33 *
34 */
35
36 //----------------------------------------------------------------------------------
37 /*!
38 // \file PythonQtSignal.h
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
42 */
43 //----------------------------------------------------------------------------------
44
45 #include "PythonQtPythonInclude.h"
46
47 #include "PythonQtSystem.h"
48 #include "structmember.h"
49
50 class PythonQtSlotInfo;
51
52 extern PYTHONQT_EXPORT PyTypeObject PythonQtSignalFunction_Type;
53
54 #define PythonQtSignalFunction_Check(op) ((op)->ob_type == &PythonQtSignalFunction_Type)
55
56 PyObject* PythonQtSignalFunction_New(PythonQtSlotInfo *, PyObject *,
57 PyObject *);
58
59 //! defines a python object that stores a Qt signal info
60 typedef struct {
61 PyObject_HEAD
62 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
63 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
64 PyObject *m_module; /* The __module__ attribute, can be anything */
65 } PythonQtSignalFunctionObject;
66
67
68 #endif
@@ -1,1352 +1,1692
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignal.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtStdIn.h"
49 #include "PythonQtStdIn.h"
49 #include "PythonQtStdOut.h"
50 #include "PythonQtStdOut.h"
50 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtVariants.h"
52 #include "PythonQtVariants.h"
52 #include "PythonQtStdDecorators.h"
53 #include "PythonQtStdDecorators.h"
53 #include "PythonQtQFileImporter.h"
54 #include "PythonQtQFileImporter.h"
54 #include <pydebug.h>
55 #include <pydebug.h>
55 #include <vector>
56 #include <vector>
56
57
57 PythonQt* PythonQt::_self = NULL;
58 PythonQt* PythonQt::_self = NULL;
58 int PythonQt::_uniqueModuleCount = 0;
59 int PythonQt::_uniqueModuleCount = 0;
59
60
60 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtCoreBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
62
63
63 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
64 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
64 {
65 {
65 if (!_self) {
66 if (!_self) {
66 _self = new PythonQt(flags, pythonQtModuleName);
67 _self = new PythonQt(flags, pythonQtModuleName);
67
68
68 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
69 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
69 qRegisterMetaType<QList<QObject*> >("QList<void*>");
70 qRegisterMetaType<QList<QObject*> >("QList<void*>");
70
71
71 PythonQtRegisterToolClassesTemplateConverter(int);
72 PythonQtRegisterToolClassesTemplateConverter(int);
72 PythonQtRegisterToolClassesTemplateConverter(float);
73 PythonQtRegisterToolClassesTemplateConverter(float);
73 PythonQtRegisterToolClassesTemplateConverter(double);
74 PythonQtRegisterToolClassesTemplateConverter(double);
74 PythonQtRegisterToolClassesTemplateConverter(qint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint32);
75 PythonQtRegisterToolClassesTemplateConverter(quint32);
76 PythonQtRegisterToolClassesTemplateConverter(quint32);
76 PythonQtRegisterToolClassesTemplateConverter(qint64);
77 PythonQtRegisterToolClassesTemplateConverter(qint64);
77 PythonQtRegisterToolClassesTemplateConverter(quint64);
78 PythonQtRegisterToolClassesTemplateConverter(quint64);
78 // TODO: which other POD types should be available for QList etc.
79 // TODO: which other POD types should be available for QList etc.
79
80
80 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
81 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
81
82
82 PythonQt_init_QtCoreBuiltin(NULL);
83 PythonQt_init_QtCoreBuiltin(NULL);
83 PythonQt_init_QtGuiBuiltin(NULL);
84 PythonQt_init_QtGuiBuiltin(NULL);
84
85
85 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
86 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
86 PythonQtRegisterToolClassesTemplateConverter(QDate);
87 PythonQtRegisterToolClassesTemplateConverter(QDate);
87 PythonQtRegisterToolClassesTemplateConverter(QTime);
88 PythonQtRegisterToolClassesTemplateConverter(QTime);
88 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
89 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
89 PythonQtRegisterToolClassesTemplateConverter(QUrl);
90 PythonQtRegisterToolClassesTemplateConverter(QUrl);
90 PythonQtRegisterToolClassesTemplateConverter(QLocale);
91 PythonQtRegisterToolClassesTemplateConverter(QLocale);
91 PythonQtRegisterToolClassesTemplateConverter(QRect);
92 PythonQtRegisterToolClassesTemplateConverter(QRect);
92 PythonQtRegisterToolClassesTemplateConverter(QRectF);
93 PythonQtRegisterToolClassesTemplateConverter(QRectF);
93 PythonQtRegisterToolClassesTemplateConverter(QSize);
94 PythonQtRegisterToolClassesTemplateConverter(QSize);
94 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
95 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
95 PythonQtRegisterToolClassesTemplateConverter(QLine);
96 PythonQtRegisterToolClassesTemplateConverter(QLine);
96 PythonQtRegisterToolClassesTemplateConverter(QLineF);
97 PythonQtRegisterToolClassesTemplateConverter(QLineF);
97 PythonQtRegisterToolClassesTemplateConverter(QPoint);
98 PythonQtRegisterToolClassesTemplateConverter(QPoint);
98 PythonQtRegisterToolClassesTemplateConverter(QPointF);
99 PythonQtRegisterToolClassesTemplateConverter(QPointF);
99 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
100 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
100
101
101 PythonQtRegisterToolClassesTemplateConverter(QFont);
102 PythonQtRegisterToolClassesTemplateConverter(QFont);
102 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
103 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
103 PythonQtRegisterToolClassesTemplateConverter(QBrush);
104 PythonQtRegisterToolClassesTemplateConverter(QBrush);
104 PythonQtRegisterToolClassesTemplateConverter(QColor);
105 PythonQtRegisterToolClassesTemplateConverter(QColor);
105 PythonQtRegisterToolClassesTemplateConverter(QPalette);
106 PythonQtRegisterToolClassesTemplateConverter(QPalette);
106 PythonQtRegisterToolClassesTemplateConverter(QIcon);
107 PythonQtRegisterToolClassesTemplateConverter(QIcon);
107 PythonQtRegisterToolClassesTemplateConverter(QImage);
108 PythonQtRegisterToolClassesTemplateConverter(QImage);
108 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
109 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
109 PythonQtRegisterToolClassesTemplateConverter(QRegion);
110 PythonQtRegisterToolClassesTemplateConverter(QRegion);
110 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
111 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
111 PythonQtRegisterToolClassesTemplateConverter(QCursor);
112 PythonQtRegisterToolClassesTemplateConverter(QCursor);
112 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
113 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
113 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
114 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
114 PythonQtRegisterToolClassesTemplateConverter(QPen);
115 PythonQtRegisterToolClassesTemplateConverter(QPen);
115 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
116 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
116 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
117 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
117 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
118 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
118
119
119
120
120 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
121 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
121 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
122 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
122 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
123 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
123 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
124 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
124 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
125 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
125 for (unsigned int i = 0;i<16; i++) {
126 for (unsigned int i = 0;i<16; i++) {
126 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
127 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
127 if (obj) {
128 if (obj) {
128 PyModule_AddObject(pack, names[i], obj);
129 PyModule_AddObject(pack, names[i], obj);
129 Py_INCREF(obj);
130 Py_INCREF(obj);
130 PyModule_AddObject(pack2, names[i], obj);
131 PyModule_AddObject(pack2, names[i], obj);
131 } else {
132 } else {
132 std::cerr << "method not found " << names[i];
133 std::cerr << "method not found " << names[i];
133 }
134 }
134 }
135 }
135 }
136 }
136 }
137 }
137
138
138 void PythonQt::cleanup()
139 void PythonQt::cleanup()
139 {
140 {
140 if (_self) {
141 if (_self) {
141 delete _self;
142 delete _self;
142 _self = NULL;
143 _self = NULL;
143 }
144 }
144 }
145 }
145
146
146 PythonQt* PythonQt::self() { return _self; }
147 PythonQt* PythonQt::self() { return _self; }
147
148
148 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
149 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
149 {
150 {
150 _p = new PythonQtPrivate;
151 _p = new PythonQtPrivate;
151 _p->_initFlags = flags;
152 _p->_initFlags = flags;
152
153
153 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
154 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
154
155
155 if ((flags & PythonAlreadyInitialized) == 0) {
156 if ((flags & PythonAlreadyInitialized) == 0) {
156 Py_SetProgramName(const_cast<char*>("PythonQt"));
157 Py_SetProgramName(const_cast<char*>("PythonQt"));
157 if (flags & IgnoreSiteModule) {
158 if (flags & IgnoreSiteModule) {
158 // this prevents the automatic importing of Python site files
159 // this prevents the automatic importing of Python site files
159 Py_NoSiteFlag = 1;
160 Py_NoSiteFlag = 1;
160 }
161 }
161 Py_Initialize();
162 Py_Initialize();
162 }
163 }
163
164
164 // add our own python object types for qt object slots
165 // add our own python object types for qt object slots
165 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
166 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
166 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
167 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
167 }
168 }
168 Py_INCREF(&PythonQtSlotFunction_Type);
169 Py_INCREF(&PythonQtSlotFunction_Type);
169
170
171 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
172 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
173 }
174 Py_INCREF(&PythonQtSignalFunction_Type);
175
170 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
176 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
171 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
177 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
172 // add our own python object types for classes
178 // add our own python object types for classes
173 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
179 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
174 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
180 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
175 }
181 }
176 Py_INCREF(&PythonQtClassWrapper_Type);
182 Py_INCREF(&PythonQtClassWrapper_Type);
177
183
178 // add our own python object types for CPP instances
184 // add our own python object types for CPP instances
179 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
185 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
180 PythonQt::handleError();
186 PythonQt::handleError();
181 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
187 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 }
188 }
183 Py_INCREF(&PythonQtInstanceWrapper_Type);
189 Py_INCREF(&PythonQtInstanceWrapper_Type);
184
190
185 // add our own python object types for redirection of stdout
191 // add our own python object types for redirection of stdout
186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
192 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
187 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
193 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 }
194 }
189 Py_INCREF(&PythonQtStdOutRedirectType);
195 Py_INCREF(&PythonQtStdOutRedirectType);
190
196
191 // add our own python object types for redirection of stdin
197 // add our own python object types for redirection of stdin
192 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
198 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
193 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
199 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
194 }
200 }
195 Py_INCREF(&PythonQtStdInRedirectType);
201 Py_INCREF(&PythonQtStdInRedirectType);
196
202
197 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
203 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
198
204
199 _p->setupSharedLibrarySuffixes();
205 _p->setupSharedLibrarySuffixes();
200
206
201 }
207 }
202
208
203 PythonQt::~PythonQt() {
209 PythonQt::~PythonQt() {
204 delete _p;
210 delete _p;
205 _p = NULL;
211 _p = NULL;
206 }
212 }
207
213
208 PythonQtPrivate::~PythonQtPrivate() {
214 PythonQtPrivate::~PythonQtPrivate() {
209 delete _defaultImporter;
215 delete _defaultImporter;
210 _defaultImporter = NULL;
216 _defaultImporter = NULL;
211
217
212 {
218 {
213 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
219 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
214 while (i.hasNext()) {
220 while (i.hasNext()) {
215 delete i.next().value();
221 delete i.next().value();
216 }
222 }
217 }
223 }
218 PythonQtConv::global_valueStorage.clear();
224 PythonQtConv::global_valueStorage.clear();
219 PythonQtConv::global_ptrStorage.clear();
225 PythonQtConv::global_ptrStorage.clear();
220 PythonQtConv::global_variantStorage.clear();
226 PythonQtConv::global_variantStorage.clear();
221
227
222 PythonQtMethodInfo::cleanupCachedMethodInfos();
228 PythonQtMethodInfo::cleanupCachedMethodInfos();
223 }
229 }
224
230
225 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
231 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
226 {
232 {
227 if (!callback)
233 if (!callback)
228 {
234 {
229 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
235 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
230 return;
236 return;
231 }
237 }
232
238
233 PythonQtObjectPtr sys;
239 PythonQtObjectPtr sys;
234 PythonQtObjectPtr in;
240 PythonQtObjectPtr in;
235 sys.setNewRef(PyImport_ImportModule("sys"));
241 sys.setNewRef(PyImport_ImportModule("sys"));
236
242
237 // Backup original 'sys.stdin' if not yet done
243 // Backup original 'sys.stdin' if not yet done
238 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
244 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
239 "sys.pythonqt_original_stdin = sys.stdin");
245 "sys.pythonqt_original_stdin = sys.stdin");
240
246
241 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
247 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
242 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
248 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
243 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
249 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
244 // replace the built in file objects with our own objects
250 // replace the built in file objects with our own objects
245 PyModule_AddObject(sys, "stdin", in);
251 PyModule_AddObject(sys, "stdin", in);
246
252
247 // Backup custom 'stdin' into 'pythonqt_stdin'
253 // Backup custom 'stdin' into 'pythonqt_stdin'
248 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
254 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
249 }
255 }
250
256
251 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
257 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
252 {
258 {
253 if (enabled)
259 if (enabled)
254 {
260 {
255 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
261 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
256 "sys.stdin = sys.pythonqt_stdin");
262 "sys.stdin = sys.pythonqt_stdin");
257 }
263 }
258 else
264 else
259 {
265 {
260 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
266 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
261 "sys.stdin = sys.pythonqt_original_stdin");
267 "sys.stdin = sys.pythonqt_original_stdin");
262 }
268 }
263 }
269 }
264
270
265 PythonQtImportFileInterface* PythonQt::importInterface()
271 PythonQtImportFileInterface* PythonQt::importInterface()
266 {
272 {
267 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
273 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
268 }
274 }
269
275
270 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
276 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
271 {
277 {
272 if (_self->_p->_noLongerWrappedCB) {
278 if (_self->_p->_noLongerWrappedCB) {
273 (*_self->_p->_noLongerWrappedCB)(o);
279 (*_self->_p->_noLongerWrappedCB)(o);
274 };
280 };
275 }
281 }
276
282
277 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
283 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
278 {
284 {
279 _p->registerClass(metaobject, package, wrapperCreator, shell);
285 _p->registerClass(metaobject, package, wrapperCreator, shell);
280 }
286 }
281
287
282 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
288 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
283 {
289 {
284 // we register all classes in the hierarchy
290 // we register all classes in the hierarchy
285 const QMetaObject* m = metaobject;
291 const QMetaObject* m = metaobject;
286 bool first = true;
292 bool first = true;
287 while (m) {
293 while (m) {
288 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
294 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
289 if (!info->pythonQtClassWrapper()) {
295 if (!info->pythonQtClassWrapper()) {
290 info->setTypeSlots(typeSlots);
296 info->setTypeSlots(typeSlots);
291 info->setupQObject(m);
297 info->setupQObject(m);
292 createPythonQtClassWrapper(info, package, module);
298 createPythonQtClassWrapper(info, package, module);
293 if (m->superClass()) {
299 if (m->superClass()) {
294 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
300 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
295 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
301 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
296 }
302 }
297 } else if (first && module) {
303 } else if (first && module) {
298 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
304 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
299 // since it might have been placed into "private" earlier on.
305 // since it might have been placed into "private" earlier on.
300 // If the wrapper was already added to module before, it is just readded, which does no harm.
306 // If the wrapper was already added to module before, it is just readded, which does no harm.
301 PyObject* classWrapper = info->pythonQtClassWrapper();
307 PyObject* classWrapper = info->pythonQtClassWrapper();
302 // AddObject steals a reference, so we need to INCREF
308 // AddObject steals a reference, so we need to INCREF
303 Py_INCREF(classWrapper);
309 Py_INCREF(classWrapper);
304 PyModule_AddObject(module, info->className(), classWrapper);
310 PyModule_AddObject(module, info->className(), classWrapper);
305 }
311 }
306 if (first) {
312 if (first) {
307 first = false;
313 first = false;
308 if (wrapperCreator) {
314 if (wrapperCreator) {
309 info->setDecoratorProvider(wrapperCreator);
315 info->setDecoratorProvider(wrapperCreator);
310 }
316 }
311 if (shell) {
317 if (shell) {
312 info->setShellSetInstanceWrapperCB(shell);
318 info->setShellSetInstanceWrapperCB(shell);
313 }
319 }
314 }
320 }
315 m = m->superClass();
321 m = m->superClass();
316 }
322 }
317 }
323 }
318
324
319 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
325 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
320 {
326 {
321 PyObject* pack = module?module:packageByName(package);
327 PyObject* pack = module?module:packageByName(package);
322 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
328 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
323 PyModule_AddObject(pack, info->className(), pyobj);
329 PyModule_AddObject(pack, info->className(), pyobj);
324 if (!module && package && strncmp(package,"Qt",2)==0) {
330 if (!module && package && strncmp(package,"Qt",2)==0) {
325 // since PyModule_AddObject steals the reference, we need a incref once more...
331 // since PyModule_AddObject steals the reference, we need a incref once more...
326 Py_INCREF(pyobj);
332 Py_INCREF(pyobj);
327 // put all qt objects into Qt as well
333 // put all qt objects into Qt as well
328 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
334 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
329 }
335 }
330 info->setPythonQtClassWrapper(pyobj);
336 info->setPythonQtClassWrapper(pyobj);
331 }
337 }
332
338
333 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
339 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
334 {
340 {
335 if (!obj) {
341 if (!obj) {
336 Py_INCREF(Py_None);
342 Py_INCREF(Py_None);
337 return Py_None;
343 return Py_None;
338 }
344 }
339 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
345 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
340 if (!wrap) {
346 if (!wrap) {
341 // smuggling it in...
347 // smuggling it in...
342 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
348 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
343 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
349 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
344 registerClass(obj->metaObject());
350 registerClass(obj->metaObject());
345 classInfo = _knownClassInfos.value(obj->metaObject()->className());
351 classInfo = _knownClassInfos.value(obj->metaObject()->className());
346 }
352 }
347 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
353 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
348 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
354 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
349 } else {
355 } else {
350 Py_INCREF(wrap);
356 Py_INCREF(wrap);
351 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
357 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
352 }
358 }
353 return (PyObject*)wrap;
359 return (PyObject*)wrap;
354 }
360 }
355
361
356 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
362 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
357 {
363 {
358 if (!ptr) {
364 if (!ptr) {
359 Py_INCREF(Py_None);
365 Py_INCREF(Py_None);
360 return Py_None;
366 return Py_None;
361 }
367 }
362
368
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
369 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
364 if (!wrap) {
370 if (!wrap) {
365 PythonQtClassInfo* info = _knownClassInfos.value(name);
371 PythonQtClassInfo* info = _knownClassInfos.value(name);
366 if (!info) {
372 if (!info) {
367 // maybe it is a PyObject, which we can return directly
373 // maybe it is a PyObject, which we can return directly
368 if (name == "PyObject") {
374 if (name == "PyObject") {
369 PyObject* p = (PyObject*)ptr;
375 PyObject* p = (PyObject*)ptr;
370 Py_INCREF(p);
376 Py_INCREF(p);
371 return p;
377 return p;
372 }
378 }
373
379
374 // we do not know the metaobject yet, but we might know it by it's name:
380 // we do not know the metaobject yet, but we might know it by it's name:
375 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
381 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
376 // yes, we know it, so we can convert to QObject
382 // yes, we know it, so we can convert to QObject
377 QObject* qptr = (QObject*)ptr;
383 QObject* qptr = (QObject*)ptr;
378 registerClass(qptr->metaObject());
384 registerClass(qptr->metaObject());
379 info = _knownClassInfos.value(qptr->metaObject()->className());
385 info = _knownClassInfos.value(qptr->metaObject()->className());
380 }
386 }
381 }
387 }
382 if (info && info->isQObject()) {
388 if (info && info->isQObject()) {
383 QObject* qptr = (QObject*)ptr;
389 QObject* qptr = (QObject*)ptr;
384 // if the object is a derived object, we want to switch the class info to the one of the derived class:
390 // if the object is a derived object, we want to switch the class info to the one of the derived class:
385 if (name!=(qptr->metaObject()->className())) {
391 if (name!=(qptr->metaObject()->className())) {
386 registerClass(qptr->metaObject());
392 registerClass(qptr->metaObject());
387 info = _knownClassInfos.value(qptr->metaObject()->className());
393 info = _knownClassInfos.value(qptr->metaObject()->className());
388 }
394 }
389 wrap = createNewPythonQtInstanceWrapper(qptr, info);
395 wrap = createNewPythonQtInstanceWrapper(qptr, info);
390 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
396 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
391 return (PyObject*)wrap;
397 return (PyObject*)wrap;
392 }
398 }
393
399
394 // not a known QObject, try to wrap via foreign wrapper factories
400 // not a known QObject, try to wrap via foreign wrapper factories
395 PyObject* foreignWrapper = NULL;
401 PyObject* foreignWrapper = NULL;
396 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
402 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
397 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
403 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
398 if (foreignWrapper) {
404 if (foreignWrapper) {
399 return foreignWrapper;
405 return foreignWrapper;
400 }
406 }
401 }
407 }
402
408
403 // not a known QObject, so try our wrapper factory:
409 // not a known QObject, so try our wrapper factory:
404 QObject* wrapper = NULL;
410 QObject* wrapper = NULL;
405 for (int i=0; i<_cppWrapperFactories.size(); i++) {
411 for (int i=0; i<_cppWrapperFactories.size(); i++) {
406 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
412 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
407 if (wrapper) {
413 if (wrapper) {
408 break;
414 break;
409 }
415 }
410 }
416 }
411
417
412 if (info) {
418 if (info) {
413 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
419 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
414 ptr = info->castDownIfPossible(ptr, &info);
420 ptr = info->castDownIfPossible(ptr, &info);
421
422 // if downcasting found out that the object is a QObject,
423 // handle it like one:
424 if (info && info->isQObject()) {
425 QObject* qptr = (QObject*)ptr;
426 // if the object is a derived object, we want to switch the class info to the one of the derived class:
427 if (name!=(qptr->metaObject()->className())) {
428 registerClass(qptr->metaObject());
429 info = _knownClassInfos.value(qptr->metaObject()->className());
430 }
431 wrap = createNewPythonQtInstanceWrapper(qptr, info);
432 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
433 return (PyObject*)wrap;
434 }
415 }
435 }
416
436
417 if (!info || info->pythonQtClassWrapper()==NULL) {
437 if (!info || info->pythonQtClassWrapper()==NULL) {
418 // still unknown, register as CPP class
438 // still unknown, register as CPP class
419 registerCPPClass(name.constData());
439 registerCPPClass(name.constData());
420 info = _knownClassInfos.value(name);
440 info = _knownClassInfos.value(name);
421 }
441 }
422 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
442 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
423 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
443 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
424 info->setMetaObject(wrapper->metaObject());
444 info->setMetaObject(wrapper->metaObject());
425 }
445 }
426
446
427 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
447 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
428 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
448 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
429 } else {
449 } else {
430 Py_INCREF(wrap);
450 Py_INCREF(wrap);
431 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
451 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
432 }
452 }
433 return (PyObject*)wrap;
453 return (PyObject*)wrap;
434 }
454 }
435
455
436 PyObject* PythonQtPrivate::dummyTuple() {
456 PyObject* PythonQtPrivate::dummyTuple() {
437 static PyObject* dummyTuple = NULL;
457 static PyObject* dummyTuple = NULL;
438 if (dummyTuple==NULL) {
458 if (dummyTuple==NULL) {
439 dummyTuple = PyTuple_New(1);
459 dummyTuple = PyTuple_New(1);
440 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
460 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
441 }
461 }
442 return dummyTuple;
462 return dummyTuple;
443 }
463 }
444
464
445
465
446 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
466 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
447 // call the associated class type to create a new instance...
467 // call the associated class type to create a new instance...
448 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
468 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
449
469
450 result->setQObject(obj);
470 result->setQObject(obj);
451 result->_wrappedPtr = wrappedPtr;
471 result->_wrappedPtr = wrappedPtr;
452 result->_ownedByPythonQt = false;
472 result->_ownedByPythonQt = false;
453 result->_useQMetaTypeDestroy = false;
473 result->_useQMetaTypeDestroy = false;
454
474
455 if (wrappedPtr) {
475 if (wrappedPtr) {
456 _wrappedObjects.insert(wrappedPtr, result);
476 _wrappedObjects.insert(wrappedPtr, result);
457 } else {
477 } else {
458 _wrappedObjects.insert(obj, result);
478 _wrappedObjects.insert(obj, result);
459 if (obj->parent()== NULL && _wrappedCB) {
479 if (obj->parent()== NULL && _wrappedCB) {
460 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
480 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
461 (*_wrappedCB)(obj);
481 (*_wrappedCB)(obj);
462 }
482 }
463 }
483 }
464 return result;
484 return result;
465 }
485 }
466
486
467 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
487 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
468 PythonQtClassWrapper* result;
488 PythonQtClassWrapper* result;
469
489
470 PyObject* className = PyString_FromString(info->className());
490 PyObject* className = PyString_FromString(info->className());
471
491
472 PyObject* baseClasses = PyTuple_New(1);
492 PyObject* baseClasses = PyTuple_New(1);
473 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
493 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
474
494
475 PyObject* typeDict = PyDict_New();
495 PyObject* typeDict = PyDict_New();
476 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
496 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
477 PyDict_SetItemString(typeDict, "__module__", moduleName);
497 PyDict_SetItemString(typeDict, "__module__", moduleName);
478
498
479 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
499 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
480
500
481 // set the class info so that PythonQtClassWrapper_new can read it
501 // set the class info so that PythonQtClassWrapper_new can read it
482 _currentClassInfoForClassWrapperCreation = info;
502 _currentClassInfoForClassWrapperCreation = info;
483 // create the new type object by calling the type
503 // create the new type object by calling the type
484 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
504 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
485
505
486 Py_DECREF(baseClasses);
506 Py_DECREF(baseClasses);
487 Py_DECREF(typeDict);
507 Py_DECREF(typeDict);
488 Py_DECREF(args);
508 Py_DECREF(args);
489 Py_DECREF(className);
509 Py_DECREF(className);
490
510
491 return result;
511 return result;
492 }
512 }
493
513
494 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
514 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
495 {
515 {
496 PyObject* args = Py_BuildValue("(i)", enumValue);
516 PyObject* args = Py_BuildValue("(i)", enumValue);
497 PyObject* result = PyObject_Call(enumType, args, NULL);
517 PyObject* result = PyObject_Call(enumType, args, NULL);
498 Py_DECREF(args);
518 Py_DECREF(args);
499 return result;
519 return result;
500 }
520 }
501
521
502 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
522 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
503 PyObject* result;
523 PyObject* result;
504
524
505 PyObject* className = PyString_FromString(enumName);
525 PyObject* className = PyString_FromString(enumName);
506
526
507 PyObject* baseClasses = PyTuple_New(1);
527 PyObject* baseClasses = PyTuple_New(1);
508 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
528 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
509
529
510 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
530 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
511 PyObject* typeDict = PyDict_New();
531 PyObject* typeDict = PyDict_New();
512 PyDict_SetItemString(typeDict, "__module__", module);
532 PyDict_SetItemString(typeDict, "__module__", module);
513
533
514 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
534 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
515
535
516 // create the new int derived type object by calling the core type
536 // create the new int derived type object by calling the core type
517 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
537 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
518
538
519 Py_DECREF(baseClasses);
539 Py_DECREF(baseClasses);
520 Py_DECREF(typeDict);
540 Py_DECREF(typeDict);
521 Py_DECREF(args);
541 Py_DECREF(args);
522 Py_DECREF(className);
542 Py_DECREF(className);
523
543
524 return result;
544 return result;
525 }
545 }
526
546
527 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
547 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
528 {
548 {
529 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
549 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
530 if (!r) {
550 if (!r) {
531 r = new PythonQtSignalReceiver(obj);
551 r = new PythonQtSignalReceiver(obj);
532 _p->_signalReceivers.insert(obj, r);
552 _p->_signalReceivers.insert(obj, r);
533 }
553 }
534 return r;
554 return r;
535 }
555 }
536
556
537 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
557 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
538 {
558 {
539 bool flag = false;
559 bool flag = false;
540 PythonQtObjectPtr callable = lookupCallable(module, objectname);
560 PythonQtObjectPtr callable = lookupCallable(module, objectname);
541 if (callable) {
561 if (callable) {
542 PythonQtSignalReceiver* r = getSignalReceiver(obj);
562 PythonQtSignalReceiver* r = getSignalReceiver(obj);
543 flag = r->addSignalHandler(signal, callable);
563 flag = r->addSignalHandler(signal, callable);
544 if (!flag) {
564 if (!flag) {
545 // signal not found
565 // signal not found
546 }
566 }
547 } else {
567 } else {
548 // callable not found
568 // callable not found
549 }
569 }
550 return flag;
570 return flag;
551 }
571 }
552
572
553 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
573 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
554 {
574 {
555 bool flag = false;
575 bool flag = false;
556 PythonQtSignalReceiver* r = getSignalReceiver(obj);
576 PythonQtSignalReceiver* r = getSignalReceiver(obj);
557 if (r) {
577 if (r) {
558 flag = r->addSignalHandler(signal, receiver);
578 flag = r->addSignalHandler(signal, receiver);
559 }
579 }
560 return flag;
580 return flag;
561 }
581 }
562
582
563 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
583 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
564 {
584 {
565 bool flag = false;
585 bool flag = false;
566 PythonQtObjectPtr callable = lookupCallable(module, objectname);
586 PythonQtObjectPtr callable = lookupCallable(module, objectname);
567 if (callable) {
587 if (callable) {
568 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
588 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
569 if (r) {
589 if (r) {
570 flag = r->removeSignalHandler(signal, callable);
590 flag = r->removeSignalHandler(signal, callable);
571 }
591 }
572 } else {
592 } else {
573 // callable not found
593 // callable not found
574 }
594 }
575 return flag;
595 return flag;
576 }
596 }
577
597
578 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
598 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
579 {
599 {
580 bool flag = false;
600 bool flag = false;
581 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
601 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
582 if (r) {
602 if (r) {
583 flag = r->removeSignalHandler(signal, receiver);
603 flag = r->removeSignalHandler(signal, receiver);
584 }
604 }
585 return flag;
605 return flag;
586 }
606 }
587
607
588 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
608 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
589 {
609 {
590 PythonQtObjectPtr p = lookupObject(module, name);
610 PythonQtObjectPtr p = lookupObject(module, name);
591 if (p) {
611 if (p) {
592 if (PyCallable_Check(p)) {
612 if (PyCallable_Check(p)) {
593 return p;
613 return p;
594 }
614 }
595 }
615 }
596 PyErr_Clear();
616 PyErr_Clear();
597 return NULL;
617 return NULL;
598 }
618 }
599
619
600 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
620 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
601 {
621 {
602 QStringList l = name.split('.');
622 QStringList l = name.split('.');
603 PythonQtObjectPtr p = module;
623 PythonQtObjectPtr p = module;
604 PythonQtObjectPtr prev;
624 PythonQtObjectPtr prev;
605 QString s;
606 QByteArray b;
625 QByteArray b;
607 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
626 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
608 prev = p;
627 prev = p;
609 b = (*i).toLatin1();
628 b = (*i).toLatin1();
610 if (PyDict_Check(p)) {
629 if (PyDict_Check(p)) {
611 p = PyDict_GetItemString(p, b.data());
630 p = PyDict_GetItemString(p, b.data());
612 } else {
631 } else {
613 p.setNewRef(PyObject_GetAttrString(p, b.data()));
632 p.setNewRef(PyObject_GetAttrString(p, b.data()));
614 }
633 }
615 }
634 }
616 PyErr_Clear();
635 PyErr_Clear();
617 return p;
636 return p;
618 }
637 }
619
638
620 PythonQtObjectPtr PythonQt::getMainModule() {
639 PythonQtObjectPtr PythonQt::getMainModule() {
621 //both borrowed
640 //both borrowed
622 PythonQtObjectPtr dict = PyImport_GetModuleDict();
641 PythonQtObjectPtr dict = PyImport_GetModuleDict();
623 return PyDict_GetItemString(dict, "__main__");
642 return PyDict_GetItemString(dict, "__main__");
624 }
643 }
625
644
626 PythonQtObjectPtr PythonQt::importModule(const QString& name)
645 PythonQtObjectPtr PythonQt::importModule(const QString& name)
627 {
646 {
628 PythonQtObjectPtr mod;
647 PythonQtObjectPtr mod;
629 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
648 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
630 return mod;
649 return mod;
631 }
650 }
632
651
633
652
634 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
653 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
635 QVariant result;
654 QVariant result;
636 if (pycode) {
655 if (pycode) {
637 PyObject* dict = NULL;
656 PyObject* dict = NULL;
638 if (PyModule_Check(object)) {
657 if (PyModule_Check(object)) {
639 dict = PyModule_GetDict(object);
658 dict = PyModule_GetDict(object);
640 } else if (PyDict_Check(object)) {
659 } else if (PyDict_Check(object)) {
641 dict = object;
660 dict = object;
642 }
661 }
643 PyObject* r = NULL;
662 PyObject* r = NULL;
644 if (dict) {
663 if (dict) {
645 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
664 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
646 }
665 }
647 if (r) {
666 if (r) {
648 result = PythonQtConv::PyObjToQVariant(r);
667 result = PythonQtConv::PyObjToQVariant(r);
649 Py_DECREF(r);
668 Py_DECREF(r);
650 } else {
669 } else {
651 handleError();
670 handleError();
652 }
671 }
653 } else {
672 } else {
654 handleError();
673 handleError();
655 }
674 }
656 return result;
675 return result;
657 }
676 }
658
677
659 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
678 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
660 {
679 {
661 QVariant result;
680 QVariant result;
662 PythonQtObjectPtr p;
681 PythonQtObjectPtr p;
663 PyObject* dict = NULL;
682 PyObject* dict = NULL;
664 if (PyModule_Check(object)) {
683 if (PyModule_Check(object)) {
665 dict = PyModule_GetDict(object);
684 dict = PyModule_GetDict(object);
666 } else if (PyDict_Check(object)) {
685 } else if (PyDict_Check(object)) {
667 dict = object;
686 dict = object;
668 }
687 }
669 if (dict) {
688 if (dict) {
670 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
689 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
671 }
690 }
672 if (p) {
691 if (p) {
673 result = PythonQtConv::PyObjToQVariant(p);
692 result = PythonQtConv::PyObjToQVariant(p);
674 } else {
693 } else {
675 handleError();
694 handleError();
676 }
695 }
677 return result;
696 return result;
678 }
697 }
679
698
680 void PythonQt::evalFile(PyObject* module, const QString& filename)
699 void PythonQt::evalFile(PyObject* module, const QString& filename)
681 {
700 {
682 PythonQtObjectPtr code = parseFile(filename);
701 PythonQtObjectPtr code = parseFile(filename);
683 if (code) {
702 if (code) {
684 evalCode(module, code);
703 evalCode(module, code);
685 } else {
704 } else {
686 handleError();
705 handleError();
687 }
706 }
688 }
707 }
689
708
690 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
709 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
691 {
710 {
692 PythonQtObjectPtr p;
711 PythonQtObjectPtr p;
693 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
712 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
694 if (!p) {
713 if (!p) {
695 handleError();
714 handleError();
696 }
715 }
697 return p;
716 return p;
698 }
717 }
699
718
700 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
719 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
701 {
720 {
702 PythonQtObjectPtr code = parseFile(filename);
721 PythonQtObjectPtr code = parseFile(filename);
703 PythonQtObjectPtr module = _p->createModule(name, code);
722 PythonQtObjectPtr module = _p->createModule(name, code);
704 return module;
723 return module;
705 }
724 }
706
725
707 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
726 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
708 {
727 {
709 PyErr_Clear();
728 PyErr_Clear();
710 QString scriptCode = script;
729 QString scriptCode = script;
711 if (scriptCode.isEmpty()) {
730 if (scriptCode.isEmpty()) {
712 // we always need at least a linefeed
731 // we always need at least a linefeed
713 scriptCode = "\n";
732 scriptCode = "\n";
714 }
733 }
715 PythonQtObjectPtr pycode;
734 PythonQtObjectPtr pycode;
716 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
735 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
717 PythonQtObjectPtr module = _p->createModule(name, pycode);
736 PythonQtObjectPtr module = _p->createModule(name, pycode);
718 return module;
737 return module;
719 }
738 }
720
739
721 PythonQtObjectPtr PythonQt::createUniqueModule()
740 PythonQtObjectPtr PythonQt::createUniqueModule()
722 {
741 {
723 static QString pyQtStr("PythonQt_module");
742 static QString pyQtStr("PythonQt_module");
724 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
743 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
725 return createModuleFromScript(moduleName);
744 return createModuleFromScript(moduleName);
726 }
745 }
727
746
728 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
747 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
729 {
748 {
730 if (PyModule_Check(object)) {
749 if (PyModule_Check(object)) {
731 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
750 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
732 } else if (PyDict_Check(object)) {
751 } else if (PyDict_Check(object)) {
733 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
752 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
734 } else {
753 } else {
735 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
754 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
736 }
755 }
737 }
756 }
738
757
739 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
758 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
740 {
759 {
741 if (PyModule_Check(object)) {
760 if (PyModule_Check(object)) {
742 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
761 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
743 } else if (PyDict_Check(object)) {
762 } else if (PyDict_Check(object)) {
744 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
763 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
745 } else {
764 } else {
746 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
765 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
747 }
766 }
748 }
767 }
749
768
750 void PythonQt::removeVariable(PyObject* object, const QString& name)
769 void PythonQt::removeVariable(PyObject* object, const QString& name)
751 {
770 {
752 if (PyDict_Check(object)) {
771 if (PyDict_Check(object)) {
753 PyDict_DelItemString(object, name.toLatin1().data());
772 PyDict_DelItemString(object, name.toLatin1().data());
754 } else {
773 } else {
755 PyObject_DelAttrString(object, name.toLatin1().data());
774 PyObject_DelAttrString(object, name.toLatin1().data());
756 }
775 }
757 }
776 }
758
777
759 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
778 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
760 {
779 {
761 QVariant result;
780 QVariant result;
762 PythonQtObjectPtr obj = lookupObject(object, objectname);
781 PythonQtObjectPtr obj = lookupObject(object, objectname);
763 if (obj) {
782 if (obj) {
764 result = PythonQtConv::PyObjToQVariant(obj);
783 result = PythonQtConv::PyObjToQVariant(obj);
765 }
784 }
766 return result;
785 return result;
767 }
786 }
768
787
769 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
788 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
770 {
789 {
771 QStringList results;
790 QStringList results;
772
791
773 PythonQtObjectPtr object;
792 PythonQtObjectPtr object;
774 if (objectname.isEmpty()) {
793 if (objectname.isEmpty()) {
775 object = module;
794 object = module;
776 } else {
795 } else {
777 object = lookupObject(module, objectname);
796 object = lookupObject(module, objectname);
778 if (!object && type == CallOverloads) {
797 if (!object && type == CallOverloads) {
779 PyObject* dict = lookupObject(module, "__builtins__");
798 PyObject* dict = lookupObject(module, "__builtins__");
780 if (dict) {
799 if (dict) {
781 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
800 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
782 }
801 }
783 }
802 }
784 }
803 }
785
804
786 if (object) {
805 if (object) {
806 results = introspectObject(object, type);
807 }
808
809 return results;
810 }
811
812 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
813 {
814 QStringList results;
815
787 if (type == CallOverloads) {
816 if (type == CallOverloads) {
788 if (PythonQtSlotFunction_Check(object)) {
817 if (PythonQtSlotFunction_Check(object)) {
789 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
818 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
819 PythonQtSlotInfo* info = o->m_ml;
820
821 while (info) {
822 results << info->fullSignature();
823 info = info->nextInfo();
824 }
825 } else if (PythonQtSignalFunction_Check(object)) {
826 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
790 PythonQtSlotInfo* info = o->m_ml;
827 PythonQtSlotInfo* info = o->m_ml;
791
828
792 while (info) {
829 while (info) {
793 results << info->fullSignature();
830 results << info->fullSignature();
794 info = info->nextInfo();
831 info = info->nextInfo();
795 }
832 }
796 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
833 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
797 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
834 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
798 PythonQtSlotInfo* info = o->classInfo()->constructors();
835 PythonQtSlotInfo* info = o->classInfo()->constructors();
799
836
800 while (info) {
837 while (info) {
801 results << info->fullSignature();
838 results << info->fullSignature();
802 info = info->nextInfo();
839 info = info->nextInfo();
803 }
840 }
804 } else {
841 } else {
805 //TODO: use pydoc!
842 QString signature = _p->getSignature(object);
843 if (!signature.isEmpty()) {
844 results << signature;
845 } else {
806 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
846 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
807 if (doc) {
847 if (doc) {
808 results << PyString_AsString(doc);
848 results << PyString_AsString(doc);
809 Py_DECREF(doc);
849 Py_DECREF(doc);
810 }
850 }
811 }
851 }
852 }
812 } else {
853 } else {
813 PyObject* keys = NULL;
854 PyObject* keys = NULL;
814 bool isDict = false;
855 bool isDict = false;
815 if (PyDict_Check(object)) {
856 if (PyDict_Check(object)) {
816 keys = PyDict_Keys(object);
857 keys = PyDict_Keys(object);
817 isDict = true;
858 isDict = true;
818 } else {
859 } else {
819 keys = PyObject_Dir(object);
860 keys = PyObject_Dir(object);
820 }
861 }
821 if (keys) {
862 if (keys) {
822 int count = PyList_Size(keys);
863 int count = PyList_Size(keys);
823 PyObject* key;
864 PyObject* key;
824 PyObject* value;
865 PyObject* value;
825 QString keystr;
866 QString keystr;
826 for (int i = 0;i<count;i++) {
867 for (int i = 0;i<count;i++) {
827 key = PyList_GetItem(keys,i);
868 key = PyList_GetItem(keys,i);
828 if (isDict) {
869 if (isDict) {
829 value = PyDict_GetItem(object, key);
870 value = PyDict_GetItem(object, key);
830 Py_INCREF(value);
871 Py_INCREF(value);
831 } else {
872 } else {
832 value = PyObject_GetAttr(object, key);
873 value = PyObject_GetAttr(object, key);
833 }
874 }
834 if (!value) continue;
875 if (!value) continue;
835 keystr = PyString_AsString(key);
876 keystr = PyString_AsString(key);
836 static const QString underscoreStr("__tmp");
877 static const QString underscoreStr("__tmp");
837 if (!keystr.startsWith(underscoreStr)) {
878 if (!keystr.startsWith(underscoreStr)) {
838 switch (type) {
879 switch (type) {
839 case Anything:
880 case Anything:
840 results << keystr;
881 results << keystr;
841 break;
882 break;
842 case Class:
883 case Class:
843 if (value->ob_type == &PyClass_Type) {
884 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
844 results << keystr;
885 results << keystr;
845 }
886 }
846 break;
887 break;
847 case Variable:
888 case Variable:
848 if (value->ob_type != &PyClass_Type
889 if (value->ob_type != &PyClass_Type
849 && value->ob_type != &PyCFunction_Type
890 && value->ob_type != &PyCFunction_Type
850 && value->ob_type != &PyFunction_Type
891 && value->ob_type != &PyFunction_Type
892 && value->ob_type != &PyMethod_Type
851 && value->ob_type != &PyModule_Type
893 && value->ob_type != &PyModule_Type
894 && value->ob_type != &PyType_Type
895 && value->ob_type != &PythonQtSlotFunction_Type
852 ) {
896 ) {
853 results << keystr;
897 results << keystr;
854 }
898 }
855 break;
899 break;
856 case Function:
900 case Function:
857 if (value->ob_type == &PyFunction_Type ||
901 if (value->ob_type == &PyCFunction_Type ||
858 value->ob_type == &PyMethod_Type
902 value->ob_type == &PyFunction_Type ||
903 value->ob_type == &PyMethod_Type ||
904 value->ob_type == &PythonQtSlotFunction_Type
859 ) {
905 ) {
860 results << keystr;
906 results << keystr;
861 }
907 }
862 break;
908 break;
863 case Module:
909 case Module:
864 if (value->ob_type == &PyModule_Type) {
910 if (value->ob_type == &PyModule_Type) {
865 results << keystr;
911 results << keystr;
866 }
912 }
867 break;
913 break;
868 default:
914 default:
869 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
915 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
870 }
916 }
871 }
917 }
872 Py_DECREF(value);
918 Py_DECREF(value);
873 }
919 }
874 Py_DECREF(keys);
920 Py_DECREF(keys);
875 }
921 }
876 }
922 }
923 return results;
924 }
925
926 PyObject* PythonQt::getObjectByType(const QString& typeName)
927 {
928 PythonQtObjectPtr sys;
929 sys.setNewRef(PyImport_ImportModule("sys"));
930 PythonQtObjectPtr modules = lookupObject(sys, "modules");
931 Q_ASSERT(PyDict_Check(modules));
932
933 QStringList tmp = typeName.split(".");
934 QString simpleTypeName = tmp.takeLast();
935 QString moduleName = tmp.join(".");
936
937 PyObject* object = NULL;
938 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
939 if (moduleObject) {
940 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
941 }
942
943 if (!object) {
944 moduleObject = PyDict_GetItemString(modules, "__builtin__");
945 if (moduleObject) {
946 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
947 }
948 }
949
950 return object;
951 }
952
953 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
954 {
955 QStringList results;
956 PyObject* object = getObjectByType(typeName);
957 if (!object) {
958 // the last item may be a member, split it away and try again
959 QStringList tmp = typeName.split(".");
960 QString memberName = tmp.takeLast();
961 QString typeName = tmp.takeLast();
962 PyObject* typeObject = getObjectByType(typeName);
963 if (typeObject) {
964 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
965 }
966 }
967 if (object) {
968 results = introspectObject(object, type);
969 Py_DECREF(object);
877 }
970 }
878 return results;
971 return results;
879 }
972 }
880
973
881 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
974 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
882 {
975 {
883 PythonQtObjectPtr callable = lookupCallable(object, name);
976 PythonQtObjectPtr callable = lookupCallable(object, name);
884 if (callable) {
977 if (callable) {
885 return call(callable, args);
978 return call(callable, args);
886 } else {
979 } else {
887 return QVariant();
980 return QVariant();
888 }
981 }
889 }
982 }
890
983
891 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
984 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
892 {
985 {
893 QVariant r;
986 QVariant r;
894 PythonQtObjectPtr result;
987 PythonQtObjectPtr result;
895 result.setNewRef(callAndReturnPyObject(callable, args));
988 result.setNewRef(callAndReturnPyObject(callable, args));
896 if (result) {
989 if (result) {
897 r = PythonQtConv::PyObjToQVariant(result);
990 r = PythonQtConv::PyObjToQVariant(result);
898 } else {
991 } else {
899 PythonQt::self()->handleError();
992 PythonQt::self()->handleError();
900 }
993 }
901 return r;
994 return r;
902 }
995 }
903
996
904 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
997 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
905 {
998 {
906 PyObject* result = NULL;
999 PyObject* result = NULL;
907 if (callable) {
1000 if (callable) {
908 PythonQtObjectPtr pargs;
1001 PythonQtObjectPtr pargs;
909 int count = args.size();
1002 int count = args.size();
910 if (count>0) {
1003 if (count>0) {
911 pargs.setNewRef(PyTuple_New(count));
1004 pargs.setNewRef(PyTuple_New(count));
912 }
1005 }
913 bool err = false;
1006 bool err = false;
914 // transform QVariants to Python
1007 // transform QVariants to Python
915 for (int i = 0; i < count; i++) {
1008 for (int i = 0; i < count; i++) {
916 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1009 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
917 if (arg) {
1010 if (arg) {
918 // steals reference, no unref
1011 // steals reference, no unref
919 PyTuple_SetItem(pargs, i,arg);
1012 PyTuple_SetItem(pargs, i,arg);
920 } else {
1013 } else {
921 err = true;
1014 err = true;
922 break;
1015 break;
923 }
1016 }
924 }
1017 }
925
1018
926 if (!err) {
1019 if (!err) {
927 PyErr_Clear();
1020 PyErr_Clear();
928 result = PyObject_CallObject(callable, pargs);
1021 result = PyObject_CallObject(callable, pargs);
929 }
1022 }
930 }
1023 }
931 return result;
1024 return result;
932 }
1025 }
933
1026
934 void PythonQt::addInstanceDecorators(QObject* o)
1027 void PythonQt::addInstanceDecorators(QObject* o)
935 {
1028 {
936 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1029 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
937 }
1030 }
938
1031
939 void PythonQt::addClassDecorators(QObject* o)
1032 void PythonQt::addClassDecorators(QObject* o)
940 {
1033 {
941 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1034 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
942 }
1035 }
943
1036
944 void PythonQt::addDecorators(QObject* o)
1037 void PythonQt::addDecorators(QObject* o)
945 {
1038 {
946 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1039 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
947 }
1040 }
948
1041
949 void PythonQt::registerQObjectClassNames(const QStringList& names)
1042 void PythonQt::registerQObjectClassNames(const QStringList& names)
950 {
1043 {
951 _p->registerQObjectClassNames(names);
1044 _p->registerQObjectClassNames(names);
952 }
1045 }
953
1046
954 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1047 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
955 {
1048 {
956 _p->_importInterface = importInterface;
1049 _p->_importInterface = importInterface;
957 PythonQtImport::init();
1050 PythonQtImport::init();
958 }
1051 }
959
1052
960 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1053 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
961 {
1054 {
962 _p->_importIgnorePaths = paths;
1055 _p->_importIgnorePaths = paths;
963 }
1056 }
964
1057
965 const QStringList& PythonQt::getImporterIgnorePaths()
1058 const QStringList& PythonQt::getImporterIgnorePaths()
966 {
1059 {
967 return _p->_importIgnorePaths;
1060 return _p->_importIgnorePaths;
968 }
1061 }
969
1062
970 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1063 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
971 {
1064 {
972 _p->_cppWrapperFactories.append(factory);
1065 _p->_cppWrapperFactories.append(factory);
973 }
1066 }
974
1067
975 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1068 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
976 {
1069 {
977 _p->_foreignWrapperFactories.append(factory);
1070 _p->_foreignWrapperFactories.append(factory);
978 }
1071 }
979
1072
980 //---------------------------------------------------------------------------------------------------
1073 //---------------------------------------------------------------------------------------------------
981 PythonQtPrivate::PythonQtPrivate()
1074 PythonQtPrivate::PythonQtPrivate()
982 {
1075 {
983 _importInterface = NULL;
1076 _importInterface = NULL;
984 _defaultImporter = new PythonQtQFileImporter;
1077 _defaultImporter = new PythonQtQFileImporter;
985 _noLongerWrappedCB = NULL;
1078 _noLongerWrappedCB = NULL;
986 _wrappedCB = NULL;
1079 _wrappedCB = NULL;
987 _currentClassInfoForClassWrapperCreation = NULL;
1080 _currentClassInfoForClassWrapperCreation = NULL;
988 _profilingCB = NULL;
1081 _profilingCB = NULL;
989 }
1082 }
990
1083
991 void PythonQtPrivate::setupSharedLibrarySuffixes()
1084 void PythonQtPrivate::setupSharedLibrarySuffixes()
992 {
1085 {
993 _sharedLibrarySuffixes.clear();
1086 _sharedLibrarySuffixes.clear();
994 PythonQtObjectPtr imp;
1087 PythonQtObjectPtr imp;
995 imp.setNewRef(PyImport_ImportModule("imp"));
1088 imp.setNewRef(PyImport_ImportModule("imp"));
996 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1089 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
997 QVariant result = imp.call("get_suffixes");
1090 QVariant result = imp.call("get_suffixes");
998 #ifdef __linux
1091 #ifdef __linux
999 #ifdef _DEBUG
1092 #ifdef _DEBUG
1000 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1093 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1001 // This is a workaround, because python does not append the '_d' suffix on Linux
1094 // This is a workaround, because python does not append the '_d' suffix on Linux
1002 // and would always load the release library otherwise.
1095 // and would always load the release library otherwise.
1003 _sharedLibrarySuffixes << "_d.so";
1096 _sharedLibrarySuffixes << "_d.so";
1004 #endif
1097 #endif
1005 #endif
1098 #endif
1006 foreach (QVariant entry, result.toList()) {
1099 foreach (QVariant entry, result.toList()) {
1007 QVariantList suffixEntry = entry.toList();
1100 QVariantList suffixEntry = entry.toList();
1008 if (suffixEntry.count()==3) {
1101 if (suffixEntry.count()==3) {
1009 int code = suffixEntry.at(2).toInt();
1102 int code = suffixEntry.at(2).toInt();
1010 if (code == cExtensionCode) {
1103 if (code == cExtensionCode) {
1011 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1104 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1012 }
1105 }
1013 }
1106 }
1014 }
1107 }
1015 }
1108 }
1016
1109
1017 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1110 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1018 {
1111 {
1019 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1112 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1020 _currentClassInfoForClassWrapperCreation = NULL;
1113 _currentClassInfoForClassWrapperCreation = NULL;
1021 return info;
1114 return info;
1022 }
1115 }
1023
1116
1024 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1117 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1025 {
1118 {
1026 o->setParent(this);
1119 o->setParent(this);
1027 int numMethods = o->metaObject()->methodCount();
1120 int numMethods = o->metaObject()->methodCount();
1028 for (int i = 0; i < numMethods; i++) {
1121 for (int i = 0; i < numMethods; i++) {
1029 QMetaMethod m = o->metaObject()->method(i);
1122 QMetaMethod m = o->metaObject()->method(i);
1030 if ((m.methodType() == QMetaMethod::Method ||
1123 if ((m.methodType() == QMetaMethod::Method ||
1031 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1124 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1032 if (qstrncmp(m.signature(), "new_", 4)==0) {
1125 if (qstrncmp(m.signature(), "new_", 4)==0) {
1033 if ((decoTypes & ConstructorDecorator) == 0) continue;
1126 if ((decoTypes & ConstructorDecorator) == 0) continue;
1034 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1127 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1035 if (info->parameters().at(0).pointerCount == 1) {
1128 if (info->parameters().at(0).pointerCount == 1) {
1036 QByteArray signature = m.signature();
1129 QByteArray signature = m.signature();
1037 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1130 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1038 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1131 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1039 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1132 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1040 classInfo->addConstructor(newSlot);
1133 classInfo->addConstructor(newSlot);
1041 }
1134 }
1042 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1135 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1043 if ((decoTypes & DestructorDecorator) == 0) continue;
1136 if ((decoTypes & DestructorDecorator) == 0) continue;
1044 QByteArray signature = m.signature();
1137 QByteArray signature = m.signature();
1045 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1138 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1046 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1139 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1047 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1140 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1048 classInfo->setDestructor(newSlot);
1141 classInfo->setDestructor(newSlot);
1049 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1142 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1050 if ((decoTypes & StaticDecorator) == 0) continue;
1143 if ((decoTypes & StaticDecorator) == 0) continue;
1051 QByteArray signature = m.signature();
1144 QByteArray signature = m.signature();
1052 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1145 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1053 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1146 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1054 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1147 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1055 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1148 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1056 classInfo->addDecoratorSlot(newSlot);
1149 classInfo->addDecoratorSlot(newSlot);
1057 } else {
1150 } else {
1058 if ((decoTypes & InstanceDecorator) == 0) continue;
1151 if ((decoTypes & InstanceDecorator) == 0) continue;
1059 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1152 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1060 if (info->parameters().count()>1) {
1153 if (info->parameters().count()>1) {
1061 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1154 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1062 if (p.pointerCount==1) {
1155 if (p.pointerCount==1) {
1063 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1156 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1064 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1157 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1065 classInfo->addDecoratorSlot(newSlot);
1158 classInfo->addDecoratorSlot(newSlot);
1066 }
1159 }
1067 }
1160 }
1068 }
1161 }
1069 }
1162 }
1070 }
1163 }
1071 }
1164 }
1072
1165
1073 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1166 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1074 {
1167 {
1075 foreach(QString name, names) {
1168 foreach(QString name, names) {
1076 _knownQObjectClassNames.insert(name.toLatin1(), true);
1169 _knownQObjectClassNames.insert(name.toLatin1(), true);
1077 }
1170 }
1078 }
1171 }
1079
1172
1080 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1173 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1081 {
1174 {
1082 _signalReceivers.remove(obj);
1175 _signalReceivers.remove(obj);
1083 }
1176 }
1084
1177
1085 bool PythonQt::handleError()
1178 bool PythonQt::handleError()
1086 {
1179 {
1087 bool flag = false;
1180 bool flag = false;
1088 if (PyErr_Occurred()) {
1181 if (PyErr_Occurred()) {
1089
1182
1090 // currently we just print the error and the stderr handler parses the errors
1183 // currently we just print the error and the stderr handler parses the errors
1091 PyErr_Print();
1184 PyErr_Print();
1092
1185
1093 /*
1186 /*
1094 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1187 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1095 PyObject *ptype;
1188 PyObject *ptype;
1096 PyObject *pvalue;
1189 PyObject *pvalue;
1097 PyObject *ptraceback;
1190 PyObject *ptraceback;
1098 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1191 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1099
1192
1100 Py_XDECREF(ptype);
1193 Py_XDECREF(ptype);
1101 Py_XDECREF(pvalue);
1194 Py_XDECREF(pvalue);
1102 Py_XDECREF(ptraceback);
1195 Py_XDECREF(ptraceback);
1103 */
1196 */
1104 PyErr_Clear();
1197 PyErr_Clear();
1105 flag = true;
1198 flag = true;
1106 }
1199 }
1107 return flag;
1200 return flag;
1108 }
1201 }
1109
1202
1110 void PythonQt::addSysPath(const QString& path)
1203 void PythonQt::addSysPath(const QString& path)
1111 {
1204 {
1112 PythonQtObjectPtr sys;
1205 PythonQtObjectPtr sys;
1113 sys.setNewRef(PyImport_ImportModule("sys"));
1206 sys.setNewRef(PyImport_ImportModule("sys"));
1114 PythonQtObjectPtr obj = lookupObject(sys, "path");
1207 PythonQtObjectPtr obj = lookupObject(sys, "path");
1115 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1208 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1116 }
1209 }
1117
1210
1118 void PythonQt::overwriteSysPath(const QStringList& paths)
1211 void PythonQt::overwriteSysPath(const QStringList& paths)
1119 {
1212 {
1120 PythonQtObjectPtr sys;
1213 PythonQtObjectPtr sys;
1121 sys.setNewRef(PyImport_ImportModule("sys"));
1214 sys.setNewRef(PyImport_ImportModule("sys"));
1122 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1215 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1123 }
1216 }
1124
1217
1125 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1218 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1126 {
1219 {
1127 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1220 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1128 }
1221 }
1129
1222
1130 void PythonQt::stdOutRedirectCB(const QString& str)
1223 void PythonQt::stdOutRedirectCB(const QString& str)
1131 {
1224 {
1132 if (!PythonQt::self()) {
1225 if (!PythonQt::self()) {
1133 std::cout << str.toLatin1().data() << std::endl;
1226 std::cout << str.toLatin1().data() << std::endl;
1134 return;
1227 return;
1135 }
1228 }
1136 emit PythonQt::self()->pythonStdOut(str);
1229 emit PythonQt::self()->pythonStdOut(str);
1137 }
1230 }
1138
1231
1139 void PythonQt::stdErrRedirectCB(const QString& str)
1232 void PythonQt::stdErrRedirectCB(const QString& str)
1140 {
1233 {
1141 if (!PythonQt::self()) {
1234 if (!PythonQt::self()) {
1142 std::cerr << str.toLatin1().data() << std::endl;
1235 std::cerr << str.toLatin1().data() << std::endl;
1143 return;
1236 return;
1144 }
1237 }
1145 emit PythonQt::self()->pythonStdErr(str);
1238 emit PythonQt::self()->pythonStdErr(str);
1146 }
1239 }
1147
1240
1148 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1241 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1149 {
1242 {
1150 _p->_wrappedCB = cb;
1243 _p->_wrappedCB = cb;
1151 }
1244 }
1152
1245
1153 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1246 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1154 {
1247 {
1155 _p->_noLongerWrappedCB = cb;
1248 _p->_noLongerWrappedCB = cb;
1156 }
1249 }
1157
1250
1158 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1251 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1159 {
1252 {
1160 _p->_profilingCB = cb;
1253 _p->_profilingCB = cb;
1161 }
1254 }
1162
1255
1163
1256
1164 static PyMethodDef PythonQtMethods[] = {
1257 static PyMethodDef PythonQtMethods[] = {
1165 {NULL, NULL, 0, NULL}
1258 {NULL, NULL, 0, NULL}
1166 };
1259 };
1167
1260
1168 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1261 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1169 {
1262 {
1170 QByteArray name = "PythonQt";
1263 QByteArray name = "PythonQt";
1171 if (!pythonQtModuleName.isEmpty()) {
1264 if (!pythonQtModuleName.isEmpty()) {
1172 name = pythonQtModuleName;
1265 name = pythonQtModuleName;
1173 }
1266 }
1174 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1267 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1175 _p->_pythonQtModuleName = name;
1268 _p->_pythonQtModuleName = name;
1176
1269
1177 if (redirectStdOut) {
1270 if (redirectStdOut) {
1178 PythonQtObjectPtr sys;
1271 PythonQtObjectPtr sys;
1179 PythonQtObjectPtr out;
1272 PythonQtObjectPtr out;
1180 PythonQtObjectPtr err;
1273 PythonQtObjectPtr err;
1181 sys.setNewRef(PyImport_ImportModule("sys"));
1274 sys.setNewRef(PyImport_ImportModule("sys"));
1182 // create a redirection object for stdout and stderr
1275 // create a redirection object for stdout and stderr
1183 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1276 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1184 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1277 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1185 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1278 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1186 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1279 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1187 // replace the built in file objects with our own objects
1280 // replace the built in file objects with our own objects
1188 PyModule_AddObject(sys, "stdout", out);
1281 PyModule_AddObject(sys, "stdout", out);
1189 PyModule_AddObject(sys, "stderr", err);
1282 PyModule_AddObject(sys, "stderr", err);
1190 }
1283 }
1191 }
1284 }
1192
1285
1286 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1287 {
1288 QStringList tmp = name.split(".");
1289 QString methodName = tmp.takeLast();
1290 QString variableName = tmp.join(".");
1291 // TODO: the variableName may be a type name, this needs to be handled differently,
1292 // because it is not necessarily known in the module context
1293 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1294 if (variableObject.isNull()) {
1295 return "";
1296 }
1297
1298 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1299 }
1300
1301 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1302 {
1303 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1304 if (typeObject.isNull()) {
1305 return "";
1306 }
1307 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1308 }
1309
1310 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1311 {
1312 PythonQtObjectPtr methodObject;
1313 if (PyDict_Check(variableObject)) {
1314 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1315 } else {
1316 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1317 }
1318 if (methodObject.isNull()) {
1319 return "";
1320 }
1321
1322 QString type;
1323
1324 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1325 // the methodObject is not a method, but the name of a type/class. This means
1326 // a constructor is called. Return the context.
1327 type = context;
1328 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1329 QString className;
1330
1331 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1332 // the type name of wrapped instance is the class name
1333 className = variableObject->ob_type->tp_name;
1334 } else {
1335 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1336 if (classNameObject) {
1337 Q_ASSERT(PyString_Check(classNameObject));
1338 className = PyString_AsString(classNameObject);
1339 Py_DECREF(classNameObject);
1340 }
1341 }
1342
1343 if (!className.isEmpty()) {
1344 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1345 if (info) {
1346 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1347 if (slotInfo) {
1348 if (slotInfo->metaMethod()) {
1349 type = slotInfo->metaMethod()->typeName();
1350 if (!type.isEmpty()) {
1351 QChar c = type.at(type.length()-1);
1352 while (c == '*' || c == '&') {
1353 type.truncate(type.length()-1);
1354 if (!type.isEmpty()) {
1355 c = type.at(type.length()-1);
1356 } else {
1357 break;
1358 }
1359 }
1360 // split away template arguments
1361 type = type.split("<").first();
1362 // split away const
1363 type = type.split(" ").last().trimmed();
1364
1365 // if the type is a known class info, then create the full type name, i.e. include the
1366 // module name. For example, the slot may return a QDate, then this looks up the
1367 // name _PythonQt.QtCore.QDate.
1368 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1369 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1370 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1371 Q_ASSERT(PyString_Check(s));
1372 type = QString(PyString_AsString(s)) + "." + type;
1373 Py_DECREF(s);
1374 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1375 Q_ASSERT(PyString_Check(s));
1376 Py_DECREF(s);
1377 }
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384 return type;
1385 }
1386
1193 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1387 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1194 {
1388 {
1195 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1389 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1196 }
1390 }
1197
1391
1198
1392
1199 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1393 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1200 {
1394 {
1201 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1395 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1202 if (!info) {
1396 if (!info) {
1203 info = new PythonQtClassInfo();
1397 info = new PythonQtClassInfo();
1204 info->setupCPPObject(typeName);
1398 info->setupCPPObject(typeName);
1205 _knownClassInfos.insert(typeName, info);
1399 _knownClassInfos.insert(typeName, info);
1206 }
1400 }
1207 return info;
1401 return info;
1208 }
1402 }
1209
1403
1210 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1404 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1211 {
1405 {
1212 _p->addPolymorphicHandler(typeName, cb);
1406 _p->addPolymorphicHandler(typeName, cb);
1213 }
1407 }
1214
1408
1215 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1409 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1216 {
1410 {
1217 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1411 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1218 info->addPolymorphicHandler(cb);
1412 info->addPolymorphicHandler(cb);
1219 }
1413 }
1220
1414
1221 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1415 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1222 {
1416 {
1223 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1417 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1224 }
1418 }
1225
1419
1226 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1420 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1227 {
1421 {
1228 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1422 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1229 if (info) {
1423 if (info) {
1230 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1424 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1231 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1425 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1232 return true;
1426 return true;
1233 } else {
1427 } else {
1234 return false;
1428 return false;
1235 }
1429 }
1236 }
1430 }
1237
1431
1238 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1432 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1239 {
1433 {
1240 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1434 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1241 if (!info->pythonQtClassWrapper()) {
1435 if (!info->pythonQtClassWrapper()) {
1242 info->setTypeSlots(typeSlots);
1436 info->setTypeSlots(typeSlots);
1243 info->setupCPPObject(typeName);
1437 info->setupCPPObject(typeName);
1244 createPythonQtClassWrapper(info, package, module);
1438 createPythonQtClassWrapper(info, package, module);
1245 }
1439 }
1246 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1440 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1247 addParentClass(typeName, parentTypeName, 0);
1441 addParentClass(typeName, parentTypeName, 0);
1248 }
1442 }
1249 if (wrapperCreator) {
1443 if (wrapperCreator) {
1250 info->setDecoratorProvider(wrapperCreator);
1444 info->setDecoratorProvider(wrapperCreator);
1251 }
1445 }
1252 if (shell) {
1446 if (shell) {
1253 info->setShellSetInstanceWrapperCB(shell);
1447 info->setShellSetInstanceWrapperCB(shell);
1254 }
1448 }
1255 }
1449 }
1256
1450
1257 PyObject* PythonQtPrivate::packageByName(const char* name)
1451 PyObject* PythonQtPrivate::packageByName(const char* name)
1258 {
1452 {
1259 if (name==NULL || name[0]==0) {
1453 if (name==NULL || name[0]==0) {
1260 name = "private";
1454 name = "private";
1261 }
1455 }
1262 PyObject* v = _packages.value(name);
1456 PyObject* v = _packages.value(name);
1263 if (!v) {
1457 if (!v) {
1264 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1458 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1265 _packages.insert(name, v);
1459 _packages.insert(name, v);
1266 // AddObject steals the reference, so increment it!
1460 // AddObject steals the reference, so increment it!
1267 Py_INCREF(v);
1461 Py_INCREF(v);
1268 PyModule_AddObject(_pythonQtModule, name, v);
1462 PyModule_AddObject(_pythonQtModule, name, v);
1269 }
1463 }
1270 return v;
1464 return v;
1271 }
1465 }
1272
1466
1273 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1467 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1274 {
1468 {
1275 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1469 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1276 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1470 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1277 PythonQt::self()->handleError();
1471 PythonQt::self()->handleError();
1278 }
1472 }
1279
1473
1280 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1474 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1281 {
1475 {
1282 if (_p->_initFlags & ExternalHelp) {
1476 if (_p->_initFlags & ExternalHelp) {
1283 emit pythonHelpRequest(QByteArray(info->className()));
1477 emit pythonHelpRequest(QByteArray(info->className()));
1284 return Py_BuildValue("");
1478 return Py_BuildValue("");
1285 } else {
1479 } else {
1286 return PyString_FromString(info->help().toLatin1().data());
1480 return PyString_FromString(info->help().toLatin1().data());
1287 }
1481 }
1288 }
1482 }
1289
1483
1290 void PythonQt::clearNotFoundCachedMembers()
1484 void PythonQt::clearNotFoundCachedMembers()
1291 {
1485 {
1292 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1486 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1293 info->clearNotFoundCachedMembers();
1487 info->clearNotFoundCachedMembers();
1294 }
1488 }
1295 }
1489 }
1296
1490
1297 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1491 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1298 {
1492 {
1299 _p->_cppWrapperFactories.removeAll(factory);
1493 _p->_cppWrapperFactories.removeAll(factory);
1300 }
1494 }
1301
1495
1302 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1496 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1303 {
1497 {
1304 _p->_foreignWrapperFactories.removeAll(factory);
1498 _p->_foreignWrapperFactories.removeAll(factory);
1305 }
1499 }
1306
1500
1307 void PythonQtPrivate::removeWrapperPointer(void* obj)
1501 void PythonQtPrivate::removeWrapperPointer(void* obj)
1308 {
1502 {
1309 _wrappedObjects.remove(obj);
1503 _wrappedObjects.remove(obj);
1310 }
1504 }
1311
1505
1312 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1506 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1313 {
1507 {
1314 _wrappedObjects.insert(obj, wrapper);
1508 _wrappedObjects.insert(obj, wrapper);
1315 }
1509 }
1316
1510
1317 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1511 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1318 {
1512 {
1319 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1513 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1320 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1514 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1321 // this is a wrapper whose QObject was already removed due to destruction
1515 // this is a wrapper whose QObject was already removed due to destruction
1322 // so the obj pointer has to be a new QObject with the same address...
1516 // so the obj pointer has to be a new QObject with the same address...
1323 // we remove the old one and set the copy to NULL
1517 // we remove the old one and set the copy to NULL
1324 wrap->_objPointerCopy = NULL;
1518 wrap->_objPointerCopy = NULL;
1325 removeWrapperPointer(obj);
1519 removeWrapperPointer(obj);
1326 wrap = NULL;
1520 wrap = NULL;
1327 }
1521 }
1328 return wrap;
1522 return wrap;
1329 }
1523 }
1330
1524
1331 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1525 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1332 {
1526 {
1333 PythonQtObjectPtr result;
1527 PythonQtObjectPtr result;
1334 if (pycode) {
1528 if (pycode) {
1335 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1529 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1336 } else {
1530 } else {
1337 PythonQt::self()->handleError();
1531 PythonQt::self()->handleError();
1338 }
1532 }
1339 return result;
1533 return result;
1340 }
1534 }
1341
1535
1342 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1536 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1343 {
1537 {
1344 void* foreignObject = NULL;
1538 void* foreignObject = NULL;
1345 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1539 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1346 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1540 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1347 if (foreignObject) {
1541 if (foreignObject) {
1348 return foreignObject;
1542 return foreignObject;
1349 }
1543 }
1350 }
1544 }
1351 return NULL;
1545 return NULL;
1352 }
1546 }
1547
1548 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1549 {
1550 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1551 if (PyObject_HasAttrString(object, "__get__") &&
1552 !PyObject_HasAttrString(object, "__set__") &&
1553 !PyMethod_Check(object) &&
1554 !PyFunction_Check(object) &&
1555 !PyClass_Check(object)) {
1556 return true;
1557 }
1558 return false;
1559 }
1560
1561 QString PythonQtPrivate::getSignature(PyObject* object)
1562 {
1563 QString signature;
1564
1565 if (object) {
1566 PyMethodObject* method = NULL;
1567 PyFunctionObject* func = NULL;
1568
1569 bool decrefMethod = false;
1570
1571 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1572 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1573 decrefMethod = true;
1574 } else if (object->ob_type == &PyFunction_Type) {
1575 func = (PyFunctionObject*)object;
1576 } else if (object->ob_type == &PyMethod_Type) {
1577 method = (PyMethodObject*)object;
1578 }
1579 if (method) {
1580 if (PyFunction_Check(method->im_func)) {
1581 func = (PyFunctionObject*)method->im_func;
1582 } else if (isMethodDescriptor((PyObject*)method)) {
1583 QString docstr;
1584 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1585 if (doc) {
1586 docstr = PyString_AsString(doc);
1587 Py_DECREF(doc);
1588 }
1589
1590 PyObject* s = PyObject_GetAttrString(object, "__name__");
1591 if (s) {
1592 Q_ASSERT(PyString_Check(s));
1593 signature = PyString_AsString(s);
1594 if (docstr.startsWith(signature + "(")) {
1595 signature = docstr;
1596 } else {
1597 signature += "(...)";
1598 if (!docstr.isEmpty()) {
1599 signature += "\n\n" + docstr;
1600 }
1601 }
1602 Py_DECREF(s);
1603 }
1604 }
1605 }
1606
1607 if (func) {
1608 QString funcName;
1609 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1610 if (s) {
1611 Q_ASSERT(PyString_Check(s));
1612 funcName = PyString_AsString(s);
1613 Py_DECREF(s);
1614 }
1615 if (method && funcName == "__init__") {
1616 PyObject* s = PyObject_GetAttrString(object, "__name__");
1617 if (s) {
1618 Q_ASSERT(PyString_Check(s));
1619 funcName = PyString_AsString(s);
1620 Py_DECREF(s);
1621 }
1622 }
1623
1624 QStringList arguments;
1625 QStringList defaults;
1626 QString varargs;
1627 QString varkeywords;
1628 // NOTE: This implementation is based on function getargs() in inspect.py.
1629 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1630 // It can be implemented, but it may be rarely needed and not necessary.
1631 PyCodeObject* code = (PyCodeObject*)func->func_code;
1632 if (code->co_varnames) {
1633 int nargs = code->co_argcount;
1634 Q_ASSERT(PyTuple_Check(code->co_varnames));
1635 for (int i=0; i<nargs; i++) {
1636 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1637 Q_ASSERT(PyString_Check(name));
1638 arguments << PyString_AsString(name);
1639 }
1640 if (code->co_flags & CO_VARARGS) {
1641 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1642 Q_ASSERT(PyString_Check(s));
1643 varargs = PyString_AsString(s);
1644 nargs += 1;
1645 }
1646 if (code->co_flags & CO_VARKEYWORDS) {
1647 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1648 Q_ASSERT(PyString_Check(s));
1649 varkeywords = PyString_AsString(s);
1650 }
1651 }
1652
1653 PyObject* defaultsTuple = func->func_defaults;
1654 if (defaultsTuple) {
1655 Q_ASSERT(PyTuple_Check(defaultsTuple));
1656 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1657 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1658 PyObject* s = PyObject_Repr(d);
1659 Q_ASSERT(PyString_Check(s));
1660 defaults << PyString_AsString(s);
1661 Py_DECREF(s);
1662 }
1663 }
1664
1665 int firstdefault = arguments.size() - defaults.size();
1666 for (int i=0; i<arguments.size(); i++) {
1667 if (!signature.isEmpty()) { signature += ", "; }
1668 if (!method || i>0 || arguments[i] != "self") {
1669 signature += arguments[i];
1670 if (i >= firstdefault) {
1671 signature += "=" + defaults[i-firstdefault];
1672 }
1673 }
1674 }
1675 if (!varargs.isEmpty()) {
1676 if (!signature.isEmpty()) { signature += ", "; }
1677 signature += "*" + varargs;
1678 }
1679 if (!varkeywords.isEmpty()) {
1680 if (!signature.isEmpty()) { signature += ", "; }
1681 signature += "**" + varkeywords;
1682 }
1683 signature = funcName + "(" + signature + ")";
1684 }
1685
1686 if (method && decrefMethod) {
1687 Py_DECREF(method);
1688 }
1689 }
1690
1691 return signature;
1692 }
@@ -1,690 +1,711
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include "PythonQtStdIn.h"
50 #include "PythonQtStdIn.h"
51 #include <QObject>
51 #include <QObject>
52 #include <QVariant>
52 #include <QVariant>
53 #include <QList>
53 #include <QList>
54 #include <QHash>
54 #include <QHash>
55 #include <QByteArray>
55 #include <QByteArray>
56 #include <QStringList>
56 #include <QStringList>
57 #include <QtDebug>
57 #include <QtDebug>
58 #include <iostream>
58 #include <iostream>
59
59
60
60
61 class PythonQtClassInfo;
61 class PythonQtClassInfo;
62 class PythonQtPrivate;
62 class PythonQtPrivate;
63 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
64 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
65 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
66 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
67 class PythonQtForeignWrapperFactory;
67 class PythonQtForeignWrapperFactory;
68 class PythonQtQFileImporter;
68 class PythonQtQFileImporter;
69
69
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
72 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
72 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
73
73
74 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
74 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
75
75
76 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
77 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
78 }
78 }
79
79
80 //! returns the offset that needs to be added to upcast an object of type T1 to T2
80 //! returns the offset that needs to be added to upcast an object of type T1 to T2
81 template<class T1, class T2> int PythonQtUpcastingOffset() {
81 template<class T1, class T2> int PythonQtUpcastingOffset() {
82 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
83 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
83 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
84 }
84 }
85
85
86 //! callback to create a QObject lazily
86 //! callback to create a QObject lazily
87 typedef QObject* PythonQtQObjectCreatorFunctionCB();
87 typedef QObject* PythonQtQObjectCreatorFunctionCB();
88
88
89 //! helper template to create a derived QObject class
89 //! helper template to create a derived QObject class
90 template<class T> QObject* PythonQtCreateObject() { return new T(); };
90 template<class T> QObject* PythonQtCreateObject() { return new T(); };
91
91
92 //! The main interface to the Python Qt binding, realized as a singleton
92 //! The main interface to the Python Qt binding, realized as a singleton
93 /*!
93 /*!
94 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
94 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
95 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
95 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
96 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
96 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
97 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
97 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
98 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
98 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
99 code in the scope of a dict.
99 code in the scope of a dict.
100 */
100 */
101 class PYTHONQT_EXPORT PythonQt : public QObject {
101 class PYTHONQT_EXPORT PythonQt : public QObject {
102
102
103 Q_OBJECT
103 Q_OBJECT
104
104
105 public:
105 public:
106
106
107 //! flags that can be passed to PythonQt::init()
107 //! flags that can be passed to PythonQt::init()
108 enum InitFlags {
108 enum InitFlags {
109 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
109 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
110 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
110 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
111 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
111 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
112 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
112 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
113 };
113 };
114
114
115 //! flags that tell PythonQt which operators to expect on the registered type
115 //! flags that tell PythonQt which operators to expect on the registered type
116 enum TypeSlots {
116 enum TypeSlots {
117 Type_Add = 1,
117 Type_Add = 1,
118 Type_Subtract = 1 << 1,
118 Type_Subtract = 1 << 1,
119 Type_Multiply = 1 << 2,
119 Type_Multiply = 1 << 2,
120 Type_Divide = 1 << 3,
120 Type_Divide = 1 << 3,
121 Type_Mod = 1 << 4,
121 Type_Mod = 1 << 4,
122 Type_And = 1 << 5,
122 Type_And = 1 << 5,
123 Type_Or = 1 << 6,
123 Type_Or = 1 << 6,
124 Type_Xor = 1 << 7,
124 Type_Xor = 1 << 7,
125 Type_LShift = 1 << 8,
125 Type_LShift = 1 << 8,
126 Type_RShift = 1 << 9,
126 Type_RShift = 1 << 9,
127
127
128 Type_InplaceAdd = 1 << 10,
128 Type_InplaceAdd = 1 << 10,
129 Type_InplaceSubtract = 1 << 11,
129 Type_InplaceSubtract = 1 << 11,
130 Type_InplaceMultiply = 1 << 12,
130 Type_InplaceMultiply = 1 << 12,
131 Type_InplaceDivide = 1 << 13,
131 Type_InplaceDivide = 1 << 13,
132 Type_InplaceMod = 1 << 14,
132 Type_InplaceMod = 1 << 14,
133 Type_InplaceAnd = 1 << 15,
133 Type_InplaceAnd = 1 << 15,
134 Type_InplaceOr = 1 << 16,
134 Type_InplaceOr = 1 << 16,
135 Type_InplaceXor = 1 << 17,
135 Type_InplaceXor = 1 << 17,
136 Type_InplaceLShift = 1 << 18,
136 Type_InplaceLShift = 1 << 18,
137 Type_InplaceRShift = 1 << 19,
137 Type_InplaceRShift = 1 << 19,
138
138
139 // Not yet needed/nicely mappable/generated...
139 // Not yet needed/nicely mappable/generated...
140 //Type_Positive = 1 << 29,
140 //Type_Positive = 1 << 29,
141 //Type_Negative = 1 << 29,
141 //Type_Negative = 1 << 29,
142 //Type_Abs = 1 << 29,
142 //Type_Abs = 1 << 29,
143 //Type_Hash = 1 << 29,
143 //Type_Hash = 1 << 29,
144
144
145 Type_Invert = 1 << 29,
145 Type_Invert = 1 << 29,
146 Type_RichCompare = 1 << 30,
146 Type_RichCompare = 1 << 30,
147 Type_NonZero = 1 << 31,
147 Type_NonZero = 1 << 31,
148
148
149 };
149 };
150
150
151 //! enum for profiling callback
151 //! enum for profiling callback
152 enum ProfilingCallbackState {
152 enum ProfilingCallbackState {
153 Enter = 1,
153 Enter = 1,
154 Leave = 2
154 Leave = 2
155 };
155 };
156
156
157 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
157 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
158 //! they are NULL.
158 //! they are NULL.
159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
160
160
161 //---------------------------------------------------------------------------
161 //---------------------------------------------------------------------------
162 //! \name Singleton Initialization
162 //! \name Singleton Initialization
163 //@{
163 //@{
164
164
165 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
165 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
166 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
166 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
167 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
167 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
169
169
170 //! cleanup of the singleton
170 //! cleanup of the singleton
171 static void cleanup();
171 static void cleanup();
172
172
173 //! get the singleton instance
173 //! get the singleton instance
174 static PythonQt* self();
174 static PythonQt* self();
175
175
176 //@}
176 //@}
177
177
178 //! defines the object types for introspection
178 //! defines the object types for introspection
179 enum ObjectType {
179 enum ObjectType {
180 Class,
180 Class,
181 Function,
181 Function,
182 Variable,
182 Variable,
183 Module,
183 Module,
184 Anything,
184 Anything,
185 CallOverloads
185 CallOverloads
186 };
186 };
187
187
188
188
189 //---------------------------------------------------------------------------
189 //---------------------------------------------------------------------------
190 //! \name Standard input handling
190 //! \name Standard input handling
191 //@{
191 //@{
192
192
193 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! Overwrite default handling of stdin using a custom callback. It internally backup
194 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
196
196
197 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
198 //! or 'sys.pythonqt_original_stdin'
198 //! or 'sys.pythonqt_original_stdin'
199 void setRedirectStdInCallbackEnabled(bool enabled);
199 void setRedirectStdInCallbackEnabled(bool enabled);
200
200
201 //@}
201 //@}
202
202
203 //---------------------------------------------------------------------------
203 //---------------------------------------------------------------------------
204 //! \name Modules
204 //! \name Modules
205 //@{
205 //@{
206
206
207 //! get the __main__ module of python
207 //! get the __main__ module of python
208 PythonQtObjectPtr getMainModule();
208 PythonQtObjectPtr getMainModule();
209
209
210 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
210 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
211 //! If a module is already imported, this returns the already imported module.
211 //! If a module is already imported, this returns the already imported module.
212 PythonQtObjectPtr importModule(const QString& name);
212 PythonQtObjectPtr importModule(const QString& name);
213
213
214 //! creates the new module \c name and evaluates the given file in the context of that module
214 //! creates the new module \c name and evaluates the given file in the context of that module
215 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
215 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
216 //! to a module later on.
216 //! to a module later on.
217 //! The user needs to make sure that the \c name is unique in the python module dictionary.
217 //! The user needs to make sure that the \c name is unique in the python module dictionary.
218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
219
219
220 //! creates the new module \c name and evaluates the given script in the context of that module.
220 //! creates the new module \c name and evaluates the given script in the context of that module.
221 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
221 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
222 //! to a module later on.
222 //! to a module later on.
223 //! The user needs to make sure that the \c name is unique in the python module dictionary.
223 //! The user needs to make sure that the \c name is unique in the python module dictionary.
224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
225
225
226 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
226 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
227 //! script code
227 //! script code
228 PythonQtObjectPtr createUniqueModule();
228 PythonQtObjectPtr createUniqueModule();
229
229
230 //@}
230 //@}
231
231
232 //---------------------------------------------------------------------------
232 //---------------------------------------------------------------------------
233 //! \name Importing/Paths
233 //! \name Importing/Paths
234 //@{
234 //@{
235
235
236 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
236 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
237 void overwriteSysPath(const QStringList& paths);
237 void overwriteSysPath(const QStringList& paths);
238
238
239 //! prepend a path to sys.path to allow importing from it
239 //! prepend a path to sys.path to allow importing from it
240 void addSysPath(const QString& path);
240 void addSysPath(const QString& path);
241
241
242 //! sets the __path__ list of a module to the given list (important for local imports)
242 //! sets the __path__ list of a module to the given list (important for local imports)
243 void setModuleImportPath(PyObject* module, const QStringList& paths);
243 void setModuleImportPath(PyObject* module, const QStringList& paths);
244
244
245 //@}
245 //@}
246
246
247 //---------------------------------------------------------------------------
247 //---------------------------------------------------------------------------
248 //! \name Registering Classes
248 //! \name Registering Classes
249 //@{
249 //@{
250
250
251 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
251 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
255
255
256 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
256 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
257 //! (ownership of wrapper is passed to PythonQt)
257 //! (ownership of wrapper is passed to PythonQt)
258 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
258 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
259
259
260 This will add a wrapper object that is used to make calls to the given classname \c typeName.
260 This will add a wrapper object that is used to make calls to the given classname \c typeName.
261 All slots that take a pointer to typeName as the first argument will be callable from Python on
261 All slots that take a pointer to typeName as the first argument will be callable from Python on
262 a variant object that contains such a type.
262 a variant object that contains such a type.
263 */
263 */
264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
265
265
266 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
266 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
267 //! and it will register the classes when it first sees a pointer to such a derived class
267 //! and it will register the classes when it first sees a pointer to such a derived class
268 void registerQObjectClassNames(const QStringList& names);
268 void registerQObjectClassNames(const QStringList& names);
269
269
270 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
270 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
271 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
271 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
272 //! type is really derived from parentType.
272 //! type is really derived from parentType.
273 //! Returns false if the typeName was not yet registered.
273 //! Returns false if the typeName was not yet registered.
274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
275
275
276 //! add a handler for polymorphic downcasting
276 //! add a handler for polymorphic downcasting
277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
278
278
279 //@}
279 //@}
280
280
281 //---------------------------------------------------------------------------
281 //---------------------------------------------------------------------------
282 //! \name Script Parsing and Evaluation
282 //! \name Script Parsing and Evaluation
283 //@{
283 //@{
284
284
285 //! parses the given file and returns the python code object, this can then be used to call evalCode()
285 //! parses the given file and returns the python code object, this can then be used to call evalCode()
286 PythonQtObjectPtr parseFile(const QString& filename);
286 PythonQtObjectPtr parseFile(const QString& filename);
287
287
288 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
288 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
289 //! If pycode is NULL, a python error is printed.
289 //! If pycode is NULL, a python error is printed.
290 QVariant evalCode(PyObject* object, PyObject* pycode);
290 QVariant evalCode(PyObject* object, PyObject* pycode);
291
291
292 //! evaluates the given script code and returns the result value
292 //! evaluates the given script code and returns the result value
293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
294
294
295 //! evaluates the given script code from file
295 //! evaluates the given script code from file
296 void evalFile(PyObject* object, const QString& filename);
296 void evalFile(PyObject* object, const QString& filename);
297
297
298 //@}
298 //@}
299
299
300 //---------------------------------------------------------------------------
300 //---------------------------------------------------------------------------
301 //! \name Signal Handlers
301 //! \name Signal Handlers
302 //@{
302 //@{
303
303
304 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
304 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
306
306
307 //! remove a signal handler from the given \c signal of \c obj
307 //! remove a signal handler from the given \c signal of \c obj
308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
309
309
310 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
310 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
312
312
313 //! remove a signal handler from the given \c signal of \c obj
313 //! remove a signal handler from the given \c signal of \c obj
314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
315
315
316 //@}
316 //@}
317
317
318 //---------------------------------------------------------------------------
318 //---------------------------------------------------------------------------
319 //! \name Variable access
319 //! \name Variable access
320 //@{
320 //@{
321
321
322 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
322 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
323 void addObject(PyObject* object, const QString& name, QObject* qObject);
323 void addObject(PyObject* object, const QString& name, QObject* qObject);
324
324
325 //! add the given variable to the object
325 //! add the given variable to the object
326 void addVariable(PyObject* object, const QString& name, const QVariant& v);
326 void addVariable(PyObject* object, const QString& name, const QVariant& v);
327
327
328 //! remove the given variable
328 //! remove the given variable
329 void removeVariable(PyObject* module, const QString& name);
329 void removeVariable(PyObject* module, const QString& name);
330
330
331 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
331 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
332 QVariant getVariable(PyObject* object, const QString& name);
332 QVariant getVariable(PyObject* object, const QString& name);
333
333
334 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
334 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
336 //! read vars etc. in scope of the given \c object
337 QStringList introspectObject(PyObject* object, ObjectType type);
338 //! read vars etc. in scope of the type object called \c typename. First the typename
339 //! of the form module.type is split into module and type. Then the module is looked up
340 //! in sys.modules. If the module or type is not found there, then the type is looked up in
341 //! the __builtin__ module.
342 QStringList introspectType(const QString& typeName, ObjectType type);
336
343
337 //! returns the found callable object or NULL
344 //! returns the found callable object or NULL
338 //! @return new reference
345 //! @return new reference
339 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
340
347
348 //! returns the return type of the method of a wrapped c++ object referenced by \c objectname
349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
350 //! returns the return type of the method \c methodName of a wrapped c++ type referenced by \c typeName
351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
341 //@}
352 //@}
342
353
343 //---------------------------------------------------------------------------
354 //---------------------------------------------------------------------------
344 //! \name Calling Python Objects
355 //! \name Calling Python Objects
345 //@{
356 //@{
346
357
347 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
358 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
348 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
349
360
350 //! call the given python object, returns the result converted to a QVariant
361 //! call the given python object, returns the result converted to a QVariant
351 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
352
363
353 //! call the given python object, returns the result as new PyObject
364 //! call the given python object, returns the result as new PyObject
354 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
355
366
356 //@}
367 //@}
357
368
358 //---------------------------------------------------------------------------
369 //---------------------------------------------------------------------------
359 //! \name Decorations, Constructors, Wrappers...
370 //! \name Decorations, Constructors, Wrappers...
360 //@{
371 //@{
361
372
362 //! add an object whose slots will be used as decorator slots for
373 //! add an object whose slots will be used as decorator slots for
363 //! other QObjects or CPP classes. The slots need to follow the
374 //! other QObjects or CPP classes. The slots need to follow the
364 //! convention that the first argument is a pointer to the wrapped object.
375 //! convention that the first argument is a pointer to the wrapped object.
365 //! (ownership is passed to PythonQt)
376 //! (ownership is passed to PythonQt)
366 /*!
377 /*!
367 Example:
378 Example:
368
379
369 A slot with the signature
380 A slot with the signature
370
381
371 \code
382 \code
372 bool doSomething(QWidget* w, int a)
383 bool doSomething(QWidget* w, int a)
373 \endcode
384 \endcode
374
385
375 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
386 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
376 that will be called with the concrete instance as first argument.
387 that will be called with the concrete instance as first argument.
377 So in Python you can now e.g. call
388 So in Python you can now e.g. call
378
389
379 \code
390 \code
380 someWidget.doSomething(12)
391 someWidget.doSomething(12)
381 \endcode
392 \endcode
382
393
383 without QWidget really having this method. This allows to easily make normal methods
394 without QWidget really having this method. This allows to easily make normal methods
384 of Qt classes callable by forwarding them with such decorator slots
395 of Qt classes callable by forwarding them with such decorator slots
385 or to make CPP classes (which are not derived from QObject) callable from Python.
396 or to make CPP classes (which are not derived from QObject) callable from Python.
386 */
397 */
387 void addInstanceDecorators(QObject* o);
398 void addInstanceDecorators(QObject* o);
388
399
389 //! add an object whose slots will be used as decorator slots for
400 //! add an object whose slots will be used as decorator slots for
390 //! class objects (ownership is passed to PythonQt)
401 //! class objects (ownership is passed to PythonQt)
391 /*!
402 /*!
392 The slots need to follow the following convention:
403 The slots need to follow the following convention:
393 - SomeClass* new_SomeClass(...)
404 - SomeClass* new_SomeClass(...)
394 - QVariant new_SomeClass(...)
405 - QVariant new_SomeClass(...)
395 - void delete_SomeClass(SomeClass*)
406 - void delete_SomeClass(SomeClass*)
396 - ... static_SomeClass_someName(...)
407 - ... static_SomeClass_someName(...)
397
408
398 This will add:
409 This will add:
399 - a constructor
410 - a constructor
400 - a constructor which generates a QVariant
411 - a constructor which generates a QVariant
401 - a destructor (only useful for CPP objects)
412 - a destructor (only useful for CPP objects)
402 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
413 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
403
414
404 */
415 */
405 void addClassDecorators(QObject* o);
416 void addClassDecorators(QObject* o);
406
417
407 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
418 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
408 void addDecorators(QObject* o);
419 void addDecorators(QObject* o);
409
420
410 //! add the given factory to PythonQt (ownership stays with caller)
421 //! add the given factory to PythonQt (ownership stays with caller)
411 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
422 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
412
423
413 //! add the given factory to PythonQt (ownership stays with caller)
424 //! add the given factory to PythonQt (ownership stays with caller)
414 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
415
426
416 //! remove the wrapper factory
427 //! remove the wrapper factory
417 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
418
429
419 //! remove the wrapper factory
430 //! remove the wrapper factory
420 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
421
432
422 //@}
433 //@}
423
434
424 //---------------------------------------------------------------------------
435 //---------------------------------------------------------------------------
425 //! \name Custom Importer
436 //! \name Custom Importer
426 //@{
437 //@{
427
438
428 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
439 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
429 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
440 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
430 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
441 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
431 //! This is not reversible, so even setting setImporter(NULL) afterwards will
442 //! This is not reversible, so even setting setImporter(NULL) afterwards will
432 //! keep the custom PythonQt importer with a QFile default import interface.
443 //! keep the custom PythonQt importer with a QFile default import interface.
433 //! Subsequent python import calls will make use of the passed importInterface
444 //! Subsequent python import calls will make use of the passed importInterface
434 //! which forwards all import calls to the given \c importInterface.
445 //! which forwards all import calls to the given \c importInterface.
435 //! Passing NULL will install a default QFile importer.
446 //! Passing NULL will install a default QFile importer.
436 //! (\c importInterface ownership stays with caller)
447 //! (\c importInterface ownership stays with caller)
437 void setImporter(PythonQtImportFileInterface* importInterface);
448 void setImporter(PythonQtImportFileInterface* importInterface);
438
449
439 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
450 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
440 //! (without calling setImporter or installDefaultImporter at least once, the default python import
451 //! (without calling setImporter or installDefaultImporter at least once, the default python import
441 //! mechanism is in place)
452 //! mechanism is in place)
442 //! the default importer allows to import files from anywhere QFile can read from,
453 //! the default importer allows to import files from anywhere QFile can read from,
443 //! including the Qt resource system using ":". Keep in mind that you need to extend
454 //! including the Qt resource system using ":". Keep in mind that you need to extend
444 //! "sys.path" with ":" to be able to import from the Qt resources.
455 //! "sys.path" with ":" to be able to import from the Qt resources.
445 void installDefaultImporter() { setImporter(NULL); }
456 void installDefaultImporter() { setImporter(NULL); }
446
457
447 //! set paths that the importer should ignore
458 //! set paths that the importer should ignore
448 void setImporterIgnorePaths(const QStringList& paths);
459 void setImporterIgnorePaths(const QStringList& paths);
449
460
450 //! get paths that the importer should ignore
461 //! get paths that the importer should ignore
451 const QStringList& getImporterIgnorePaths();
462 const QStringList& getImporterIgnorePaths();
452
463
453 //! get access to the file importer (if set)
464 //! get access to the file importer (if set)
454 static PythonQtImportFileInterface* importInterface();
465 static PythonQtImportFileInterface* importInterface();
455
466
456 //@}
467 //@}
457
468
458 //---------------------------------------------------------------------------
469 //---------------------------------------------------------------------------
459 //! \name Other Stuff
470 //! \name Other Stuff
460 //@{
471 //@{
461
472
462 //! get access to internal data (should not be used on the public API, but is used by some C functions)
473 //! get access to internal data (should not be used on the public API, but is used by some C functions)
463 static PythonQtPrivate* priv() { return _self->_p; }
474 static PythonQtPrivate* priv() { return _self->_p; }
464
475
465 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
476 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
466 //! The error is currently just output to the python stderr, future version might implement better trace printing
477 //! The error is currently just output to the python stderr, future version might implement better trace printing
467 bool handleError();
478 bool handleError();
468
479
469 //! clear all NotFound entries on all class infos, to ensure that
480 //! clear all NotFound entries on all class infos, to ensure that
470 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
481 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
471 void clearNotFoundCachedMembers();
482 void clearNotFoundCachedMembers();
472
483
473 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
484 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
474 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
485 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
475 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
486 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
476 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
487 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
477
488
478 //! call the callback if it is set
489 //! call the callback if it is set
479 static void qObjectNoLongerWrappedCB(QObject* o);
490 static void qObjectNoLongerWrappedCB(QObject* o);
480
491
481 //! called by internal help methods
492 //! called by internal help methods
482 PyObject* helpCalled(PythonQtClassInfo* info);
493 PyObject* helpCalled(PythonQtClassInfo* info);
483
494
484 //! returns the found object or NULL
495 //! returns the found object or NULL
485 //! @return new reference
496 //! @return new reference
486 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
497 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
487
498
488 //! sets a callback that is called before and after function calls for profiling
499 //! sets a callback that is called before and after function calls for profiling
489 void setProfilingCallback(ProfilingCB* cb);
500 void setProfilingCallback(ProfilingCB* cb);
490
501
491 //@}
502 //@}
492
503
493 signals:
504 signals:
494 //! emitted when python outputs something to stdout (and redirection is turned on)
505 //! emitted when python outputs something to stdout (and redirection is turned on)
495 void pythonStdOut(const QString& str);
506 void pythonStdOut(const QString& str);
496 //! emitted when python outputs something to stderr (and redirection is turned on)
507 //! emitted when python outputs something to stderr (and redirection is turned on)
497 void pythonStdErr(const QString& str);
508 void pythonStdErr(const QString& str);
498
509
499 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
510 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
500 void pythonHelpRequest(const QByteArray& cppClassName);
511 void pythonHelpRequest(const QByteArray& cppClassName);
501
512
502 private:
513 private:
503 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
514 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
504
515
516 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
517
518 PyObject* getObjectByType(const QString& typeName);
519
505 //! callback for stdout redirection, emits pythonStdOut signal
520 //! callback for stdout redirection, emits pythonStdOut signal
506 static void stdOutRedirectCB(const QString& str);
521 static void stdOutRedirectCB(const QString& str);
507 //! callback for stderr redirection, emits pythonStdErr signal
522 //! callback for stderr redirection, emits pythonStdErr signal
508 static void stdErrRedirectCB(const QString& str);
523 static void stdErrRedirectCB(const QString& str);
509
524
510 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
525 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
511 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
526 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
512
527
513 PythonQt(int flags, const QByteArray& pythonQtModuleName);
528 PythonQt(int flags, const QByteArray& pythonQtModuleName);
514 ~PythonQt();
529 ~PythonQt();
515
530
516 static PythonQt* _self;
531 static PythonQt* _self;
517 static int _uniqueModuleCount;
532 static int _uniqueModuleCount;
518
533
519 PythonQtPrivate* _p;
534 PythonQtPrivate* _p;
520
535
521 };
536 };
522
537
523 //! internal PythonQt details
538 //! internal PythonQt details
524 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
539 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
525
540
526 Q_OBJECT
541 Q_OBJECT
527
542
528 public:
543 public:
529 PythonQtPrivate();
544 PythonQtPrivate();
530 ~PythonQtPrivate();
545 ~PythonQtPrivate();
531
546
532 enum DecoratorTypes {
547 enum DecoratorTypes {
533 StaticDecorator = 1,
548 StaticDecorator = 1,
534 ConstructorDecorator = 2,
549 ConstructorDecorator = 2,
535 DestructorDecorator = 4,
550 DestructorDecorator = 4,
536 InstanceDecorator = 8,
551 InstanceDecorator = 8,
537 AllDecorators = 0xffff
552 AllDecorators = 0xffff
538 };
553 };
539
554
540 //! get the suffixes that are used for shared libraries
555 //! get the suffixes that are used for shared libraries
541 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
556 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
542
557
543 //! returns if the id is the id for PythonQtObjectPtr
558 //! returns if the id is the id for PythonQtObjectPtr
544 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
559 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
545
560
546 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
561 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
547 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
562 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
548 //! remove the wrapper ptr again
563 //! remove the wrapper ptr again
549 void removeWrapperPointer(void* obj);
564 void removeWrapperPointer(void* obj);
550
565
551 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
566 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
552 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
567 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
553
568
554 //! add parent class relation
569 //! add parent class relation
555 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
570 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
556
571
557 //! add a handler for polymorphic downcasting
572 //! add a handler for polymorphic downcasting
558 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
573 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
559
574
560 //! lookup existing classinfo and return new if not yet present
575 //! lookup existing classinfo and return new if not yet present
561 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
576 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
562
577
563 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
578 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
564 void removeSignalEmitter(QObject* obj);
579 void removeSignalEmitter(QObject* obj);
565
580
566 //! wrap the given QObject into a Python object (or return existing wrapper!)
581 //! wrap the given QObject into a Python object (or return existing wrapper!)
567 PyObject* wrapQObject(QObject* obj);
582 PyObject* wrapQObject(QObject* obj);
568
583
569 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
584 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
570 PyObject* wrapPtr(void* ptr, const QByteArray& name);
585 PyObject* wrapPtr(void* ptr, const QByteArray& name);
571
586
572 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
587 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
573 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
588 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
574 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
589 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
575 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
590 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
576
591
577 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
592 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
578 //! (ownership of wrapper is passed to PythonQt)
593 //! (ownership of wrapper is passed to PythonQt)
579 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
594 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
580
595
581 This will add a wrapper object that is used to make calls to the given classname \c typeName.
596 This will add a wrapper object that is used to make calls to the given classname \c typeName.
582 All slots that take a pointer to typeName as the first argument will be callable from Python on
597 All slots that take a pointer to typeName as the first argument will be callable from Python on
583 a variant object that contains such a type.
598 a variant object that contains such a type.
584 */
599 */
585 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
600 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
586
601
587 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
602 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
588 //! and it will register the classes when it first sees a pointer to such a derived class
603 //! and it will register the classes when it first sees a pointer to such a derived class
589 void registerQObjectClassNames(const QStringList& names);
604 void registerQObjectClassNames(const QStringList& names);
590
605
591 //! add a decorator object
606 //! add a decorator object
592 void addDecorators(QObject* o, int decoTypes);
607 void addDecorators(QObject* o, int decoTypes);
593
608
594 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
609 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
595 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
610 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
596
611
597 //! create a new instance of the given enum type with given value (returns a new reference)
612 //! create a new instance of the given enum type with given value (returns a new reference)
598 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
613 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
599
614
600 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
615 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
601 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
616 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
602
617
603 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
618 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
604 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
619 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
605
620
606 //! get the class info for a meta object (if available)
621 //! get the class info for a meta object (if available)
607 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
622 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
608
623
609 //! get the class info for a meta object (if available)
624 //! get the class info for a meta object (if available)
610 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
625 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
611
626
612 //! creates the new module from the given pycode
627 //! creates the new module from the given pycode
613 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
628 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
614
629
615 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
630 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
616 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
631 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
617
632
618 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
633 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
619 static PyObject* dummyTuple();
634 static PyObject* dummyTuple();
620
635
621 //! called by virtual overloads when a python return value can not be converted to the required Qt type
636 //! called by virtual overloads when a python return value can not be converted to the required Qt type
622 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
637 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
623
638
624 //! get access to the PythonQt module
639 //! get access to the PythonQt module
625 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
640 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
626
641
627 //! returns the profiling callback, which may be NULL
642 //! returns the profiling callback, which may be NULL
628 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
643 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
629
644
645 //! determines the signature of the given callable object (similar as pydoc)
646 QString getSignature(PyObject* object);
647
648 //! returns true if the object is a method descriptor (same as inspect.ismethoddescriptor() in inspect.py)
649 bool isMethodDescriptor(PyObject* object) const;
650
630 private:
651 private:
631 //! Setup the shared library suffixes by getting them from the "imp" module.
652 //! Setup the shared library suffixes by getting them from the "imp" module.
632 void setupSharedLibrarySuffixes();
653 void setupSharedLibrarySuffixes();
633
654
634 //! create a new pythonqt class wrapper and place it in the pythonqt module
655 //! create a new pythonqt class wrapper and place it in the pythonqt module
635 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
656 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
636
657
637 //! get/create new package module (the returned object is a borrowed reference)
658 //! get/create new package module (the returned object is a borrowed reference)
638 PyObject* packageByName(const char* name);
659 PyObject* packageByName(const char* name);
639
660
640 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
661 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
641 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
662 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
642
663
643 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
664 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
644 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
665 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
645
666
646 //! stores the meta info of known Qt classes
667 //! stores the meta info of known Qt classes
647 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
668 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
648
669
649 //! names of qobject derived classes that can be casted to qobject savely
670 //! names of qobject derived classes that can be casted to qobject savely
650 QHash<QByteArray, bool> _knownQObjectClassNames;
671 QHash<QByteArray, bool> _knownQObjectClassNames;
651
672
652 //! stores signal receivers for QObjects
673 //! stores signal receivers for QObjects
653 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
674 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
654
675
655 //! the PythonQt python module
676 //! the PythonQt python module
656 PythonQtObjectPtr _pythonQtModule;
677 PythonQtObjectPtr _pythonQtModule;
657
678
658 //! the name of the PythonQt python module
679 //! the name of the PythonQt python module
659 QByteArray _pythonQtModuleName;
680 QByteArray _pythonQtModuleName;
660
681
661 //! the importer interface (if set)
682 //! the importer interface (if set)
662 PythonQtImportFileInterface* _importInterface;
683 PythonQtImportFileInterface* _importInterface;
663
684
664 //! the default importer
685 //! the default importer
665 PythonQtQFileImporter* _defaultImporter;
686 PythonQtQFileImporter* _defaultImporter;
666
687
667 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
688 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
668 PythonQtQObjectWrappedCB* _wrappedCB;
689 PythonQtQObjectWrappedCB* _wrappedCB;
669
690
670 QStringList _importIgnorePaths;
691 QStringList _importIgnorePaths;
671 QStringList _sharedLibrarySuffixes;
692 QStringList _sharedLibrarySuffixes;
672
693
673 //! the cpp object wrapper factories
694 //! the cpp object wrapper factories
674 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
695 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
675
696
676 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
697 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
677
698
678 QHash<QByteArray, PyObject*> _packages;
699 QHash<QByteArray, PyObject*> _packages;
679
700
680 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
701 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
681
702
682 PythonQt::ProfilingCB* _profilingCB;
703 PythonQt::ProfilingCB* _profilingCB;
683
704
684 int _initFlags;
705 int _initFlags;
685 int _PythonQtObjectPtr_metaId;
706 int _PythonQtObjectPtr_metaId;
686
707
687 friend class PythonQt;
708 friend class PythonQt;
688 };
709 };
689
710
690 #endif
711 #endif
@@ -1,868 +1,894
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _typeSlots = 0;
60 _typeSlots = 0;
61 _isQObject = false;
61 _isQObject = false;
62 _enumsCreated = false;
62 _enumsCreated = false;
63 }
63 }
64
64
65 PythonQtClassInfo::~PythonQtClassInfo()
65 PythonQtClassInfo::~PythonQtClassInfo()
66 {
66 {
67 clearCachedMembers();
67 clearCachedMembers();
68
68
69 if (_constructors) {
69 if (_constructors) {
70 _constructors->deleteOverloadsAndThis();
70 _constructors->deleteOverloadsAndThis();
71 }
71 }
72 if (_destructor) {
72 if (_destructor) {
73 _destructor->deleteOverloadsAndThis();
73 _destructor->deleteOverloadsAndThis();
74 }
74 }
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
76 info->deleteOverloadsAndThis();
76 info->deleteOverloadsAndThis();
77 }
77 }
78 }
78 }
79
79
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
81 {
81 {
82 // _wrappedClassName is already set earlier in the class setup
82 // _wrappedClassName is already set earlier in the class setup
83 _isQObject = true;
83 _isQObject = true;
84 _meta = meta;
84 _meta = meta;
85 }
85 }
86
86
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
88 {
88 {
89 _isQObject = false;
89 _isQObject = false;
90 _wrappedClassName = classname;
90 _wrappedClassName = classname;
91 _metaTypeId = QMetaType::type(classname);
91 _metaTypeId = QMetaType::type(classname);
92 }
92 }
93
93
94 void PythonQtClassInfo::clearCachedMembers()
94 void PythonQtClassInfo::clearCachedMembers()
95 {
95 {
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
97 while (i.hasNext()) {
97 while (i.hasNext()) {
98 PythonQtMemberInfo member = i.next().value();
98 PythonQtMemberInfo member = i.next().value();
99 if (member._type== PythonQtMemberInfo::Slot) {
99 if (member._type== PythonQtMemberInfo::Slot || member._type== PythonQtMemberInfo::Signal) {
100 PythonQtSlotInfo* info = member._slot;
100 PythonQtSlotInfo* info = member._slot;
101 while (info) {
101 while (info) {
102 PythonQtSlotInfo* next = info->nextInfo();
102 PythonQtSlotInfo* next = info->nextInfo();
103 delete info;
103 delete info;
104 info = next;
104 info = next;
105 }
105 }
106 }
106 }
107 }
107 }
108 }
108 }
109
109
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
111 {
111 {
112 const char* sigEnd = sigStart;
112 const char* sigEnd = sigStart;
113 char c;
113 char c;
114 do {
114 do {
115 c = *sigEnd++;
115 c = *sigEnd++;
116 } while (c!=someChar && c!=0);
116 } while (c!=someChar && c!=0);
117 return sigEnd-sigStart-1;
117 return sigEnd-sigStart-1;
118 }
118 }
119
119
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
121 {
121 {
122 if (!_meta) return false;
122 if (!_meta) return false;
123
123
124 bool found = false;
124 bool found = false;
125 bool nameMapped = false;
125 bool nameMapped = false;
126 const char* attributeName = memberName;
126 const char* attributeName = memberName;
127 // look for properties
127 // look for properties
128 int i = _meta->indexOfProperty(attributeName);
128 int i = _meta->indexOfProperty(attributeName);
129 if (i==-1) {
129 if (i==-1) {
130 // try to map name to objectName
130 // try to map name to objectName
131 if (qstrcmp(attributeName, "name")==0) {
131 if (qstrcmp(attributeName, "name")==0) {
132 attributeName = "objectName";
132 attributeName = "objectName";
133 nameMapped = true;
133 nameMapped = true;
134 i = _meta->indexOfProperty(attributeName);
134 i = _meta->indexOfProperty(attributeName);
135 }
135 }
136 }
136 }
137 if (i!=-1) {
137 if (i!=-1) {
138 PythonQtMemberInfo newInfo(_meta->property(i));
138 PythonQtMemberInfo newInfo(_meta->property(i));
139 _cachedMembers.insert(attributeName, newInfo);
139 _cachedMembers.insert(attributeName, newInfo);
140 if (nameMapped) {
140 if (nameMapped) {
141 _cachedMembers.insert(memberName, newInfo);
141 _cachedMembers.insert(memberName, newInfo);
142 }
142 }
143 #ifdef PYTHONQT_DEBUG
143 #ifdef PYTHONQT_DEBUG
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
145 #endif
145 #endif
146 found = true;
146 found = true;
147 }
147 }
148 return found;
148 return found;
149 }
149 }
150
150
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
152 {
152 {
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
154 foreach(const ParentClassInfo& info, _parentClasses) {
154 foreach(const ParentClassInfo& info, _parentClasses) {
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
156 }
156 }
157 return inputInfo;
157 return inputInfo;
158 }
158 }
159
159
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
161 QObject* decoratorProvider = decorator();
161 QObject* decoratorProvider = decorator();
162 int memberNameLen = static_cast<int>(strlen(memberName));
162 int memberNameLen = static_cast<int>(strlen(memberName));
163 if (decoratorProvider) {
163 if (decoratorProvider) {
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
165 const QMetaObject* meta = decoratorProvider->metaObject();
165 const QMetaObject* meta = decoratorProvider->metaObject();
166 int numMethods = meta->methodCount();
166 int numMethods = meta->methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
168 for (int i = startFrom; i < numMethods; i++) {
168 for (int i = startFrom; i < numMethods; i++) {
169 QMetaMethod m = meta->method(i);
169 QMetaMethod m = meta->method(i);
170 if ((m.methodType() == QMetaMethod::Method ||
170 if ((m.methodType() == QMetaMethod::Method ||
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
172
172
173 const char* sigStart = m.signature();
173 const char* sigStart = m.signature();
174 bool isClassDeco = false;
174 bool isClassDeco = false;
175 if (qstrncmp(sigStart, "static_", 7)==0) {
175 if (qstrncmp(sigStart, "static_", 7)==0) {
176 // skip the static_classname_ part of the string
176 // skip the static_classname_ part of the string
177 sigStart += 7 + 1 + strlen(className());
177 sigStart += 7 + 1 + strlen(className());
178 isClassDeco = true;
178 isClassDeco = true;
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
180 isClassDeco = true;
180 isClassDeco = true;
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
182 isClassDeco = true;
182 isClassDeco = true;
183 }
183 }
184 // find the first '('
184 // find the first '('
185 int offset = findCharOffset(sigStart, '(');
185 int offset = findCharOffset(sigStart, '(');
186
186
187 // XXX no checking is currently done if the slots have correct first argument or not...
187 // XXX no checking is currently done if the slots have correct first argument or not...
188
188
189 // check if same length and same name
189 // check if same length and same name
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
191 found = true;
191 found = true;
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
193 info->setUpcastingOffset(upcastingOffset);
193 info->setUpcastingOffset(upcastingOffset);
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
195 if (tail) {
195 if (tail) {
196 tail->setNextInfo(info);
196 tail->setNextInfo(info);
197 } else {
197 } else {
198 PythonQtMemberInfo newInfo(info);
198 PythonQtMemberInfo newInfo(info);
199 memberCache.insert(memberName, newInfo);
199 memberCache.insert(memberName, newInfo);
200 }
200 }
201 tail = info;
201 tail = info;
202 }
202 }
203 }
203 }
204 }
204 }
205 }
205 }
206
206
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
208
208
209 return tail;
209 return tail;
210 }
210 }
211
211
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
213 {
213 {
214 bool found = false;
214 bool found = false;
215 int memberNameLen = static_cast<int>(strlen(memberName));
215 int memberNameLen = static_cast<int>(strlen(memberName));
216 PythonQtSlotInfo* tail = NULL;
216 PythonQtSlotInfo* tail = NULL;
217 if (_meta) {
217 if (_meta) {
218 int numMethods = _meta->methodCount();
218 int numMethods = _meta->methodCount();
219 for (int i = 0; i < numMethods; i++) {
219 for (int i = 0; i < numMethods; i++) {
220 QMetaMethod m = _meta->method(i);
220 QMetaMethod m = _meta->method(i);
221 if (((m.methodType() == QMetaMethod::Method ||
221 if (((m.methodType() == QMetaMethod::Method ||
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
223 || m.methodType()==QMetaMethod::Signal) {
223 || m.methodType()==QMetaMethod::Signal) {
224
224
225 const char* sigStart = m.signature();
225 const char* sigStart = m.signature();
226 // find the first '('
226 // find the first '('
227 int offset = findCharOffset(sigStart, '(');
227 int offset = findCharOffset(sigStart, '(');
228
228
229 // check if same length and same name
229 // check if same length and same name
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
231 found = true;
231 found = true;
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
233 if (tail) {
233 if (tail) {
234 tail->setNextInfo(info);
234 tail->setNextInfo(info);
235 } else {
235 } else {
236 PythonQtMemberInfo newInfo(info);
236 PythonQtMemberInfo newInfo(info);
237 _cachedMembers.insert(memberName, newInfo);
237 _cachedMembers.insert(memberName, newInfo);
238 }
238 }
239 tail = info;
239 tail = info;
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243 }
244
244
245 // look for dynamic decorators in this class and in derived classes
245 // look for dynamic decorators in this class and in derived classes
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
247
247
248 return found;
248 return found;
249 }
249 }
250
250
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
252 {
252 {
253 bool found = false;
253 bool found = false;
254 // look for enum values
254 // look for enum values
255 int enumCount = meta->enumeratorCount();
255 int enumCount = meta->enumeratorCount();
256 for (int i=0;i<enumCount; i++) {
256 for (int i=0;i<enumCount; i++) {
257 QMetaEnum e = meta->enumerator(i);
257 QMetaEnum e = meta->enumerator(i);
258 // we do not want flags, they will cause our values to appear two times
258 // we do not want flags, they will cause our values to appear two times
259 if (e.isFlag()) continue;
259 if (e.isFlag()) continue;
260
260
261 for (int j=0; j < e.keyCount(); j++) {
261 for (int j=0; j < e.keyCount(); j++) {
262 if (qstrcmp(e.key(j), memberName)==0) {
262 if (qstrcmp(e.key(j), memberName)==0) {
263 PyObject* enumType = findEnumWrapper(e.name());
263 PyObject* enumType = findEnumWrapper(e.name());
264 if (enumType) {
264 if (enumType) {
265 PythonQtObjectPtr enumValuePtr;
265 PythonQtObjectPtr enumValuePtr;
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
267 PythonQtMemberInfo newInfo(enumValuePtr);
267 PythonQtMemberInfo newInfo(enumValuePtr);
268 _cachedMembers.insert(memberName, newInfo);
268 _cachedMembers.insert(memberName, newInfo);
269 #ifdef PYTHONQT_DEBUG
269 #ifdef PYTHONQT_DEBUG
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
271 #endif
271 #endif
272 found = true;
272 found = true;
273 break;
273 break;
274 } else {
274 } else {
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
276 }
276 }
277 }
277 }
278 }
278 }
279 }
279 }
280 return found;
280 return found;
281 }
281 }
282
282
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
284 {
284 {
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
286 if (info._type != PythonQtMemberInfo::Invalid) {
286 if (info._type != PythonQtMemberInfo::Invalid) {
287 return info;
287 return info;
288 } else {
288 } else {
289 bool found = false;
289 bool found = false;
290
290
291 found = lookForPropertyAndCache(memberName);
291 found = lookForPropertyAndCache(memberName);
292 if (!found) {
292 if (!found) {
293 found = lookForMethodAndCache(memberName);
293 found = lookForMethodAndCache(memberName);
294 }
294 }
295 if (!found) {
295 if (!found) {
296 if (_meta) {
296 if (_meta) {
297 // check enums in our meta object directly
297 // check enums in our meta object directly
298 found = lookForEnumAndCache(_meta, memberName);
298 found = lookForEnumAndCache(_meta, memberName);
299 }
299 }
300 if (!found) {
300 if (!found) {
301 // check enums in the class hierachy of CPP classes
301 // check enums in the class hierachy of CPP classes
302 // look for dynamic decorators in this class and in derived classes
302 // look for dynamic decorators in this class and in derived classes
303 QList<QObject*> decoObjects;
303 QList<QObject*> decoObjects;
304 recursiveCollectDecoratorObjects(decoObjects);
304 recursiveCollectDecoratorObjects(decoObjects);
305 foreach(QObject* deco, decoObjects) {
305 foreach(QObject* deco, decoObjects) {
306 // call on ourself for caching, but with different metaObject():
306 // call on ourself for caching, but with different metaObject():
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
308 if (found) {
308 if (found) {
309 break;
309 break;
310 }
310 }
311 }
311 }
312 }
312 }
313 }
313 }
314 if (!found) {
314 if (!found) {
315 // maybe it is an enum wrapper?
315 // maybe it is an enum wrapper?
316 PyObject* p = findEnumWrapper(memberName);
316 PyObject* p = findEnumWrapper(memberName);
317 if (p) {
317 if (p) {
318 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._type = PythonQtMemberInfo::EnumWrapper;
319 info._enumWrapper = p;
319 info._enumWrapper = p;
320 _cachedMembers.insert(memberName, info);
320 _cachedMembers.insert(memberName, info);
321 found = true;
321 found = true;
322 }
322 }
323 }
323 }
324 if (!found) {
324 if (!found) {
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
327 QByteArray mbrName(memberName);
327 QByteArray mbrName(memberName);
328 if ((mbrName.length()>2) &&
328 if ((mbrName.length()>2) &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
330 (mbrName.at(mbrName.length()-2) != '_')) {
330 (mbrName.at(mbrName.length()-2) != '_')) {
331 mbrName = mbrName.mid(0,mbrName.length()-1);
331 mbrName = mbrName.mid(0,mbrName.length()-1);
332 found = lookForMethodAndCache(mbrName.constData());
332 found = lookForMethodAndCache(mbrName.constData());
333 if (found) {
333 if (found) {
334 return _cachedMembers.value(mbrName);
334 return _cachedMembers.value(mbrName);
335 }
335 }
336 }
336 }
337 }
337 }
338 if (!found) {
338 if (!found) {
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
340 info._type = PythonQtMemberInfo::NotFound;
340 info._type = PythonQtMemberInfo::NotFound;
341 _cachedMembers.insert(memberName, info);
341 _cachedMembers.insert(memberName, info);
342 }
342 }
343 }
343 }
344
344
345 return _cachedMembers.value(memberName);
345 return _cachedMembers.value(memberName);
346 }
346 }
347
347
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
349 QObject* deco = decorator();
349 QObject* deco = decorator();
350 if (deco) {
350 if (deco) {
351 decoratorObjects.append(deco);
351 decoratorObjects.append(deco);
352 }
352 }
353 foreach(const ParentClassInfo& info, _parentClasses) {
353 foreach(const ParentClassInfo& info, _parentClasses) {
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
355 }
355 }
356 }
356 }
357
357
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
359 classInfoObjects.append(this);
359 classInfoObjects.append(this);
360 foreach(const ParentClassInfo& info, _parentClasses) {
360 foreach(const ParentClassInfo& info, _parentClasses) {
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
362 }
362 }
363 }
363 }
364
364
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
366 {
366 {
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
368 while (it.hasNext()) {
368 while (it.hasNext()) {
369
369
370 PythonQtSlotInfo* infoOrig = it.next();
370 PythonQtSlotInfo* infoOrig = it.next();
371
371
372 const char* sigStart = infoOrig->metaMethod()->signature();
372 const char* sigStart = infoOrig->metaMethod()->signature();
373 if (qstrncmp("static_", sigStart, 7)==0) {
373 if (qstrncmp("static_", sigStart, 7)==0) {
374 sigStart += 7;
374 sigStart += 7;
375 sigStart += findCharOffset(sigStart, '_')+1;
375 sigStart += findCharOffset(sigStart, '_')+1;
376 }
376 }
377 int offset = findCharOffset(sigStart, '(');
377 int offset = findCharOffset(sigStart, '(');
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
379 //make a copy, otherwise we will have trouble on overloads!
379 //make a copy, otherwise we will have trouble on overloads!
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
381 info->setUpcastingOffset(upcastingOffset);
381 info->setUpcastingOffset(upcastingOffset);
382 found = true;
382 found = true;
383 if (tail) {
383 if (tail) {
384 tail->setNextInfo(info);
384 tail->setNextInfo(info);
385 } else {
385 } else {
386 PythonQtMemberInfo newInfo(info);
386 PythonQtMemberInfo newInfo(info);
387 memberCache.insert(memberName, newInfo);
387 memberCache.insert(memberName, newInfo);
388 }
388 }
389 tail = info;
389 tail = info;
390 }
390 }
391 }
391 }
392 return tail;
392 return tail;
393 }
393 }
394
394
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
396 QObject* decoratorProvider = decorator();
396 QObject* decoratorProvider = decorator();
397 if (decoratorProvider) {
397 if (decoratorProvider) {
398 const QMetaObject* meta = decoratorProvider->metaObject();
398 const QMetaObject* meta = decoratorProvider->metaObject();
399 int numMethods = meta->methodCount();
399 int numMethods = meta->methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
401 for (int i = startFrom; i < numMethods; i++) {
401 for (int i = startFrom; i < numMethods; i++) {
402 QMetaMethod m = meta->method(i);
402 QMetaMethod m = meta->method(i);
403 if ((m.methodType() == QMetaMethod::Method ||
403 if ((m.methodType() == QMetaMethod::Method ||
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
405
405
406 const char* sigStart = m.signature();
406 const char* sigStart = m.signature();
407 bool isClassDeco = false;
407 bool isClassDeco = false;
408 if (qstrncmp(sigStart, "static_", 7)==0) {
408 if (qstrncmp(sigStart, "static_", 7)==0) {
409 // skip the static_classname_ part of the string
409 // skip the static_classname_ part of the string
410 sigStart += 7 + 1 + strlen(className());
410 sigStart += 7 + 1 + strlen(className());
411 isClassDeco = true;
411 isClassDeco = true;
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
413 continue;
413 continue;
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
415 continue;
415 continue;
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
417 // hide everything that starts with py_
417 // hide everything that starts with py_
418 continue;
418 continue;
419 }
419 }
420 // find the first '('
420 // find the first '('
421 int offset = findCharOffset(sigStart, '(');
421 int offset = findCharOffset(sigStart, '(');
422
422
423 // XXX no checking is currently done if the slots have correct first argument or not...
423 // XXX no checking is currently done if the slots have correct first argument or not...
424 if (!metaOnly || isClassDeco) {
424 if (!metaOnly || isClassDeco) {
425 list << QString::fromLatin1(sigStart, offset);
425 list << QString::fromLatin1(sigStart, offset);
426 }
426 }
427 }
427 }
428 }
428 }
429 }
429 }
430
430
431 // look for global decorator slots
431 // look for global decorator slots
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
433 while (it.hasNext()) {
433 while (it.hasNext()) {
434 PythonQtSlotInfo* slot = it.next();
434 PythonQtSlotInfo* slot = it.next();
435 if (metaOnly) {
435 if (metaOnly) {
436 if (slot->isClassDecorator()) {
436 if (slot->isClassDecorator()) {
437 QByteArray first = slot->slotName();
437 QByteArray first = slot->slotName();
438 if (first.startsWith("static_")) {
438 if (first.startsWith("static_")) {
439 int idx = first.indexOf('_');
439 int idx = first.indexOf('_');
440 idx = first.indexOf('_', idx+1);
440 idx = first.indexOf('_', idx+1);
441 first = first.mid(idx+1);
441 first = first.mid(idx+1);
442 }
442 }
443 list << first;
443 list << first;
444 }
444 }
445 } else {
445 } else {
446 list << slot->slotName();
446 list << slot->slotName();
447 }
447 }
448 }
448 }
449 }
449 }
450
450
451 QStringList PythonQtClassInfo::propertyList()
451 QStringList PythonQtClassInfo::propertyList()
452 {
452 {
453 QStringList l;
453 QStringList l;
454 if (_isQObject && _meta) {
454 if (_isQObject && _meta) {
455 int i;
455 int i;
456 int numProperties = _meta->propertyCount();
456 int numProperties = _meta->propertyCount();
457 for (i = 0; i < numProperties; i++) {
457 for (i = 0; i < numProperties; i++) {
458 QMetaProperty p = _meta->property(i);
458 QMetaProperty p = _meta->property(i);
459 l << QString(p.name());
459 l << QString(p.name());
460 }
460 }
461 }
461 }
462 return l;
462 return l;
463 }
463 }
464
464
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
465 QStringList PythonQtClassInfo::memberList()
466 {
466 {
467 decorator();
467 decorator();
468
468
469 QStringList l;
469 QStringList l;
470 QString h;
470 QString h;
471 if (_isQObject && _meta && !metaOnly) {
472 l = propertyList();
473 }
474
475 // normal slots of QObject (or wrapper QObject)
471 // normal slots of QObject (or wrapper QObject)
476 if (!metaOnly && _meta) {
472 if (_meta) {
477 int numMethods = _meta->methodCount();
473 int numMethods = _meta->methodCount();
478 bool skipQObj = !_isQObject;
474 bool skipQObj = !_isQObject;
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
475 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
480 QMetaMethod m = _meta->method(i);
476 QMetaMethod m = _meta->method(i);
481 if (((m.methodType() == QMetaMethod::Method ||
477 if (((m.methodType() == QMetaMethod::Method ||
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
478 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
483 || m.methodType()==QMetaMethod::Signal) {
479 || m.methodType()==QMetaMethod::Signal) {
484 QByteArray signa(m.signature());
480 QByteArray signa(m.signature());
485 signa = signa.left(signa.indexOf('('));
481 signa = signa.left(signa.indexOf('('));
486 l << signa;
482 l << signa;
487 }
483 }
488 }
484 }
489 }
485 }
490
486
491 {
487 {
492 // look for dynamic decorators in this class and in derived classes
488 // look for dynamic decorators in this class and in derived classes
493 QList<PythonQtClassInfo*> infos;
489 QList<PythonQtClassInfo*> infos;
494 recursiveCollectClassInfos(infos);
490 recursiveCollectClassInfos(infos);
495 foreach(PythonQtClassInfo* info, infos) {
491 foreach(PythonQtClassInfo* info, infos) {
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
492 info->listDecoratorSlotsFromDecoratorProvider(l, false);
497 }
493 }
498 }
494 }
499
495
500 // List enumerator keys...
496 // List enumerator keys...
501 QList<const QMetaObject*> enumMetaObjects;
497 QList<const QMetaObject*> enumMetaObjects;
502 if (_meta) {
498 if (_meta) {
503 enumMetaObjects << _meta;
499 enumMetaObjects << _meta;
504 }
500 }
505 // check enums in the class hierachy of CPP classes
501 // check enums in the class hierachy of CPP classes
506 QList<QObject*> decoObjects;
502 QList<QObject*> decoObjects;
507 recursiveCollectDecoratorObjects(decoObjects);
503 recursiveCollectDecoratorObjects(decoObjects);
508 foreach(QObject* deco, decoObjects) {
504 foreach(QObject* deco, decoObjects) {
509 enumMetaObjects << deco->metaObject();
505 enumMetaObjects << deco->metaObject();
510 }
506 }
511
507
512 foreach(const QMetaObject* meta, enumMetaObjects) {
508 foreach(const QMetaObject* meta, enumMetaObjects) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
509 for (int i = 0; i<meta->enumeratorCount(); i++) {
514 QMetaEnum e = meta->enumerator(i);
510 QMetaEnum e = meta->enumerator(i);
515 l << e.name();
511 l << e.name();
516 // we do not want flags, they will cause our values to appear two times
512 // we do not want flags, they will cause our values to appear two times
517 if (e.isFlag()) continue;
513 if (e.isFlag()) continue;
518
514
519 for (int j=0; j < e.keyCount(); j++) {
515 for (int j=0; j < e.keyCount(); j++) {
520 l << QString(e.key(j));
516 l << QString(e.key(j));
521 }
517 }
522 }
518 }
523 }
519 }
524
520
525 return QSet<QString>::fromList(l).toList();
521 return QSet<QString>::fromList(l).toList();
526 }
522 }
527
523
528 const char* PythonQtClassInfo::className()
524 const char* PythonQtClassInfo::className()
529 {
525 {
530 return _wrappedClassName.constData();
526 return _wrappedClassName.constData();
531 }
527 }
532
528
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
529 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
534 {
530 {
535 if (ptr==NULL) {
531 if (ptr==NULL) {
536 return NULL;
532 return NULL;
537 }
533 }
538 if (_wrappedClassName == classname) {
534 if (_wrappedClassName == classname) {
539 return ptr;
535 return ptr;
540 }
536 }
541 foreach(const ParentClassInfo& info, _parentClasses) {
537 foreach(const ParentClassInfo& info, _parentClasses) {
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
538 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
543 if (result) {
539 if (result) {
544 return result;
540 return result;
545 }
541 }
546 }
542 }
547 return NULL;
543 return NULL;
548 }
544 }
549
545
550 bool PythonQtClassInfo::inherits(const char* name)
546 bool PythonQtClassInfo::inherits(const char* name)
551 {
547 {
552 if (_wrappedClassName == name) {
548 if (_wrappedClassName == name) {
553 return true;
549 return true;
554 }
550 }
555 foreach(const ParentClassInfo& info, _parentClasses) {
551 foreach(const ParentClassInfo& info, _parentClasses) {
556 if (info._parent->inherits(name)) {
552 if (info._parent->inherits(name)) {
557 return true;
553 return true;
558 }
554 }
559 }
555 }
560 return false;
556 return false;
561 }
557 }
562
558
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
559 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
564 {
560 {
565 if (classInfo == this) {
561 if (classInfo == this) {
566 return true;
562 return true;
567 }
563 }
568 foreach(const ParentClassInfo& info, _parentClasses) {
564 foreach(const ParentClassInfo& info, _parentClasses) {
569 if (info._parent->inherits(classInfo)) {
565 if (info._parent->inherits(classInfo)) {
570 return true;
566 return true;
571 }
567 }
572 }
568 }
573 return false;
569 return false;
574 }
570 }
575
571
576 QString PythonQtClassInfo::help()
572 QString PythonQtClassInfo::help()
577 {
573 {
578 decorator();
574 decorator();
579 QString h;
575 QString h;
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
576 h += QString("--- ") + QString(className()) + QString(" ---\n");
581
577
582 if (_isQObject) {
578 if (_isQObject) {
583 h += "Properties:\n";
579 h += "Properties:\n";
584
580
585 int i;
581 int i;
586 int numProperties = _meta->propertyCount();
582 int numProperties = _meta->propertyCount();
587 for (i = 0; i < numProperties; i++) {
583 for (i = 0; i < numProperties; i++) {
588 QMetaProperty p = _meta->property(i);
584 QMetaProperty p = _meta->property(i);
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
585 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
590 }
586 }
591 }
587 }
592
588
593 if (constructors()) {
589 if (constructors()) {
594 h += "Constructors:\n";
590 h += "Constructors:\n";
595 PythonQtSlotInfo* constr = constructors();
591 PythonQtSlotInfo* constr = constructors();
596 while (constr) {
592 while (constr) {
597 h += constr->fullSignature() + "\n";
593 h += constr->fullSignature() + "\n";
598 constr = constr->nextInfo();
594 constr = constr->nextInfo();
599 }
595 }
600 }
596 }
601
597
602 h += "Slots:\n";
598 h += "Slots:\n";
603 h += "QString help()\n";
599 h += "QString help()\n";
604 h += "QString className()\n";
600 h += "QString className()\n";
605
601
606 if (_meta) {
602 if (_meta) {
607 int numMethods = _meta->methodCount();
603 int numMethods = _meta->methodCount();
608 for (int i = 0; i < numMethods; i++) {
604 for (int i = 0; i < numMethods; i++) {
609 QMetaMethod m = _meta->method(i);
605 QMetaMethod m = _meta->method(i);
610 if ((m.methodType() == QMetaMethod::Method ||
606 if ((m.methodType() == QMetaMethod::Method ||
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
607 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
612 PythonQtSlotInfo slot(this, m, i);
608 PythonQtSlotInfo slot(this, m, i);
613 h += slot.fullSignature()+ "\n";
609 h += slot.fullSignature()+ "\n";
614 }
610 }
615 }
611 }
616 }
612 }
617
613
618 // TODO xxx : decorators and enums from decorator() are missing...
614 // TODO xxx : decorators and enums from decorator() are missing...
619 // maybe we can reuse memberlist()?
615 // maybe we can reuse memberlist()?
620
616
621 if (_meta && _meta->enumeratorCount()) {
617 if (_meta && _meta->enumeratorCount()) {
622 h += "Enums:\n";
618 h += "Enums:\n";
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
619 for (int i = 0; i<_meta->enumeratorCount(); i++) {
624 QMetaEnum e = _meta->enumerator(i);
620 QMetaEnum e = _meta->enumerator(i);
625 h += QString(e.name()) + " {";
621 h += QString(e.name()) + " {";
626 for (int j=0; j < e.keyCount(); j++) {
622 for (int j=0; j < e.keyCount(); j++) {
627 if (j) { h+= ", "; }
623 if (j) { h+= ", "; }
628 h += e.key(j);
624 h += e.key(j);
629 }
625 }
630 h += " }\n";
626 h += " }\n";
631 }
627 }
632 }
628 }
633
629
634 if (_isQObject && _meta) {
630 if (_isQObject && _meta) {
635 int numMethods = _meta->methodCount();
631 int numMethods = _meta->methodCount();
636 if (numMethods>0) {
632 if (numMethods>0) {
637 h += "Signals:\n";
633 h += "Signals:\n";
638 for (int i = 0; i < numMethods; i++) {
634 for (int i = 0; i < numMethods; i++) {
639 QMetaMethod m = _meta->method(i);
635 QMetaMethod m = _meta->method(i);
640 if (m.methodType() == QMetaMethod::Signal) {
636 if (m.methodType() == QMetaMethod::Signal) {
641 h += QString(m.signature()) + "\n";
637 h += QString(m.signature()) + "\n";
642 }
638 }
643 }
639 }
644 }
640 }
645 }
641 }
646 return h;
642 return h;
647 }
643 }
648
644
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
645 PythonQtSlotInfo* PythonQtClassInfo::constructors()
650 {
646 {
651 if (!_constructors) {
647 if (!_constructors) {
652 // force creation of lazy decorator, which will register the decorators
648 // force creation of lazy decorator, which will register the decorators
653 decorator();
649 decorator();
654 }
650 }
655 return _constructors;
651 return _constructors;
656 }
652 }
657
653
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
654 PythonQtSlotInfo* PythonQtClassInfo::destructor()
659 {
655 {
660 if (!_destructor) {
656 if (!_destructor) {
661 // force creation of lazy decorator, which will register the decorators
657 // force creation of lazy decorator, which will register the decorators
662 decorator();
658 decorator();
663 }
659 }
664 return _destructor;
660 return _destructor;
665 }
661 }
666
662
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
663 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
668 {
664 {
669 PythonQtSlotInfo* prev = constructors();
665 PythonQtSlotInfo* prev = constructors();
670 if (prev) {
666 if (prev) {
671 info->setNextInfo(prev->nextInfo());
667 info->setNextInfo(prev->nextInfo());
672 prev->setNextInfo(info);
668 prev->setNextInfo(info);
673 } else {
669 } else {
674 _constructors = info;
670 _constructors = info;
675 }
671 }
676 }
672 }
677
673
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
674 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
679 {
675 {
680 _decoratorSlots.append(info);
676 _decoratorSlots.append(info);
681 }
677 }
682
678
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
679 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
684 {
680 {
685 if (_destructor) {
681 if (_destructor) {
686 _destructor->deleteOverloadsAndThis();
682 _destructor->deleteOverloadsAndThis();
687 }
683 }
688 _destructor = info;
684 _destructor = info;
689 }
685 }
690
686
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
687 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
692 {
688 {
693 _meta = meta;
689 _meta = meta;
694 clearCachedMembers();
690 clearCachedMembers();
695 }
691 }
696
692
697 QObject* PythonQtClassInfo::decorator()
693 QObject* PythonQtClassInfo::decorator()
698 {
694 {
699 if (!_decoratorProvider && _decoratorProviderCB) {
695 if (!_decoratorProvider && _decoratorProviderCB) {
700 _decoratorProvider = (*_decoratorProviderCB)();
696 _decoratorProvider = (*_decoratorProviderCB)();
701 if (_decoratorProvider) {
697 if (_decoratorProvider) {
702 _decoratorProvider->setParent(PythonQt::priv());
698 _decoratorProvider->setParent(PythonQt::priv());
703 // setup enums early, since they might be needed by the constructor decorators:
699 // setup enums early, since they might be needed by the constructor decorators:
704 if (!_enumsCreated) {
700 if (!_enumsCreated) {
705 createEnumWrappers();
701 createEnumWrappers();
706 }
702 }
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
703 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
708 }
704 }
709 }
705 }
710 // check if enums need to be created and create them if they are not yet created
706 // check if enums need to be created and create them if they are not yet created
711 if (!_enumsCreated) {
707 if (!_enumsCreated) {
712 createEnumWrappers();
708 createEnumWrappers();
713 }
709 }
714 return _decoratorProvider;
710 return _decoratorProvider;
715 }
711 }
716
712
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
713 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
718 {
714 {
719 PythonQtMemberInfo info = member("py_hasOwner");
715 PythonQtMemberInfo info = member("py_hasOwner");
720 if (info._type == PythonQtMemberInfo::Slot) {
716 if (info._type == PythonQtMemberInfo::Slot) {
721 void* obj = object;
717 void* obj = object;
722 bool result = false;
718 bool result = false;
723 void* args[2];
719 void* args[2];
724 args[0] = &result;
720 args[0] = &result;
725 args[1] = &obj;
721 args[1] = &obj;
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
722 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
727 return !result;
723 return !result;
728 } else {
724 } else {
729 return false;
725 return false;
730 }
726 }
731 }
727 }
732
728
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
729 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
734 {
730 {
735 if (!_polymorphicHandlers.isEmpty()) {
731 if (!_polymorphicHandlers.isEmpty()) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
732 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
737 void* resultPtr = (*cb)(ptr, resultClassName);
733 void* resultPtr = (*cb)(ptr, resultClassName);
738 if (resultPtr) {
734 if (resultPtr) {
739 return resultPtr;
735 return resultPtr;
740 }
736 }
741 }
737 }
742 }
738 }
743 foreach(const ParentClassInfo& info, _parentClasses) {
739 foreach(const ParentClassInfo& info, _parentClasses) {
744 if (!info._parent->isQObject()) {
740 if (!info._parent->isQObject()) {
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
741 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
746 if (resultPtr) {
742 if (resultPtr) {
747 return resultPtr;
743 return resultPtr;
748 }
744 }
749 }
745 }
750 }
746 }
751 return NULL;
747 return NULL;
752 }
748 }
753
749
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
750 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
755 {
751 {
756 const char* className;
752 const char* className;
757 // this would do downcasting recursively...
753 // this would do downcasting recursively...
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
754 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
759
755
760 // we only do downcasting on the base object, not on the whole inheritance tree...
756 // we only do downcasting on the base object, not on the whole inheritance tree...
761 void* resultPtr = NULL;
757 void* resultPtr = NULL;
762 if (!_polymorphicHandlers.isEmpty()) {
758 if (!_polymorphicHandlers.isEmpty()) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
759 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
764 resultPtr = (*cb)(ptr, &className);
760 resultPtr = (*cb)(ptr, &className);
765 if (resultPtr) {
761 if (resultPtr) {
766 break;
762 break;
767 }
763 }
768 }
764 }
769 }
765 }
770 if (resultPtr) {
766 if (resultPtr) {
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
767 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
772 } else {
768 } else {
773 *resultClassInfo = this;
769 *resultClassInfo = this;
774 resultPtr = ptr;
770 resultPtr = ptr;
775 }
771 }
776 return resultPtr;
772 return resultPtr;
777 }
773 }
778
774
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
775 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
780 {
776 {
781 if (isLocalEnum) {
777 if (isLocalEnum) {
782 *isLocalEnum = true;
778 *isLocalEnum = true;
783 }
779 }
784 int scopePos = name.lastIndexOf("::");
780 int scopePos = name.lastIndexOf("::");
785 if (scopePos != -1) {
781 if (scopePos != -1) {
786 if (isLocalEnum) {
782 if (isLocalEnum) {
787 *isLocalEnum = false;
783 *isLocalEnum = false;
788 }
784 }
789 // split into scope and enum name
785 // split into scope and enum name
790 QByteArray enumScope = name.mid(0,scopePos);
786 QByteArray enumScope = name.mid(0,scopePos);
791 QByteArray enumName = name.mid(scopePos+2);
787 QByteArray enumName = name.mid(scopePos+2);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
788 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
793 if (info) {
789 if (info) {
794 return info->findEnumWrapper(enumName);
790 return info->findEnumWrapper(enumName);
795 } else{
791 } else{
796 return NULL;
792 return NULL;
797 }
793 }
798 }
794 }
799 if (localScope) {
795 if (localScope) {
800 return localScope->findEnumWrapper(name);
796 return localScope->findEnumWrapper(name);
801 } else {
797 } else {
802 return NULL;
798 return NULL;
803 }
799 }
804 }
800 }
805
801
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
802 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
807 {
803 {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
804 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
809 QMetaEnum e = meta->enumerator(i);
805 QMetaEnum e = meta->enumerator(i);
810 PythonQtObjectPtr p;
806 PythonQtObjectPtr p;
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
807 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
812 _enumWrappers.append(p);
808 _enumWrappers.append(p);
813 }
809 }
814 }
810 }
815
811
816 void PythonQtClassInfo::createEnumWrappers()
812 void PythonQtClassInfo::createEnumWrappers()
817 {
813 {
818 if (!_enumsCreated) {
814 if (!_enumsCreated) {
819 _enumsCreated = true;
815 _enumsCreated = true;
820 if (_meta) {
816 if (_meta) {
821 createEnumWrappers(_meta);
817 createEnumWrappers(_meta);
822 }
818 }
823 if (decorator()) {
819 if (decorator()) {
824 createEnumWrappers(decorator()->metaObject());
820 createEnumWrappers(decorator()->metaObject());
825 }
821 }
826 foreach(const ParentClassInfo& info, _parentClasses) {
822 foreach(const ParentClassInfo& info, _parentClasses) {
827 info._parent->createEnumWrappers();
823 info._parent->createEnumWrappers();
828 }
824 }
829 }
825 }
830 }
826 }
831
827
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
828 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
833 // force enum creation
829 // force enum creation
834 if (!_enumsCreated) {
830 if (!_enumsCreated) {
835 createEnumWrappers();
831 createEnumWrappers();
836 }
832 }
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
833 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
834 const char* className = ((PyTypeObject*)p.object())->tp_name;
839 if (qstrcmp(className, name)==0) {
835 if (qstrcmp(className, name)==0) {
840 return p.object();
836 return p.object();
841 }
837 }
842 }
838 }
843 foreach(const ParentClassInfo& info, _parentClasses) {
839 foreach(const ParentClassInfo& info, _parentClasses) {
844 PyObject* p = info._parent->findEnumWrapper(name);
840 PyObject* p = info._parent->findEnumWrapper(name);
845 if (p) return p;
841 if (p) return p;
846 }
842 }
847 return NULL;
843 return NULL;
848 }
844 }
849
845
850 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
846 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
851 {
847 {
852 _decoratorProviderCB = cb;
848 _decoratorProviderCB = cb;
853 _decoratorProvider = NULL;
849 _decoratorProvider = NULL;
854 _enumsCreated = false;
850 _enumsCreated = false;
855 }
851 }
856
852
857 void PythonQtClassInfo::clearNotFoundCachedMembers()
853 void PythonQtClassInfo::clearNotFoundCachedMembers()
858 {
854 {
859 // remove all not found entries, since a new decorator means new slots,
855 // remove all not found entries, since a new decorator means new slots,
860 // which might have been cached as "NotFound" already.
856 // which might have been cached as "NotFound" already.
861 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
857 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
862 while (it.hasNext()) {
858 while (it.hasNext()) {
863 it.next();
859 it.next();
864 if (it.value()._type == PythonQtMemberInfo::NotFound) {
860 if (it.value()._type == PythonQtMemberInfo::NotFound) {
865 it.remove();
861 it.remove();
866 }
862 }
867 }
863 }
868 }
864 }
865
866 //-------------------------------------------------------------------------
867
868 PythonQtMemberInfo::PythonQtMemberInfo( PythonQtSlotInfo* info )
869 {
870 if (info->metaMethod()->methodType() == QMetaMethod::Signal) {
871 _type = Signal;
872 } else {
873 _type = Slot;
874 }
875 _slot = info;
876 _enumValue = NULL;
877 }
878
879 PythonQtMemberInfo::PythonQtMemberInfo( const PythonQtObjectPtr& enumValue )
880 {
881 _type = EnumValue;
882 _slot = NULL;
883 _enumValue = enumValue;
884 _enumWrapper = NULL;
885 }
886
887 PythonQtMemberInfo::PythonQtMemberInfo( const QMetaProperty& prop )
888 {
889 _type = Property;
890 _slot = NULL;
891 _enumValue = NULL;
892 _property = prop;
893 _enumWrapper = NULL;
894 } No newline at end of file
@@ -1,265 +1,250
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, Signal, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
52 PythonQtMemberInfo(PythonQtSlotInfo* info);
53 _type = Slot;
54 _slot = info;
55 _enumValue = NULL;
56 }
57
53
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
54 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue);
59 _type = EnumValue;
60 _slot = NULL;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
63 }
64
55
65 PythonQtMemberInfo(const QMetaProperty& prop) {
56 PythonQtMemberInfo(const QMetaProperty& prop);
66 _type = Property;
67 _slot = NULL;
68 _enumValue = NULL;
69 _property = prop;
70 _enumWrapper = NULL;
71 }
72
57
73 Type _type;
58 Type _type;
74
59
75 // TODO: this could be a union...
60 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
61 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
62 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
63 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
64 QMetaProperty _property;
80 };
65 };
81
66
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
67 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 /*! for fast lookup of slots when calling the object from Python
68 /*! for fast lookup of slots when calling the object from Python
84 */
69 */
85 class PYTHONQT_EXPORT PythonQtClassInfo {
70 class PYTHONQT_EXPORT PythonQtClassInfo {
86
71
87 public:
72 public:
88 PythonQtClassInfo();
73 PythonQtClassInfo();
89 ~PythonQtClassInfo();
74 ~PythonQtClassInfo();
90
75
91 //! store information about parent classes
76 //! store information about parent classes
92 struct ParentClassInfo {
77 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
78 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
79 {};
95
80
96 PythonQtClassInfo* _parent;
81 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
82 int _upcastingOffset;
98 };
83 };
99
84
100
85
101 //! setup as a QObject, taking the meta object as meta information about the QObject
86 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
87 void setupQObject(const QMetaObject* meta);
103
88
104 //! setup as a CPP (non-QObject), taking the classname
89 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
90 void setupCPPObject(const QByteArray& classname);
106
91
107 //! set the type capabilities
92 //! set the type capabilities
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
93 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 //! get the type capabilities
94 //! get the type capabilities
110 int typeSlots() const { return _typeSlots; }
95 int typeSlots() const { return _typeSlots; }
111
96
112 //! get the Python method definition for a given slot name (without return type and signature)
97 //! get the Python method definition for a given slot name (without return type and signature)
113 PythonQtMemberInfo member(const char* member);
98 PythonQtMemberInfo member(const char* member);
114
99
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
100 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
116 PythonQtSlotInfo* constructors();
101 PythonQtSlotInfo* constructors();
117
102
118 //! get access to the destructor slot
103 //! get access to the destructor slot
119 PythonQtSlotInfo* destructor();
104 PythonQtSlotInfo* destructor();
120
105
121 //! add a constructor, ownership is passed to classinfo
106 //! add a constructor, ownership is passed to classinfo
122 void addConstructor(PythonQtSlotInfo* info);
107 void addConstructor(PythonQtSlotInfo* info);
123
108
124 //! set a destructor, ownership is passed to classinfo
109 //! set a destructor, ownership is passed to classinfo
125 void setDestructor(PythonQtSlotInfo* info);
110 void setDestructor(PythonQtSlotInfo* info);
126
111
127 //! add a decorator slot, ownership is passed to classinfo
112 //! add a decorator slot, ownership is passed to classinfo
128 void addDecoratorSlot(PythonQtSlotInfo* info);
113 void addDecoratorSlot(PythonQtSlotInfo* info);
129
114
130 //! get the classname (either of the QObject or of the wrapped CPP object)
115 //! get the classname (either of the QObject or of the wrapped CPP object)
131 const char* className();
116 const char* className();
132
117
133 //! returns if the QObject
118 //! returns if the QObject
134 bool isQObject() { return _isQObject; }
119 bool isQObject() { return _isQObject; }
135
120
136 //! returns if the class is a CPP wrapper
121 //! returns if the class is a CPP wrapper
137 bool isCPPWrapper() { return !_isQObject; }
122 bool isCPPWrapper() { return !_isQObject; }
138
123
139 //! get the meta object
124 //! get the meta object
140 const QMetaObject* metaObject() { return _meta; }
125 const QMetaObject* metaObject() { return _meta; }
141
126
142 //! set the meta object, this will reset the caching
127 //! set the meta object, this will reset the caching
143 void setMetaObject(const QMetaObject* meta);
128 void setMetaObject(const QMetaObject* meta);
144
129
145 //! returns if this class inherits from the given classname
130 //! returns if this class inherits from the given classname
146 bool inherits(const char* classname);
131 bool inherits(const char* classname);
147
132
148 //! returns if this class inherits from the given classinfo
133 //! returns if this class inherits from the given classinfo
149 bool inherits(PythonQtClassInfo* info);
134 bool inherits(PythonQtClassInfo* info);
150
135
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
136 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
152 //! which might be different to \c ptr due to C++ multiple inheritance
137 //! which might be different to \c ptr due to C++ multiple inheritance
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
138 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
154 void* castTo(void* ptr, const char* classname);
139 void* castTo(void* ptr, const char* classname);
155
140
156 //! get help string for the metaobject
141 //! get help string for the metaobject
157 QString help();
142 QString help();
158
143
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
144 //! get list of all properties (on QObjects only, otherwise the list is empty)
160 QStringList propertyList();
145 QStringList propertyList();
161
146
162 //! get list of all members
147 //! get list of all members (excluding properties, which can be listed with propertyList())
163 QStringList memberList(bool metaOnly = false);
148 QStringList memberList();
164
149
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
150 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
166 int metaTypeId() { return _metaTypeId; }
151 int metaTypeId() { return _metaTypeId; }
167
152
168 //! set an additional decorator provider that offers additional decorator slots for this class
153 //! set an additional decorator provider that offers additional decorator slots for this class
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
154 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
170
155
171 //! get the decorator qobject instance
156 //! get the decorator qobject instance
172 QObject* decorator();
157 QObject* decorator();
173
158
174 //! add the parent class info of a CPP object
159 //! add the parent class info of a CPP object
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
160 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
176
161
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
162 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
178 bool hasOwnerMethodButNoOwner(void* object);
163 bool hasOwnerMethodButNoOwner(void* object);
179
164
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
165 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
166 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
182
167
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
168 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
169 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
185
170
186 //! set the shell set instance wrapper cb
171 //! set the shell set instance wrapper cb
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
172 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
188 _shellSetInstanceWrapperCB = cb;
173 _shellSetInstanceWrapperCB = cb;
189 }
174 }
190
175
191 //! get the shell set instance wrapper cb
176 //! get the shell set instance wrapper cb
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
177 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
193 return _shellSetInstanceWrapperCB;
178 return _shellSetInstanceWrapperCB;
194 }
179 }
195
180
196 //! add a handler for polymorphic downcasting
181 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
182 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
198
183
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
184 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
185 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
201
186
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
187 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
188 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204
189
205 //! clear all members that where cached as "NotFound"
190 //! clear all members that where cached as "NotFound"
206 void clearNotFoundCachedMembers();
191 void clearNotFoundCachedMembers();
207
192
208 private:
193 private:
209 void createEnumWrappers();
194 void createEnumWrappers();
210 void createEnumWrappers(const QMetaObject* meta);
195 void createEnumWrappers(const QMetaObject* meta);
211 PyObject* findEnumWrapper(const char* name);
196 PyObject* findEnumWrapper(const char* name);
212
197
213 //! clear all cached members
198 //! clear all cached members
214 void clearCachedMembers();
199 void clearCachedMembers();
215
200
216 void* recursiveCastDownIfPossible(void* ptr, const char** resultClassName);
201 void* recursiveCastDownIfPossible(void* ptr, const char** resultClassName);
217
202
218 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
203 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
219 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
204 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
220 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
205 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
221
206
222 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
207 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
223 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
208 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
224
209
225 bool lookForPropertyAndCache(const char* memberName);
210 bool lookForPropertyAndCache(const char* memberName);
226 bool lookForMethodAndCache(const char* memberName);
211 bool lookForMethodAndCache(const char* memberName);
227 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
212 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
228
213
229 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
214 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
230 int findCharOffset(const char* sigStart, char someChar);
215 int findCharOffset(const char* sigStart, char someChar);
231
216
232 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
217 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
233
218
234 PythonQtSlotInfo* _constructors;
219 PythonQtSlotInfo* _constructors;
235 PythonQtSlotInfo* _destructor;
220 PythonQtSlotInfo* _destructor;
236 QList<PythonQtSlotInfo*> _decoratorSlots;
221 QList<PythonQtSlotInfo*> _decoratorSlots;
237
222
238 QList<PythonQtObjectPtr> _enumWrappers;
223 QList<PythonQtObjectPtr> _enumWrappers;
239
224
240 const QMetaObject* _meta;
225 const QMetaObject* _meta;
241
226
242 QByteArray _wrappedClassName;
227 QByteArray _wrappedClassName;
243 QList<ParentClassInfo> _parentClasses;
228 QList<ParentClassInfo> _parentClasses;
244
229
245 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
230 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
246
231
247 QObject* _decoratorProvider;
232 QObject* _decoratorProvider;
248 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
233 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
249
234
250 PyObject* _pythonQtClassWrapper;
235 PyObject* _pythonQtClassWrapper;
251
236
252 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
237 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
253
238
254 int _metaTypeId;
239 int _metaTypeId;
255 int _typeSlots;
240 int _typeSlots;
256
241
257 bool _isQObject;
242 bool _isQObject;
258 bool _enumsCreated;
243 bool _enumsCreated;
259
244
260 };
245 };
261
246
262 //---------------------------------------------------------------
247 //---------------------------------------------------------------
263
248
264
249
265 #endif
250 #endif
@@ -1,494 +1,471
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtClassWrapper.cpp
35 // \file PythonQtClassWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassWrapper.h"
42 #include "PythonQtClassWrapper.h"
43 #include <QObject>
43 #include <QObject>
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtSignal.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
50 #include "PythonQtInstanceWrapper.h"
50
51
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 {
53 {
53 PyObject* result = NULL;
54 PyObject* result = NULL;
54 static QByteArray memberName = "__invert__";
55 static QByteArray memberName = "__invert__";
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 }
59 }
59 return result;
60 return result;
60 }
61 }
61
62
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 {
64 {
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 if (result) {
66 if (result) {
66 static QByteArray memberName = "__nonzero__";
67 static QByteArray memberName = "__nonzero__";
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 if (resultObj == Py_False) {
71 if (resultObj == Py_False) {
71 result = 0;
72 result = 0;
72 }
73 }
73 Py_XDECREF(resultObj);
74 Py_XDECREF(resultObj);
74 }
75 }
75 }
76 }
76 return result;
77 return result;
77 }
78 }
78
79
79
80
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 {
82 {
82 // since we disabled type checking, we can receive any object as self, but we currently only support
83 // since we disabled type checking, we can receive any object as self, but we currently only support
83 // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
84 // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
84 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
85 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
85 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
86 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
86 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
87 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
87 return NULL;
88 return NULL;
88 }
89 }
89 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
90 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
90 PyObject* result = NULL;
91 PyObject* result = NULL;
91 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
92 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
92 if (opSlot._type == PythonQtMemberInfo::Slot) {
93 if (opSlot._type == PythonQtMemberInfo::Slot) {
93 // TODO get rid of tuple
94 // TODO get rid of tuple
94 PyObject* args = PyTuple_New(1);
95 PyObject* args = PyTuple_New(1);
95 Py_INCREF(other);
96 Py_INCREF(other);
96 PyTuple_SET_ITEM(args, 0, other);
97 PyTuple_SET_ITEM(args, 0, other);
97 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
98 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
98 Py_DECREF(args);
99 Py_DECREF(args);
99 if (!result && !fallbackOpName.isEmpty()) {
100 if (!result && !fallbackOpName.isEmpty()) {
100 // try fallback if we did not get a result
101 // try fallback if we did not get a result
101 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
102 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
102 }
103 }
103 }
104 }
104 return result;
105 return result;
105 }
106 }
106
107
107 #define BINARY_OP(NAME) \
108 #define BINARY_OP(NAME) \
108 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
109 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
109 { \
110 { \
110 static const QByteArray opName("__" #NAME "__"); \
111 static const QByteArray opName("__" #NAME "__"); \
111 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
112 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
112 }
113 }
113
114
114 #define BINARY_OP_INPLACE(NAME) \
115 #define BINARY_OP_INPLACE(NAME) \
115 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
116 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
116 { \
117 { \
117 static const QByteArray opName("__i" #NAME "__"); \
118 static const QByteArray opName("__i" #NAME "__"); \
118 static const QByteArray fallbackName("__" #NAME "__"); \
119 static const QByteArray fallbackName("__" #NAME "__"); \
119 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
120 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
120 }
121 }
121
122
122 BINARY_OP(add)
123 BINARY_OP(add)
123 BINARY_OP(sub)
124 BINARY_OP(sub)
124 BINARY_OP(mul)
125 BINARY_OP(mul)
125 BINARY_OP(div)
126 BINARY_OP(div)
126 BINARY_OP(and)
127 BINARY_OP(and)
127 BINARY_OP(or)
128 BINARY_OP(or)
128 BINARY_OP(xor)
129 BINARY_OP(xor)
129 BINARY_OP(mod)
130 BINARY_OP(mod)
130 BINARY_OP(lshift)
131 BINARY_OP(lshift)
131 BINARY_OP(rshift)
132 BINARY_OP(rshift)
132
133
133 BINARY_OP_INPLACE(add)
134 BINARY_OP_INPLACE(add)
134 BINARY_OP_INPLACE(sub)
135 BINARY_OP_INPLACE(sub)
135 BINARY_OP_INPLACE(mul)
136 BINARY_OP_INPLACE(mul)
136 BINARY_OP_INPLACE(div)
137 BINARY_OP_INPLACE(div)
137 BINARY_OP_INPLACE(and)
138 BINARY_OP_INPLACE(and)
138 BINARY_OP_INPLACE(or)
139 BINARY_OP_INPLACE(or)
139 BINARY_OP_INPLACE(xor)
140 BINARY_OP_INPLACE(xor)
140 BINARY_OP_INPLACE(mod)
141 BINARY_OP_INPLACE(mod)
141 BINARY_OP_INPLACE(lshift)
142 BINARY_OP_INPLACE(lshift)
142 BINARY_OP_INPLACE(rshift)
143 BINARY_OP_INPLACE(rshift)
143
144
144 static void initializeSlots(PythonQtClassWrapper* wrap)
145 static void initializeSlots(PythonQtClassWrapper* wrap)
145 {
146 {
146 int typeSlots = wrap->classInfo()->typeSlots();
147 int typeSlots = wrap->classInfo()->typeSlots();
147 if (typeSlots) {
148 if (typeSlots) {
148 if (typeSlots & PythonQt::Type_Add) {
149 if (typeSlots & PythonQt::Type_Add) {
149 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
150 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
150 }
151 }
151 if (typeSlots & PythonQt::Type_Subtract) {
152 if (typeSlots & PythonQt::Type_Subtract) {
152 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
153 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
153 }
154 }
154 if (typeSlots & PythonQt::Type_Multiply) {
155 if (typeSlots & PythonQt::Type_Multiply) {
155 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
156 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
156 }
157 }
157 if (typeSlots & PythonQt::Type_Divide) {
158 if (typeSlots & PythonQt::Type_Divide) {
158 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
159 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
159 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
160 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
160 }
161 }
161 if (typeSlots & PythonQt::Type_And) {
162 if (typeSlots & PythonQt::Type_And) {
162 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
163 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
163 }
164 }
164 if (typeSlots & PythonQt::Type_Or) {
165 if (typeSlots & PythonQt::Type_Or) {
165 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
166 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
166 }
167 }
167 if (typeSlots & PythonQt::Type_Xor) {
168 if (typeSlots & PythonQt::Type_Xor) {
168 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
169 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
169 }
170 }
170 if (typeSlots & PythonQt::Type_Mod) {
171 if (typeSlots & PythonQt::Type_Mod) {
171 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
172 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
172 }
173 }
173 if (typeSlots & PythonQt::Type_LShift) {
174 if (typeSlots & PythonQt::Type_LShift) {
174 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
175 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
175 }
176 }
176 if (typeSlots & PythonQt::Type_RShift) {
177 if (typeSlots & PythonQt::Type_RShift) {
177 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
178 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
178 }
179 }
179
180
180 if (typeSlots & PythonQt::Type_InplaceAdd) {
181 if (typeSlots & PythonQt::Type_InplaceAdd) {
181 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
182 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
182 }
183 }
183 if (typeSlots & PythonQt::Type_InplaceSubtract) {
184 if (typeSlots & PythonQt::Type_InplaceSubtract) {
184 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
185 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
185 }
186 }
186 if (typeSlots & PythonQt::Type_InplaceMultiply) {
187 if (typeSlots & PythonQt::Type_InplaceMultiply) {
187 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
188 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
188 }
189 }
189 if (typeSlots & PythonQt::Type_InplaceDivide) {
190 if (typeSlots & PythonQt::Type_InplaceDivide) {
190 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
191 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
191 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
192 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
192 }
193 }
193 if (typeSlots & PythonQt::Type_InplaceAnd) {
194 if (typeSlots & PythonQt::Type_InplaceAnd) {
194 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
195 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
195 }
196 }
196 if (typeSlots & PythonQt::Type_InplaceOr) {
197 if (typeSlots & PythonQt::Type_InplaceOr) {
197 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
198 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
198 }
199 }
199 if (typeSlots & PythonQt::Type_InplaceXor) {
200 if (typeSlots & PythonQt::Type_InplaceXor) {
200 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
201 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
201 }
202 }
202 if (typeSlots & PythonQt::Type_InplaceMod) {
203 if (typeSlots & PythonQt::Type_InplaceMod) {
203 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
204 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
204 }
205 }
205 if (typeSlots & PythonQt::Type_InplaceLShift) {
206 if (typeSlots & PythonQt::Type_InplaceLShift) {
206 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
207 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
207 }
208 }
208 if (typeSlots & PythonQt::Type_InplaceRShift) {
209 if (typeSlots & PythonQt::Type_InplaceRShift) {
209 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
210 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
210 }
211 }
211 if (typeSlots & PythonQt::Type_Invert) {
212 if (typeSlots & PythonQt::Type_Invert) {
212 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
213 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
213 }
214 }
214 if (typeSlots & PythonQt::Type_NonZero) {
215 if (typeSlots & PythonQt::Type_NonZero) {
215 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
216 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
216 }
217 }
217 }
218 }
218 }
219 }
219
220
220 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
221 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
221 {
222 {
222 // call the default type alloc
223 // call the default type alloc
223 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
224 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
224
225
225 // take current class type, if we are called via newPythonQtClassWrapper()
226 // take current class type, if we are called via newPythonQtClassWrapper()
226 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
227 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
227 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
228 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
228 if (wrap->_classInfo) {
229 if (wrap->_classInfo) {
229 initializeSlots(wrap);
230 initializeSlots(wrap);
230 }
231 }
231
232
232 return obj;
233 return obj;
233 }
234 }
234
235
235
236
236 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
237 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
237 {
238 {
238 // call the default type init
239 // call the default type init
239 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
240 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
240 return -1;
241 return -1;
241 }
242 }
242
243
243 // if we have no CPP class information, try our base class
244 // if we have no CPP class information, try our base class
244 if (!self->classInfo()) {
245 if (!self->classInfo()) {
245 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
246 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
246
247
247 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
248 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
248 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
249 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
249 return -1;
250 return -1;
250 }
251 }
251
252
252 // take the class info from the superType
253 // take the class info from the superType
253 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
254 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
254 }
255 }
255
256
256 return 0;
257 return 0;
257 }
258 }
258
259
259 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
260 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
260 {
261 {
261 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
262 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
262 }
263 }
263
264
264 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
265 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
265 {
266 {
266 return PythonQt::self()->helpCalled(type->classInfo());
267 return PythonQt::self()->helpCalled(type->classInfo());
267 }
268 }
268
269
269 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
270 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
270 {
271 {
271 Q_UNUSED(type);
272 Q_UNUSED(type);
272
273
273 Py_ssize_t argc = PyTuple_Size(args);
274 Py_ssize_t argc = PyTuple_Size(args);
274 if (argc>0) {
275 if (argc>0) {
275 PyObject* self = PyTuple_GET_ITEM(args, 0);
276 PyObject* self = PyTuple_GET_ITEM(args, 0);
276 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
277 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
277 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
278 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
278 }
279 }
279 }
280 }
280 return NULL;
281 return NULL;
281 }
282 }
282
283
283 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
284 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
284 {
285 {
285 Q_UNUSED(type);
286 Q_UNUSED(type);
286 PythonQtInstanceWrapper* wrapper = NULL;
287 PythonQtInstanceWrapper* wrapper = NULL;
287 char *name = NULL;
288 char *name = NULL;
288 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
289 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
289 return NULL;
290 return NULL;
290 }
291 }
291 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
292 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
292 }
293 }
293
294
294 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
295 {
296 Py_ssize_t argc = PyTuple_Size(args);
297 if (argc>0) {
298 // we need to call __init__ of the instance
299 PyObject* self = PyTuple_GET_ITEM(args, 0);
300 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
301 PyObject* newargs = PyTuple_New(argc-1);
302 for (int i = 0;i<argc-1; i++) {
303 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
304 }
305 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
306 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
307 Py_DECREF(newargs);
308 if (result==0) {
309 Py_INCREF(Py_None);
310 return Py_None;
311 } else {
312 // init failed!
313 }
314 } else {
315 // self not of correct type!
316 }
317 } else {
318 // wrong number of args
319 }
320 return NULL;
321 }
322
323
295
324 static PyMethodDef PythonQtClassWrapper_methods[] = {
296 static PyMethodDef PythonQtClassWrapper_methods[] = {
325 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
326 "Init function"
327 },
328 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
297 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
329 "Return the classname of the object"
298 "Return the classname of the object"
330 },
299 },
331 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
300 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
332 "Returns if the class inherits or is of given type name"
301 "Returns if the class inherits or is of given type name"
333 },
302 },
334 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
303 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
335 "Shows the help of available methods for this class"
304 "Shows the help of available methods for this class"
336 },
305 },
337 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
306 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
338 "Deletes the given C++ object"
307 "Deletes the given C++ object"
339 },
308 },
340 {NULL, NULL, 0 , NULL} /* Sentinel */
309 {NULL, NULL, 0 , NULL} /* Sentinel */
341 };
310 };
342
311
343
312
344 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
313 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
345 {
314 {
346 const char *attributeName;
315 const char *attributeName;
347 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
316 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
348
317
349 if ((attributeName = PyString_AsString(name)) == NULL) {
318 if ((attributeName = PyString_AsString(name)) == NULL) {
350 return NULL;
319 return NULL;
351 }
320 }
352 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
321 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
353 return NULL;
322 return NULL;
354 }
323 }
355
324
356 if (qstrcmp(attributeName, "__dict__")==0) {
325 if (qstrcmp(attributeName, "__dict__")==0) {
357 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
326 PyObject* objectDict = ((PyTypeObject *)wrapper)->tp_dict;
358 if (!wrapper->classInfo()) {
327 if (!wrapper->classInfo()) {
359 Py_INCREF(dict);
328 Py_INCREF(objectDict);
360 return dict;
329 return objectDict;
361 }
330 }
362 dict = PyDict_Copy(dict);
331 PyObject* dict = PyDict_New();
363
332
364 QStringList l = wrapper->classInfo()->memberList(false);
333 QStringList l = wrapper->classInfo()->memberList();
365 foreach (QString name, l) {
334 foreach (QString name, l) {
366 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
335 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
367 if (o) {
336 if (o) {
368 PyDict_SetItemString(dict, name.toLatin1().data(), o);
337 PyDict_SetItemString(dict, name.toLatin1().data(), o);
369 Py_DECREF(o);
338 Py_DECREF(o);
370 } else {
339 } else {
371 // it must have been a property or child, which we do not know as a class object...
340 // it must have been a property or child, which we do not know as a class object...
341 PyErr_Clear();
372 }
342 }
373 }
343 }
374 if (wrapper->classInfo()->constructors()) {
344 if (wrapper->classInfo()->constructors()) {
375 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
345 PyObject* initName = PyString_FromString("__init__");
346 PyObject* func = PyType_Type.tp_getattro(obj, initName);
347 Py_DECREF(initName);
376 PyDict_SetItemString(dict, "__init__", func);
348 PyDict_SetItemString(dict, "__init__", func);
377 Py_DECREF(func);
349 Py_DECREF(func);
378 }
350 }
379 for (int i = 1; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
351 for (int i = 0; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
380 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
352 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
381 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
353 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
382 Py_DECREF(func);
354 Py_DECREF(func);
383 }
355 }
356
357 PyDict_Update(dict, objectDict);
384 return dict;
358 return dict;
385 }
359 }
386
360
361 // look in Python to support derived Python classes
362 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
363 if (superAttr) {
364 return superAttr;
365 }
366 PyErr_Clear();
367
387 if (wrapper->classInfo()) {
368 if (wrapper->classInfo()) {
388 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
369 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
389 if (member._type == PythonQtMemberInfo::EnumValue) {
370 if (member._type == PythonQtMemberInfo::EnumValue) {
390 PyObject* enumValue = member._enumValue;
371 PyObject* enumValue = member._enumValue;
391 Py_INCREF(enumValue);
372 Py_INCREF(enumValue);
392 return enumValue;
373 return enumValue;
393 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
374 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
394 PyObject* enumWrapper = member._enumWrapper;
375 PyObject* enumWrapper = member._enumWrapper;
395 Py_INCREF(enumWrapper);
376 Py_INCREF(enumWrapper);
396 return enumWrapper;
377 return enumWrapper;
397 } else if (member._type == PythonQtMemberInfo::Slot) {
378 } else if (member._type == PythonQtMemberInfo::Slot) {
398 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
379 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
399 return PythonQtSlotFunction_New(member._slot, obj, NULL);
380 return PythonQtSlotFunction_New(member._slot, obj, NULL);
381 } else if (member._type == PythonQtMemberInfo::Signal) {
382 // we return all signals, even the instance signals, since they are callable as unbound signals with self argument
383 return PythonQtSignalFunction_New(member._slot, obj, NULL);
400 }
384 }
401 }
385 }
402
386
403 // look for the interal methods (className(), help())
387 // look for the internal methods (className(), help())
404 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
388 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
405 if (internalMethod) {
389 if (internalMethod) {
406 return internalMethod;
390 return internalMethod;
407 }
391 }
408 PyErr_Clear();
409
410 // look in super
411 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
412 if (superAttr) {
413 return superAttr;
414 }
415
392
416 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
393 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
417 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
394 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
418 return NULL;
395 return NULL;
419 }
396 }
420
397
421 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
398 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
422 {
399 {
423 return PyType_Type.tp_setattro(obj,name,value);
400 return PyType_Type.tp_setattro(obj,name,value);
424 }
401 }
425
402
426 /*
403 /*
427 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
404 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
428 {
405 {
429 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
406 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
430 if (wrapper->classInfo()->isCPPWrapper()) {
407 if (wrapper->classInfo()->isCPPWrapper()) {
431 const QMetaObject* meta = wrapper->classInfo()->metaObject();
408 const QMetaObject* meta = wrapper->classInfo()->metaObject();
432 if (!meta) {
409 if (!meta) {
433 QObject* decorator = wrapper->classInfo()->decorator();
410 QObject* decorator = wrapper->classInfo()->decorator();
434 if (decorator) {
411 if (decorator) {
435 meta = decorator->metaObject();
412 meta = decorator->metaObject();
436 }
413 }
437 }
414 }
438 if (meta) {
415 if (meta) {
439 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
416 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
440 } else {
417 } else {
441 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
418 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
442 }
419 }
443 } else {
420 } else {
444 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
421 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
445 }
422 }
446 }
423 }
447
424
448 */
425 */
449
426
450 PyTypeObject PythonQtClassWrapper_Type = {
427 PyTypeObject PythonQtClassWrapper_Type = {
451 PyObject_HEAD_INIT(NULL)
428 PyObject_HEAD_INIT(NULL)
452 0, /*ob_size*/
429 0, /*ob_size*/
453 "PythonQt.PythonQtClassWrapper", /*tp_name*/
430 "PythonQt.PythonQtClassWrapper", /*tp_name*/
454 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
431 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
455 0, /*tp_itemsize*/
432 0, /*tp_itemsize*/
456 0, /*tp_dealloc*/
433 0, /*tp_dealloc*/
457 0, /*tp_print*/
434 0, /*tp_print*/
458 0, /*tp_getattr*/
435 0, /*tp_getattr*/
459 0, /*tp_setattr*/
436 0, /*tp_setattr*/
460 0, /*tp_compare*/
437 0, /*tp_compare*/
461 0, //PythonQtClassWrapper_repr, /*tp_repr*/
438 0, //PythonQtClassWrapper_repr, /*tp_repr*/
462 0, /*tp_as_number*/
439 0, /*tp_as_number*/
463 0, /*tp_as_sequence*/
440 0, /*tp_as_sequence*/
464 0, /*tp_as_mapping*/
441 0, /*tp_as_mapping*/
465 0, /*tp_hash */
442 0, /*tp_hash */
466 0, /*tp_call*/
443 0, /*tp_call*/
467 0, /*tp_str*/
444 0, /*tp_str*/
468 PythonQtClassWrapper_getattro, /*tp_getattro*/
445 PythonQtClassWrapper_getattro, /*tp_getattro*/
469 PythonQtClassWrapper_setattro, /*tp_setattro*/
446 PythonQtClassWrapper_setattro, /*tp_setattro*/
470 0, /*tp_as_buffer*/
447 0, /*tp_as_buffer*/
471 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
448 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
472 0, /* tp_doc */
449 0, /* tp_doc */
473 0, /* tp_traverse */
450 0, /* tp_traverse */
474 0, /* tp_clear */
451 0, /* tp_clear */
475 0, /* tp_richcompare */
452 0, /* tp_richcompare */
476 0, /* tp_weaklistoffset */
453 0, /* tp_weaklistoffset */
477 0, /* tp_iter */
454 0, /* tp_iter */
478 0, /* tp_iternext */
455 0, /* tp_iternext */
479 0, /* tp_methods */
456 0, /* tp_methods */
480 0, /* tp_members */
457 0, /* tp_members */
481 0, /* tp_getset */
458 0, /* tp_getset */
482 0, /* tp_base */
459 0, /* tp_base */
483 0, /* tp_dict */
460 0, /* tp_dict */
484 0, /* tp_descr_get */
461 0, /* tp_descr_get */
485 0, /* tp_descr_set */
462 0, /* tp_descr_set */
486 0, /* tp_dictoffset */
463 0, /* tp_dictoffset */
487 (initproc)PythonQtClassWrapper_init, /* tp_init */
464 (initproc)PythonQtClassWrapper_init, /* tp_init */
488 PythonQtClassWrapper_alloc, /* tp_alloc */
465 PythonQtClassWrapper_alloc, /* tp_alloc */
489 0, /* tp_new */
466 0, /* tp_new */
490 0, /* tp_free */
467 0, /* tp_free */
491 };
468 };
492
469
493 //-------------------------------------------------------
470 //-------------------------------------------------------
494
471
@@ -1,76 +1,81
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtImportFileInterface.h
38 // \file PythonQtImportFileInterface.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QString>
46 #include <QString>
47 #include <QByteArray>
47 #include <QByteArray>
48
48
49 //! Defines an abstract interface to file access for the Python import statement.
49 //! Defines an abstract interface to file access for the Python import statement.
50 //! see PythonQt::setImporter()
50 //! see PythonQt::setImporter()
51 class PythonQtImportFileInterface {
51 class PythonQtImportFileInterface {
52
52
53 public:
53 public:
54 // get rid of warnings
54 // get rid of warnings
55 virtual ~PythonQtImportFileInterface() {}
55 virtual ~PythonQtImportFileInterface() {}
56
56
57 //! read the given file as byte array, without doing any linefeed translations
57 //! read the given file as byte array, without doing any linefeed translations
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
59
59
60 //! read a source file, expects a readable Python text file with translated line feeds.
60 //! read a source file, expects a readable Python text file with translated line feeds.
61 //! If the file can not be load OR it can not be verified, ok is set to false
61 //! If the file can not be load OR it can not be verified, ok is set to false
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
63
63
64 //! returns if the file exists
64 //! returns if the file exists
65 virtual bool exists(const QString& filename) = 0;
65 virtual bool exists(const QString& filename) = 0;
66
66
67 //! get the last modified data of a file
67 //! get the last modified data of a file
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
69
69
70 //! indicates that *.py files which are newer than their corresponding *.pyc files
70 //! indicates that *.py files which are newer than their corresponding *.pyc files
71 //! are ignored
71 //! are ignored
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
73
74 //! called by PythonQt after successful import to allow
75 //! recording of imports
76 virtual void importedModule(const QString& /*module*/) {};
77
73 };
78 };
74
79
75 #endif
80 #endif
76
81
@@ -1,822 +1,828
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtImporter.h
35 // \file PythonQtImporter.h
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51 #include <QFile>
51 #include <QFile>
52 #include <QFileInfo>
52 #include <QFileInfo>
53
53
54 #define IS_SOURCE 0x0
54 #define IS_SOURCE 0x0
55 #define IS_BYTECODE 0x1
55 #define IS_BYTECODE 0x1
56 #define IS_PACKAGE 0x2
56 #define IS_PACKAGE 0x2
57
57
58 struct st_mlab_searchorder {
58 struct st_mlab_searchorder {
59 char suffix[14];
59 char suffix[14];
60 int type;
60 int type;
61 };
61 };
62
62
63 /* mlab_searchorder defines how we search for a module in the Zip
63 /* mlab_searchorder defines how we search for a module in the Zip
64 archive: we first search for a package __init__, then for
64 archive: we first search for a package __init__, then for
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
66 are swapped by initmlabimport() if we run in optimized mode. Also,
66 are swapped by initmlabimport() if we run in optimized mode. Also,
67 '/' is replaced by SEP there. */
67 '/' is replaced by SEP there. */
68 struct st_mlab_searchorder mlab_searchorder[] = {
68 struct st_mlab_searchorder mlab_searchorder[] = {
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
72 {".pyc", IS_BYTECODE},
72 {".pyc", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
74 {".py", IS_SOURCE},
74 {".py", IS_SOURCE},
75 {"", 0}
75 {"", 0}
76 };
76 };
77
77
78 extern PyTypeObject PythonQtImporter_Type;
78 extern PyTypeObject PythonQtImporter_Type;
79 PyObject *PythonQtImportError;
79 PyObject *PythonQtImportError;
80
80
81 QString PythonQtImport::getSubName(const QString& str)
81 QString PythonQtImport::getSubName(const QString& str)
82 {
82 {
83 int idx = str.lastIndexOf('.');
83 int idx = str.lastIndexOf('.');
84 if (idx!=-1) {
84 if (idx!=-1) {
85 return str.mid(idx+1);
85 return str.mid(idx+1);
86 } else {
86 } else {
87 return str;
87 return str;
88 }
88 }
89 }
89 }
90
90
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
92 {
92 {
93 ModuleInfo info;
93 ModuleInfo info;
94 QString subname;
94 QString subname;
95 struct st_mlab_searchorder *zso;
95 struct st_mlab_searchorder *zso;
96
96
97 subname = getSubName(fullname);
97 subname = getSubName(fullname);
98 QString path = *self->_path + "/" + subname;
98 QString path = *self->_path + "/" + subname;
99
99
100 QString test;
100 QString test;
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
102 test = path + zso->suffix;
102 test = path + zso->suffix;
103 if (PythonQt::importInterface()->exists(test)) {
103 if (PythonQt::importInterface()->exists(test)) {
104 info.fullPath = test;
104 info.fullPath = test;
105 info.moduleName = subname;
105 info.moduleName = subname;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
107 return info;
107 return info;
108 }
108 }
109 }
109 }
110 // test if it is a shared library
110 // test if it is a shared library
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
112 test = path+suffix;
112 test = path+suffix;
113 if (PythonQt::importInterface()->exists(test)) {
113 if (PythonQt::importInterface()->exists(test)) {
114 info.fullPath = test;
114 info.fullPath = test;
115 info.moduleName = subname;
115 info.moduleName = subname;
116 info.type = MI_SHAREDLIBRARY;
116 info.type = MI_SHAREDLIBRARY;
117 return info;
117 return info;
118 }
118 }
119 }
119 }
120 return info;
120 return info;
121 }
121 }
122
122
123
123
124 /* PythonQtImporter.__init__
124 /* PythonQtImporter.__init__
125 Just store the path argument (or reject if it is in the ignorePaths list
125 Just store the path argument (or reject if it is in the ignorePaths list
126 */
126 */
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
128 {
128 {
129 self->_path = NULL;
129 self->_path = NULL;
130
130
131 const char* cpath;
131 const char* cpath;
132 if (!PyArg_ParseTuple(args, "s",
132 if (!PyArg_ParseTuple(args, "s",
133 &cpath))
133 &cpath))
134 return -1;
134 return -1;
135
135
136 QString path(cpath);
136 QString path(cpath);
137 if (PythonQt::importInterface()->exists(path)) {
137 if (PythonQt::importInterface()->exists(path)) {
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
139 foreach(QString ignorePath, ignorePaths) {
139 foreach(QString ignorePath, ignorePaths) {
140 if (path.startsWith(ignorePath)) {
140 if (path.startsWith(ignorePath)) {
141 PyErr_SetString(PythonQtImportError,
141 PyErr_SetString(PythonQtImportError,
142 "path ignored");
142 "path ignored");
143 return -1;
143 return -1;
144 }
144 }
145 }
145 }
146
146
147 self->_path = new QString(path);
147 self->_path = new QString(path);
148 return 0;
148 return 0;
149 } else {
149 } else {
150 PyErr_SetString(PythonQtImportError,
150 PyErr_SetString(PythonQtImportError,
151 "path does not exist error");
151 "path does not exist error");
152 return -1;
152 return -1;
153 }
153 }
154 }
154 }
155
155
156 void
156 void
157 PythonQtImporter_dealloc(PythonQtImporter *self)
157 PythonQtImporter_dealloc(PythonQtImporter *self)
158 {
158 {
159 // free the stored path
159 // free the stored path
160 if (self->_path) delete self->_path;
160 if (self->_path) delete self->_path;
161 // free ourself
161 // free ourself
162 self->ob_type->tp_free((PyObject *)self);
162 self->ob_type->tp_free((PyObject *)self);
163 }
163 }
164
164
165
165
166 /* Check whether we can satisfy the import of the module named by
166 /* Check whether we can satisfy the import of the module named by
167 'fullname'. Return self if we can, None if we can't. */
167 'fullname'. Return self if we can, None if we can't. */
168 PyObject *
168 PyObject *
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
170 {
170 {
171 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PythonQtImporter *self = (PythonQtImporter *)obj;
172 PyObject *path = NULL;
172 PyObject *path = NULL;
173 char *fullname;
173 char *fullname;
174
174
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
176 &fullname, &path))
176 &fullname, &path))
177 return NULL;
177 return NULL;
178
178
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
180
180
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
183 Py_INCREF(self);
183 Py_INCREF(self);
184 return (PyObject *)self;
184 return (PyObject *)self;
185 } else {
185 } else {
186 Py_INCREF(Py_None);
186 Py_INCREF(Py_None);
187 return Py_None;
187 return Py_None;
188 }
188 }
189 }
189 }
190
190
191 /* Load and return the module named by 'fullname'. */
191 /* Load and return the module named by 'fullname'. */
192 PyObject *
192 PyObject *
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
194 {
194 {
195 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PythonQtImporter *self = (PythonQtImporter *)obj;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
197 char *fullname;
197 char *fullname;
198
198
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
200 &fullname))
200 &fullname))
201 return NULL;
201 return NULL;
202
202
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
205 return NULL;
205 return NULL;
206 }
206 }
207
207
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
209 QString fullPath;
209 QString fullPath;
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
211 if (code == NULL) {
211 if (code == NULL) {
212 return NULL;
212 return NULL;
213 }
213 }
214
214
215 mod = PyImport_AddModule(fullname);
215 mod = PyImport_AddModule(fullname);
216 if (mod == NULL) {
216 if (mod == NULL) {
217 Py_DECREF(code);
217 Py_DECREF(code);
218 return NULL;
218 return NULL;
219 }
219 }
220 dict = PyModule_GetDict(mod);
220 dict = PyModule_GetDict(mod);
221
221
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
223 Py_DECREF(code);
223 Py_DECREF(code);
224 Py_DECREF(mod);
224 Py_DECREF(mod);
225 return NULL;
225 return NULL;
226 }
226 }
227
227
228 if (info.type == PythonQtImport::MI_PACKAGE) {
228 if (info.type == PythonQtImport::MI_PACKAGE) {
229 PyObject *pkgpath, *fullpath;
229 PyObject *pkgpath, *fullpath;
230 QString subname = info.moduleName;
230 QString subname = info.moduleName;
231 int err;
231 int err;
232
232
233 fullpath = PyString_FromFormat("%s%c%s",
233 fullpath = PyString_FromFormat("%s%c%s",
234 self->_path->toLatin1().constData(),
234 self->_path->toLatin1().constData(),
235 SEP,
235 SEP,
236 subname.toLatin1().constData());
236 subname.toLatin1().constData());
237 if (fullpath == NULL) {
237 if (fullpath == NULL) {
238 Py_DECREF(code);
238 Py_DECREF(code);
239 Py_DECREF(mod);
239 Py_DECREF(mod);
240 return NULL;
240 return NULL;
241 }
241 }
242
242
243 pkgpath = Py_BuildValue("[O]", fullpath);
243 pkgpath = Py_BuildValue("[O]", fullpath);
244 Py_DECREF(fullpath);
244 Py_DECREF(fullpath);
245 if (pkgpath == NULL) {
245 if (pkgpath == NULL) {
246 Py_DECREF(code);
246 Py_DECREF(code);
247 Py_DECREF(mod);
247 Py_DECREF(mod);
248 return NULL;
248 return NULL;
249 }
249 }
250 err = PyDict_SetItemString(dict, "__path__", pkgpath);
250 err = PyDict_SetItemString(dict, "__path__", pkgpath);
251 Py_DECREF(pkgpath);
251 Py_DECREF(pkgpath);
252 if (err != 0) {
252 if (err != 0) {
253 Py_DECREF(code);
253 Py_DECREF(code);
254 Py_DECREF(mod);
254 Py_DECREF(mod);
255 return NULL;
255 return NULL;
256 }
256 }
257 }
257 }
258
258 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
259 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
260
261 if (PythonQt::importInterface()) {
262 PythonQt::importInterface()->importedModule(fullname);
263 }
264
259 Py_DECREF(code);
265 Py_DECREF(code);
260 if (Py_VerboseFlag) {
266 if (Py_VerboseFlag) {
261 PySys_WriteStderr("import %s # loaded from %s\n",
267 PySys_WriteStderr("import %s # loaded from %s\n",
262 fullname, fullPath.toLatin1().constData());
268 fullname, fullPath.toLatin1().constData());
263 }
269 }
264 } else {
270 } else {
265 PythonQtObjectPtr imp;
271 PythonQtObjectPtr imp;
266 imp.setNewRef(PyImport_ImportModule("imp"));
272 imp.setNewRef(PyImport_ImportModule("imp"));
267
273
268 // Create a PyList with the current path as its single element,
274 // Create a PyList with the current path as its single element,
269 // which is required for find_module (it won't accept a tuple...)
275 // which is required for find_module (it won't accept a tuple...)
270 PythonQtObjectPtr pathList;
276 PythonQtObjectPtr pathList;
271 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
277 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
272
278
273 QVariantList args;
279 QVariantList args;
274 // Pass the module name without the package prefix
280 // Pass the module name without the package prefix
275 args.append(info.moduleName);
281 args.append(info.moduleName);
276 // And the path where we know that the shared library is
282 // And the path where we know that the shared library is
277 args.append(QVariant::fromValue(pathList));
283 args.append(QVariant::fromValue(pathList));
278 QVariant result = imp.call("find_module", args);
284 QVariant result = imp.call("find_module", args);
279 if (result.isValid()) {
285 if (result.isValid()) {
280 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
286 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
281 QVariantList list = result.toList();
287 QVariantList list = result.toList();
282 if (list.count()==3) {
288 if (list.count()==3) {
283 // We prepend the full module name (including package prefix)
289 // We prepend the full module name (including package prefix)
284 list.prepend(fullname);
290 list.prepend(fullname);
285 #ifdef __linux
291 #ifdef __linux
286 #ifdef _DEBUG
292 #ifdef _DEBUG
287 // imp_find_module() does not respect the debug suffix '_d' on Linux,
293 // imp_find_module() does not respect the debug suffix '_d' on Linux,
288 // so it does not return the correct file path and we correct it now
294 // so it does not return the correct file path and we correct it now
289 // find_module opened a file to the release library, but that file handle is
295 // find_module opened a file to the release library, but that file handle is
290 // ignored on Linux and Windows, maybe on MacOS also.
296 // ignored on Linux and Windows, maybe on MacOS also.
291 list[2] = info.fullPath;
297 list[2] = info.fullPath;
292 #endif
298 #endif
293 #endif
299 #endif
294 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
300 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
295 PythonQtObjectPtr module = imp.call("load_module", list);
301 PythonQtObjectPtr module = imp.call("load_module", list);
296 mod = module.object();
302 mod = module.object();
297 if (mod) {
303 if (mod) {
298 Py_INCREF(mod);
304 Py_INCREF(mod);
299 }
305 }
300
306
301 // Finally, we need to close the file again, which find_module opened for us
307 // Finally, we need to close the file again, which find_module opened for us
302 PythonQtObjectPtr file = list.at(1);
308 PythonQtObjectPtr file = list.at(1);
303 file.call("close");
309 file.call("close");
304 }
310 }
305 }
311 }
306 }
312 }
307 return mod;
313 return mod;
308 }
314 }
309
315
310
316
311 PyObject *
317 PyObject *
312 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
318 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
313 {
319 {
314 // EXTRA, NOT YET IMPLEMENTED
320 // EXTRA, NOT YET IMPLEMENTED
315 return NULL;
321 return NULL;
316 }
322 }
317
323
318 PyObject *
324 PyObject *
319 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
325 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
320 {
326 {
321 PythonQtImporter *self = (PythonQtImporter *)obj;
327 PythonQtImporter *self = (PythonQtImporter *)obj;
322 char *fullname;
328 char *fullname;
323
329
324 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
330 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
325 return NULL;
331 return NULL;
326
332
327 QString notused;
333 QString notused;
328 return PythonQtImport::getModuleCode(self, fullname, notused);
334 return PythonQtImport::getModuleCode(self, fullname, notused);
329 }
335 }
330
336
331 PyObject *
337 PyObject *
332 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
338 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
333 {
339 {
334 // EXTRA, NOT YET IMPLEMENTED
340 // EXTRA, NOT YET IMPLEMENTED
335 return NULL;
341 return NULL;
336 }
342 }
337
343
338 PyDoc_STRVAR(doc_find_module,
344 PyDoc_STRVAR(doc_find_module,
339 "find_module(fullname, path=None) -> self or None.\n\
345 "find_module(fullname, path=None) -> self or None.\n\
340 \n\
346 \n\
341 Search for a module specified by 'fullname'. 'fullname' must be the\n\
347 Search for a module specified by 'fullname'. 'fullname' must be the\n\
342 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
348 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
343 instance itself if the module was found, or None if it wasn't.\n\
349 instance itself if the module was found, or None if it wasn't.\n\
344 The optional 'path' argument is ignored -- it's there for compatibility\n\
350 The optional 'path' argument is ignored -- it's there for compatibility\n\
345 with the importer protocol.");
351 with the importer protocol.");
346
352
347 PyDoc_STRVAR(doc_load_module,
353 PyDoc_STRVAR(doc_load_module,
348 "load_module(fullname) -> module.\n\
354 "load_module(fullname) -> module.\n\
349 \n\
355 \n\
350 Load the module specified by 'fullname'. 'fullname' must be the\n\
356 Load the module specified by 'fullname'. 'fullname' must be the\n\
351 fully qualified (dotted) module name. It returns the imported\n\
357 fully qualified (dotted) module name. It returns the imported\n\
352 module, or raises PythonQtImportError if it wasn't found.");
358 module, or raises PythonQtImportError if it wasn't found.");
353
359
354 PyDoc_STRVAR(doc_get_data,
360 PyDoc_STRVAR(doc_get_data,
355 "get_data(pathname) -> string with file data.\n\
361 "get_data(pathname) -> string with file data.\n\
356 \n\
362 \n\
357 Return the data associated with 'pathname'. Raise IOError if\n\
363 Return the data associated with 'pathname'. Raise IOError if\n\
358 the file wasn't found.");
364 the file wasn't found.");
359
365
360 PyDoc_STRVAR(doc_get_code,
366 PyDoc_STRVAR(doc_get_code,
361 "get_code(fullname) -> code object.\n\
367 "get_code(fullname) -> code object.\n\
362 \n\
368 \n\
363 Return the code object for the specified module. Raise PythonQtImportError\n\
369 Return the code object for the specified module. Raise PythonQtImportError\n\
364 is the module couldn't be found.");
370 is the module couldn't be found.");
365
371
366 PyDoc_STRVAR(doc_get_source,
372 PyDoc_STRVAR(doc_get_source,
367 "get_source(fullname) -> source string.\n\
373 "get_source(fullname) -> source string.\n\
368 \n\
374 \n\
369 Return the source code for the specified module. Raise PythonQtImportError\n\
375 Return the source code for the specified module. Raise PythonQtImportError\n\
370 is the module couldn't be found, return None if the archive does\n\
376 is the module couldn't be found, return None if the archive does\n\
371 contain the module, but has no source for it.");
377 contain the module, but has no source for it.");
372
378
373 PyMethodDef PythonQtImporter_methods[] = {
379 PyMethodDef PythonQtImporter_methods[] = {
374 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
380 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
375 doc_find_module},
381 doc_find_module},
376 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
382 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
377 doc_load_module},
383 doc_load_module},
378 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
384 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
379 doc_get_data},
385 doc_get_data},
380 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
386 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
381 doc_get_code},
387 doc_get_code},
382 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
388 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
383 doc_get_source},
389 doc_get_source},
384 {NULL, NULL, 0 , NULL} /* sentinel */
390 {NULL, NULL, 0 , NULL} /* sentinel */
385 };
391 };
386
392
387
393
388 PyDoc_STRVAR(PythonQtImporter_doc,
394 PyDoc_STRVAR(PythonQtImporter_doc,
389 "PythonQtImporter(path) -> PythonQtImporter object\n\
395 "PythonQtImporter(path) -> PythonQtImporter object\n\
390 \n\
396 \n\
391 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
397 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
392 . Every path is accepted.");
398 . Every path is accepted.");
393
399
394 #define DEFERRED_ADDRESS(ADDR) 0
400 #define DEFERRED_ADDRESS(ADDR) 0
395
401
396 PyTypeObject PythonQtImporter_Type = {
402 PyTypeObject PythonQtImporter_Type = {
397 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
403 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
398 0,
404 0,
399 "PythonQtImport.PythonQtImporter",
405 "PythonQtImport.PythonQtImporter",
400 sizeof(PythonQtImporter),
406 sizeof(PythonQtImporter),
401 0, /* tp_itemsize */
407 0, /* tp_itemsize */
402 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
408 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
403 0, /* tp_print */
409 0, /* tp_print */
404 0, /* tp_getattr */
410 0, /* tp_getattr */
405 0, /* tp_setattr */
411 0, /* tp_setattr */
406 0, /* tp_compare */
412 0, /* tp_compare */
407 0, /* tp_repr */
413 0, /* tp_repr */
408 0, /* tp_as_number */
414 0, /* tp_as_number */
409 0, /* tp_as_sequence */
415 0, /* tp_as_sequence */
410 0, /* tp_as_mapping */
416 0, /* tp_as_mapping */
411 0, /* tp_hash */
417 0, /* tp_hash */
412 0, /* tp_call */
418 0, /* tp_call */
413 0, /* tp_str */
419 0, /* tp_str */
414 PyObject_GenericGetAttr, /* tp_getattro */
420 PyObject_GenericGetAttr, /* tp_getattro */
415 0, /* tp_setattro */
421 0, /* tp_setattro */
416 0, /* tp_as_buffer */
422 0, /* tp_as_buffer */
417 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
423 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
418 PythonQtImporter_doc, /* tp_doc */
424 PythonQtImporter_doc, /* tp_doc */
419 0, /* tp_traverse */
425 0, /* tp_traverse */
420 0, /* tp_clear */
426 0, /* tp_clear */
421 0, /* tp_richcompare */
427 0, /* tp_richcompare */
422 0, /* tp_weaklistoffset */
428 0, /* tp_weaklistoffset */
423 0, /* tp_iter */
429 0, /* tp_iter */
424 0, /* tp_iternext */
430 0, /* tp_iternext */
425 PythonQtImporter_methods, /* tp_methods */
431 PythonQtImporter_methods, /* tp_methods */
426 0, /* tp_members */
432 0, /* tp_members */
427 0, /* tp_getset */
433 0, /* tp_getset */
428 0, /* tp_base */
434 0, /* tp_base */
429 0, /* tp_dict */
435 0, /* tp_dict */
430 0, /* tp_descr_get */
436 0, /* tp_descr_get */
431 0, /* tp_descr_set */
437 0, /* tp_descr_set */
432 0, /* tp_dictoffset */
438 0, /* tp_dictoffset */
433 (initproc)PythonQtImporter_init, /* tp_init */
439 (initproc)PythonQtImporter_init, /* tp_init */
434 PyType_GenericAlloc, /* tp_alloc */
440 PyType_GenericAlloc, /* tp_alloc */
435 PyType_GenericNew, /* tp_new */
441 PyType_GenericNew, /* tp_new */
436 PyObject_Del, /* tp_free */
442 PyObject_Del, /* tp_free */
437 };
443 };
438
444
439
445
440 /* Given a buffer, return the long that is represented by the first
446 /* Given a buffer, return the long that is represented by the first
441 4 bytes, encoded as little endian. This partially reimplements
447 4 bytes, encoded as little endian. This partially reimplements
442 marshal.c:r_long() */
448 marshal.c:r_long() */
443 long
449 long
444 PythonQtImport::getLong(unsigned char *buf)
450 PythonQtImport::getLong(unsigned char *buf)
445 {
451 {
446 long x;
452 long x;
447 x = buf[0];
453 x = buf[0];
448 x |= (long)buf[1] << 8;
454 x |= (long)buf[1] << 8;
449 x |= (long)buf[2] << 16;
455 x |= (long)buf[2] << 16;
450 x |= (long)buf[3] << 24;
456 x |= (long)buf[3] << 24;
451 #if SIZEOF_LONG > 4
457 #if SIZEOF_LONG > 4
452 /* Sign extension for 64-bit machines */
458 /* Sign extension for 64-bit machines */
453 x |= -(x & 0x80000000L);
459 x |= -(x & 0x80000000L);
454 #endif
460 #endif
455 return x;
461 return x;
456 }
462 }
457
463
458 FILE *
464 FILE *
459 open_exclusive(const QString& filename)
465 open_exclusive(const QString& filename)
460 {
466 {
461 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
467 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
462 /* Use O_EXCL to avoid a race condition when another process tries to
468 /* Use O_EXCL to avoid a race condition when another process tries to
463 write the same file. When that happens, our open() call fails,
469 write the same file. When that happens, our open() call fails,
464 which is just fine (since it's only a cache).
470 which is just fine (since it's only a cache).
465 XXX If the file exists and is writable but the directory is not
471 XXX If the file exists and is writable but the directory is not
466 writable, the file will never be written. Oh well.
472 writable, the file will never be written. Oh well.
467 */
473 */
468 QFile::remove(filename);
474 QFile::remove(filename);
469
475
470 int fd;
476 int fd;
471 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
477 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
472 #ifdef O_BINARY
478 #ifdef O_BINARY
473 flags |= O_BINARY; /* necessary for Windows */
479 flags |= O_BINARY; /* necessary for Windows */
474 #endif
480 #endif
475 #ifdef WIN32
481 #ifdef WIN32
476 fd = _wopen(filename.ucs2(), flags, 0666);
482 fd = _wopen(filename.ucs2(), flags, 0666);
477 #else
483 #else
478 fd = open(filename.local8Bit(), flags, 0666);
484 fd = open(filename.local8Bit(), flags, 0666);
479 #endif
485 #endif
480 if (fd < 0)
486 if (fd < 0)
481 return NULL;
487 return NULL;
482 return fdopen(fd, "wb");
488 return fdopen(fd, "wb");
483 #else
489 #else
484 /* Best we can do -- on Windows this can't happen anyway */
490 /* Best we can do -- on Windows this can't happen anyway */
485 return fopen(filename.toLocal8Bit().constData(), "wb");
491 return fopen(filename.toLocal8Bit().constData(), "wb");
486 #endif
492 #endif
487 }
493 }
488
494
489
495
490 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
496 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
491 {
497 {
492 FILE *fp;
498 FILE *fp;
493 // we do not want to write Qt resources to disk, do we?
499 // we do not want to write Qt resources to disk, do we?
494 if (filename.startsWith(":")) {
500 if (filename.startsWith(":")) {
495 return;
501 return;
496 }
502 }
497 fp = open_exclusive(filename);
503 fp = open_exclusive(filename);
498 if (fp == NULL) {
504 if (fp == NULL) {
499 if (Py_VerboseFlag)
505 if (Py_VerboseFlag)
500 PySys_WriteStderr(
506 PySys_WriteStderr(
501 "# can't create %s\n", filename.toLatin1().constData());
507 "# can't create %s\n", filename.toLatin1().constData());
502 return;
508 return;
503 }
509 }
504 #if PY_VERSION_HEX < 0x02040000
510 #if PY_VERSION_HEX < 0x02040000
505 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
511 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
506 #else
512 #else
507 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
513 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
508 #endif
514 #endif
509 /* First write a 0 for mtime */
515 /* First write a 0 for mtime */
510 #if PY_VERSION_HEX < 0x02040000
516 #if PY_VERSION_HEX < 0x02040000
511 PyMarshal_WriteLongToFile(0L, fp);
517 PyMarshal_WriteLongToFile(0L, fp);
512 #else
518 #else
513 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
519 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
514 #endif
520 #endif
515 #if PY_VERSION_HEX < 0x02040000
521 #if PY_VERSION_HEX < 0x02040000
516 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
522 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
517 #else
523 #else
518 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
524 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
519 #endif
525 #endif
520 if (ferror(fp)) {
526 if (ferror(fp)) {
521 if (Py_VerboseFlag)
527 if (Py_VerboseFlag)
522 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
528 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
523 /* Don't keep partial file */
529 /* Don't keep partial file */
524 fclose(fp);
530 fclose(fp);
525 QFile::remove(filename);
531 QFile::remove(filename);
526 return;
532 return;
527 }
533 }
528 /* Now write the true mtime */
534 /* Now write the true mtime */
529 fseek(fp, 4L, 0);
535 fseek(fp, 4L, 0);
530 #if PY_VERSION_HEX < 0x02040000
536 #if PY_VERSION_HEX < 0x02040000
531 PyMarshal_WriteLongToFile(mtime, fp);
537 PyMarshal_WriteLongToFile(mtime, fp);
532 #else
538 #else
533 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
539 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
534 #endif
540 #endif
535 fflush(fp);
541 fflush(fp);
536 fclose(fp);
542 fclose(fp);
537 if (Py_VerboseFlag)
543 if (Py_VerboseFlag)
538 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
544 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
539 //#ifdef macintosh
545 //#ifdef macintosh
540 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
546 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
541 //#endif
547 //#endif
542 }
548 }
543
549
544 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
550 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
545 and return the code object. Return None if it the magic word doesn't
551 and return the code object. Return None if it the magic word doesn't
546 match (we do this instead of raising an exception as we fall back
552 match (we do this instead of raising an exception as we fall back
547 to .py if available and we don't want to mask other errors).
553 to .py if available and we don't want to mask other errors).
548 Returns a new reference. */
554 Returns a new reference. */
549 PyObject *
555 PyObject *
550 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
556 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
551 {
557 {
552 PyObject *code;
558 PyObject *code;
553 // ugly cast, but Python API is not const safe
559 // ugly cast, but Python API is not const safe
554 char *buf = (char*) data.constData();
560 char *buf = (char*) data.constData();
555 int size = data.size();
561 int size = data.size();
556
562
557 if (size <= 9) {
563 if (size <= 9) {
558 PySys_WriteStderr("# %s has bad pyc data\n",
564 PySys_WriteStderr("# %s has bad pyc data\n",
559 path.toLatin1().constData());
565 path.toLatin1().constData());
560 Py_INCREF(Py_None);
566 Py_INCREF(Py_None);
561 return Py_None;
567 return Py_None;
562 }
568 }
563
569
564 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
570 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
565 if (Py_VerboseFlag)
571 if (Py_VerboseFlag)
566 PySys_WriteStderr("# %s has bad magic\n",
572 PySys_WriteStderr("# %s has bad magic\n",
567 path.toLatin1().constData());
573 path.toLatin1().constData());
568 Py_INCREF(Py_None);
574 Py_INCREF(Py_None);
569 return Py_None;
575 return Py_None;
570 }
576 }
571
577
572 if (mtime != 0) {
578 if (mtime != 0) {
573 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
579 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
574 if (timeDiff<0) { timeDiff = -timeDiff; }
580 if (timeDiff<0) { timeDiff = -timeDiff; }
575 if (timeDiff > 1) {
581 if (timeDiff > 1) {
576 if (Py_VerboseFlag)
582 if (Py_VerboseFlag)
577 PySys_WriteStderr("# %s has bad mtime\n",
583 PySys_WriteStderr("# %s has bad mtime\n",
578 path.toLatin1().constData());
584 path.toLatin1().constData());
579 Py_INCREF(Py_None);
585 Py_INCREF(Py_None);
580 return Py_None;
586 return Py_None;
581 }
587 }
582 }
588 }
583
589
584 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
590 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
585 if (code == NULL)
591 if (code == NULL)
586 return NULL;
592 return NULL;
587 if (!PyCode_Check(code)) {
593 if (!PyCode_Check(code)) {
588 Py_DECREF(code);
594 Py_DECREF(code);
589 PyErr_Format(PyExc_TypeError,
595 PyErr_Format(PyExc_TypeError,
590 "compiled module %.200s is not a code object",
596 "compiled module %.200s is not a code object",
591 path.toLatin1().constData());
597 path.toLatin1().constData());
592 return NULL;
598 return NULL;
593 }
599 }
594 return code;
600 return code;
595 }
601 }
596
602
597
603
598 /* Given a string buffer containing Python source code, compile it
604 /* Given a string buffer containing Python source code, compile it
599 return and return a code object as a new reference. */
605 return and return a code object as a new reference. */
600 PyObject *
606 PyObject *
601 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
607 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
602 {
608 {
603 PyObject *code;
609 PyObject *code;
604 QByteArray data1 = data;
610 QByteArray data1 = data;
605 // in qt4, data is null terminated
611 // in qt4, data is null terminated
606 // data1.resize(data.size()+1);
612 // data1.resize(data.size()+1);
607 // data1.data()[data.size()-1] = 0;
613 // data1.data()[data.size()-1] = 0;
608 code = Py_CompileString(data.data(), path.toLatin1().constData(),
614 code = Py_CompileString(data.data(), path.toLatin1().constData(),
609 Py_file_input);
615 Py_file_input);
610 return code;
616 return code;
611 }
617 }
612
618
613
619
614 /* Return the code object for the module named by 'fullname' from the
620 /* Return the code object for the module named by 'fullname' from the
615 Zip archive as a new reference. */
621 Zip archive as a new reference. */
616 PyObject *
622 PyObject *
617 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
623 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
618 {
624 {
619 PyObject *code;
625 PyObject *code;
620
626
621 QByteArray qdata;
627 QByteArray qdata;
622 if (!isbytecode) {
628 if (!isbytecode) {
623 // mlabDebugConst("MLABPython", "reading source " << path);
629 // mlabDebugConst("MLABPython", "reading source " << path);
624 bool ok;
630 bool ok;
625 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
631 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
626 if (!ok) {
632 if (!ok) {
627 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
633 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
628 return NULL;
634 return NULL;
629 }
635 }
630 if (qdata == " ") {
636 if (qdata == " ") {
631 qdata.clear();
637 qdata.clear();
632 }
638 }
633 } else {
639 } else {
634 qdata = PythonQt::importInterface()->readFileAsBytes(path);
640 qdata = PythonQt::importInterface()->readFileAsBytes(path);
635 }
641 }
636
642
637 if (isbytecode) {
643 if (isbytecode) {
638 // mlabDebugConst("MLABPython", "reading bytecode " << path);
644 // mlabDebugConst("MLABPython", "reading bytecode " << path);
639 code = unmarshalCode(path, qdata, mtime);
645 code = unmarshalCode(path, qdata, mtime);
640 }
646 }
641 else {
647 else {
642 // mlabDebugConst("MLABPython", "compiling source " << path);
648 // mlabDebugConst("MLABPython", "compiling source " << path);
643 code = compileSource(path, qdata);
649 code = compileSource(path, qdata);
644 if (code) {
650 if (code) {
645 // save a pyc file if possible
651 // save a pyc file if possible
646 QDateTime time;
652 QDateTime time;
647 time = PythonQt::importInterface()->lastModifiedDate(path);
653 time = PythonQt::importInterface()->lastModifiedDate(path);
648 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
654 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
649 }
655 }
650 }
656 }
651 return code;
657 return code;
652 }
658 }
653
659
654 time_t
660 time_t
655 PythonQtImport::getMTimeOfSource(const QString& path)
661 PythonQtImport::getMTimeOfSource(const QString& path)
656 {
662 {
657 time_t mtime = 0;
663 time_t mtime = 0;
658 QString path2 = path;
664 QString path2 = path;
659 path2.truncate(path.length()-1);
665 path2.truncate(path.length()-1);
660
666
661 if (PythonQt::importInterface()->exists(path2)) {
667 if (PythonQt::importInterface()->exists(path2)) {
662 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
668 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
663 if (t.isValid()) {
669 if (t.isValid()) {
664 mtime = t.toTime_t();
670 mtime = t.toTime_t();
665 }
671 }
666 }
672 }
667
673
668 return mtime;
674 return mtime;
669 }
675 }
670
676
671 /* Get the code object associated with the module specified by
677 /* Get the code object associated with the module specified by
672 'fullname'. */
678 'fullname'. */
673 PyObject *
679 PyObject *
674 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
680 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
675 {
681 {
676 QString subname;
682 QString subname;
677 struct st_mlab_searchorder *zso;
683 struct st_mlab_searchorder *zso;
678
684
679 subname = getSubName(fullname);
685 subname = getSubName(fullname);
680 QString path = *self->_path + "/" + subname;
686 QString path = *self->_path + "/" + subname;
681
687
682 QString test;
688 QString test;
683 for (zso = mlab_searchorder; *zso->suffix; zso++) {
689 for (zso = mlab_searchorder; *zso->suffix; zso++) {
684 PyObject *code = NULL;
690 PyObject *code = NULL;
685 test = path + zso->suffix;
691 test = path + zso->suffix;
686
692
687 if (Py_VerboseFlag > 1)
693 if (Py_VerboseFlag > 1)
688 PySys_WriteStderr("# trying %s\n",
694 PySys_WriteStderr("# trying %s\n",
689 test.toLatin1().constData());
695 test.toLatin1().constData());
690 if (PythonQt::importInterface()->exists(test)) {
696 if (PythonQt::importInterface()->exists(test)) {
691 time_t mtime = 0;
697 time_t mtime = 0;
692 int ispackage = zso->type & IS_PACKAGE;
698 int ispackage = zso->type & IS_PACKAGE;
693 int isbytecode = zso->type & IS_BYTECODE;
699 int isbytecode = zso->type & IS_BYTECODE;
694
700
695 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
701 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
696 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
702 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
697 // even if a newer *.py file exists. This is a release optimization where
703 // even if a newer *.py file exists. This is a release optimization where
698 // typically only *.pyc files are delivered without *.py files and reading file
704 // typically only *.pyc files are delivered without *.py files and reading file
699 // modification time is slow.
705 // modification time is slow.
700 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
706 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
701 mtime = getMTimeOfSource(test);
707 mtime = getMTimeOfSource(test);
702 }
708 }
703 code = getCodeFromData(test, isbytecode, ispackage, mtime);
709 code = getCodeFromData(test, isbytecode, ispackage, mtime);
704 if (code == Py_None) {
710 if (code == Py_None) {
705 Py_DECREF(code);
711 Py_DECREF(code);
706 continue;
712 continue;
707 }
713 }
708 if (code != NULL) {
714 if (code != NULL) {
709 modpath = test;
715 modpath = test;
710 }
716 }
711 return code;
717 return code;
712 }
718 }
713 }
719 }
714 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
720 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
715
721
716 return NULL;
722 return NULL;
717 }
723 }
718
724
719 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
725 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
720 {
726 {
721 QString r;
727 QString r;
722 int i = str.lastIndexOf('.');
728 int i = str.lastIndexOf('.');
723 if (i!=-1) {
729 if (i!=-1) {
724 r = str.mid(0,i) + "." + ext;
730 r = str.mid(0,i) + "." + ext;
725 } else {
731 } else {
726 r = str + "." + ext;
732 r = str + "." + ext;
727 }
733 }
728 return r;
734 return r;
729 }
735 }
730
736
731 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
737 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
732 {
738 {
733 PyObject* code;
739 PyObject* code;
734 const static QString pycStr("pyc");
740 const static QString pycStr("pyc");
735 QString pyc = replaceExtension(file, pycStr);
741 QString pyc = replaceExtension(file, pycStr);
736 if (PythonQt::importInterface()->exists(pyc)) {
742 if (PythonQt::importInterface()->exists(pyc)) {
737 time_t mtime = 0;
743 time_t mtime = 0;
738 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
744 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
739 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
745 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
740 // even if a newer *.py file exists. This is a release optimization where
746 // even if a newer *.py file exists. This is a release optimization where
741 // typically only *.pyc files are delivered without *.py files and reading file
747 // typically only *.pyc files are delivered without *.py files and reading file
742 // modification time is slow.
748 // modification time is slow.
743 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
749 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
744 mtime = getMTimeOfSource(pyc);
750 mtime = getMTimeOfSource(pyc);
745 }
751 }
746 code = getCodeFromData(pyc, true, false, mtime);
752 code = getCodeFromData(pyc, true, false, mtime);
747 if (code != Py_None && code != NULL) {
753 if (code != Py_None && code != NULL) {
748 return code;
754 return code;
749 }
755 }
750 if (code) {
756 if (code) {
751 Py_DECREF(code);
757 Py_DECREF(code);
752 }
758 }
753 }
759 }
754 code = getCodeFromData(file,false,false,0);
760 code = getCodeFromData(file,false,false,0);
755 return code;
761 return code;
756 }
762 }
757
763
758 /* Module init */
764 /* Module init */
759
765
760 PyDoc_STRVAR(mlabimport_doc,
766 PyDoc_STRVAR(mlabimport_doc,
761 "Imports python files into PythonQt, completely replaces internal python import");
767 "Imports python files into PythonQt, completely replaces internal python import");
762
768
763 void PythonQtImport::init()
769 void PythonQtImport::init()
764 {
770 {
765 static bool first = true;
771 static bool first = true;
766 if (!first) {
772 if (!first) {
767 return;
773 return;
768 }
774 }
769 first = false;
775 first = false;
770
776
771 PyObject *mod;
777 PyObject *mod;
772
778
773 if (PyType_Ready(&PythonQtImporter_Type) < 0)
779 if (PyType_Ready(&PythonQtImporter_Type) < 0)
774 return;
780 return;
775
781
776 /* Correct directory separator */
782 /* Correct directory separator */
777 mlab_searchorder[0].suffix[0] = SEP;
783 mlab_searchorder[0].suffix[0] = SEP;
778 mlab_searchorder[1].suffix[0] = SEP;
784 mlab_searchorder[1].suffix[0] = SEP;
779 mlab_searchorder[2].suffix[0] = SEP;
785 mlab_searchorder[2].suffix[0] = SEP;
780 if (Py_OptimizeFlag) {
786 if (Py_OptimizeFlag) {
781 /* Reverse *.pyc and *.pyo */
787 /* Reverse *.pyc and *.pyo */
782 struct st_mlab_searchorder tmp;
788 struct st_mlab_searchorder tmp;
783 tmp = mlab_searchorder[0];
789 tmp = mlab_searchorder[0];
784 mlab_searchorder[0] = mlab_searchorder[1];
790 mlab_searchorder[0] = mlab_searchorder[1];
785 mlab_searchorder[1] = tmp;
791 mlab_searchorder[1] = tmp;
786 tmp = mlab_searchorder[3];
792 tmp = mlab_searchorder[3];
787 mlab_searchorder[3] = mlab_searchorder[4];
793 mlab_searchorder[3] = mlab_searchorder[4];
788 mlab_searchorder[4] = tmp;
794 mlab_searchorder[4] = tmp;
789 }
795 }
790
796
791 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
797 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
792 NULL, PYTHON_API_VERSION);
798 NULL, PYTHON_API_VERSION);
793
799
794 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
800 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
795 PyExc_ImportError, NULL);
801 PyExc_ImportError, NULL);
796 if (PythonQtImportError == NULL)
802 if (PythonQtImportError == NULL)
797 return;
803 return;
798
804
799 Py_INCREF(PythonQtImportError);
805 Py_INCREF(PythonQtImportError);
800 if (PyModule_AddObject(mod, "PythonQtImportError",
806 if (PyModule_AddObject(mod, "PythonQtImportError",
801 PythonQtImportError) < 0)
807 PythonQtImportError) < 0)
802 return;
808 return;
803
809
804 Py_INCREF(&PythonQtImporter_Type);
810 Py_INCREF(&PythonQtImporter_Type);
805 if (PyModule_AddObject(mod, "PythonQtImporter",
811 if (PyModule_AddObject(mod, "PythonQtImporter",
806 (PyObject *)&PythonQtImporter_Type) < 0)
812 (PyObject *)&PythonQtImporter_Type) < 0)
807 return;
813 return;
808
814
809 // set our importer into the path_hooks to handle all path on sys.path
815 // set our importer into the path_hooks to handle all path on sys.path
810 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
816 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
811 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
817 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
812 PyList_Append(path_hooks, classobj);
818 PyList_Append(path_hooks, classobj);
813
819
814 #ifndef WIN32
820 #ifndef WIN32
815 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
821 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
816 PyObject* modules = PyImport_GetModuleDict();
822 PyObject* modules = PyImport_GetModuleDict();
817 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
823 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
818 if (encodingsModule != NULL) {
824 if (encodingsModule != NULL) {
819 PyImport_ReloadModule(encodingsModule);
825 PyImport_ReloadModule(encodingsModule);
820 }
826 }
821 #endif
827 #endif
822 }
828 }
@@ -1,766 +1,774
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtSignal.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
49 #include "PythonQtClassWrapper.h"
49
50
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 {
52 {
52 // take the class info from our type object
53 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
55 }
55
56
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
58
58 // is this a C++ wrapper?
59 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
60 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
62
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
64 // we own our qobject, so we delete it now:
64 delete self->_obj;
65 delete self->_obj;
65 self->_obj = NULL;
66 self->_obj = NULL;
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 int type = self->classInfo()->metaTypeId();
68 int type = self->classInfo()->metaTypeId();
68 if (self->_useQMetaTypeDestroy && type>=0) {
69 if (self->_useQMetaTypeDestroy && type>=0) {
69 // use QMetaType to destroy the object
70 // use QMetaType to destroy the object
70 QMetaType::destroy(type, self->_wrappedPtr);
71 QMetaType::destroy(type, self->_wrappedPtr);
71 } else {
72 } else {
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 if (slot) {
74 if (slot) {
74 void* args[2];
75 void* args[2];
75 args[0] = NULL;
76 args[0] = NULL;
76 args[1] = &self->_wrappedPtr;
77 args[1] = &self->_wrappedPtr;
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 self->_wrappedPtr = NULL;
79 self->_wrappedPtr = NULL;
79 } else {
80 } else {
80 if (type>=0) {
81 if (type>=0) {
81 // use QMetaType to destroy the object
82 // use QMetaType to destroy the object
82 QMetaType::destroy(type, self->_wrappedPtr);
83 QMetaType::destroy(type, self->_wrappedPtr);
83 } else {
84 } else {
84 // TODO: warn about not being able to destroy the object?
85 // TODO: warn about not being able to destroy the object?
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 }
89 } else {
90 } else {
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 if (self->_objPointerCopy) {
92 if (self->_objPointerCopy) {
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 }
94 }
94 if (self->_obj) {
95 if (self->_obj) {
95 if (force || self->_ownedByPythonQt) {
96 if (force || self->_ownedByPythonQt) {
96 if (force || !self->_obj->parent()) {
97 if (force || !self->_obj->parent()) {
97 delete self->_obj;
98 delete self->_obj;
98 }
99 }
99 } else {
100 } else {
100 if (self->_obj->parent()==NULL) {
101 if (self->_obj->parent()==NULL) {
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 }
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 self->_obj = NULL;
108 self->_obj = NULL;
108 }
109 }
109
110
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 {
112 {
112 PythonQtInstanceWrapper_deleteObject(self);
113 PythonQtInstanceWrapper_deleteObject(self);
113 self->_obj.~QPointer<QObject>();
114 self->_obj.~QPointer<QObject>();
114 self->ob_type->tp_free((PyObject*)self);
115 self->ob_type->tp_free((PyObject*)self);
115 }
116 }
116
117
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 {
119 {
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
121 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
122 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
123 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
124 emptyTuple = PyTuple_New(0);
124 }
125 }
125
126
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127
128
128 if (self != NULL) {
129 if (self != NULL) {
129 new (&self->_obj) QPointer<QObject>();
130 new (&self->_obj) QPointer<QObject>();
130 self->_wrappedPtr = NULL;
131 self->_wrappedPtr = NULL;
131 self->_ownedByPythonQt = false;
132 self->_ownedByPythonQt = false;
132 self->_useQMetaTypeDestroy = false;
133 self->_useQMetaTypeDestroy = false;
133 self->_isShellInstance = false;
134 self->_isShellInstance = false;
134 }
135 }
135 return (PyObject *)self;
136 return (PyObject *)self;
136 }
137 }
137
138
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 {
140 {
140 if (args == PythonQtPrivate::dummyTuple()) {
141 if (args == PythonQtPrivate::dummyTuple()) {
141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 // we are called from the internal PythonQt API, so our data will be filled later on...
142 return 0;
143 return 0;
143 }
144 }
144
145
145 // we are called from python, try to construct our object
146 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
147 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
148 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
150 if (PyErr_Occurred()) {
150 return -1;
151 return -1;
151 }
152 }
152 if (directCPPPointer) {
153 if (directCPPPointer) {
153 // change ownershipflag to be owned by PythonQt
154 // change ownershipflag to be owned by PythonQt
154 self->_ownedByPythonQt = true;
155 self->_ownedByPythonQt = true;
155 self->_useQMetaTypeDestroy = false;
156 self->_useQMetaTypeDestroy = false;
156 if (self->classInfo()->isCPPWrapper()) {
157 if (self->classInfo()->isCPPWrapper()) {
157 self->_wrappedPtr = directCPPPointer;
158 self->_wrappedPtr = directCPPPointer;
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 } else {
160 } else {
160 self->setQObject((QObject*)directCPPPointer);
161 self->setQObject((QObject*)directCPPPointer);
161 }
162 }
162 // register with PythonQt
163 // register with PythonQt
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164
165
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 if (cb) {
167 if (cb) {
167 // if we are a derived python class, we set the wrapper
168 // if we are a derived python class, we set the wrapper
168 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // which is the case for all non-python derived types
171 // which is the case for all non-python derived types
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 // set the wrapper and remember that we have a shell instance!
173 // set the wrapper and remember that we have a shell instance!
173 (*cb)(directCPPPointer, self);
174 (*cb)(directCPPPointer, self);
174 self->_isShellInstance = true;
175 self->_isShellInstance = true;
175 }
176 }
176 }
177 }
177 }
178 }
178 } else {
179 } else {
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 return -1;
182 return -1;
182 }
183 }
183 return 0;
184 return 0;
184 }
185 }
185
186
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 {
188 {
188 bool validPtrs = false;
189 bool validPtrs = false;
189 bool areSamePtrs = false;
190 bool areSamePtrs = false;
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 validPtrs = true;
193 validPtrs = true;
193 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 // check pointers directly
196 // check pointers directly
196 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 areSamePtrs = true;
199 areSamePtrs = true;
199 }
200 }
200 } else if (w1->_obj == w2->_obj) {
201 } else if (w1->_obj == w2->_obj) {
201 areSamePtrs = true;
202 areSamePtrs = true;
202 }
203 }
203 } else if (other == Py_None) {
204 } else if (other == Py_None) {
204 validPtrs = true;
205 validPtrs = true;
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 areSamePtrs = false;
207 areSamePtrs = false;
207 } else {
208 } else {
208 areSamePtrs = true;
209 areSamePtrs = true;
209 }
210 }
210 }
211 }
211 }
212 }
212
213
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 // shortcut if richcompare is not supported:
215 // shortcut if richcompare is not supported:
215 if (validPtrs && code == Py_EQ) {
216 if (validPtrs && code == Py_EQ) {
216 return PythonQtConv::GetPyBool(areSamePtrs);
217 return PythonQtConv::GetPyBool(areSamePtrs);
217 } else if (validPtrs && code == Py_NE) {
218 } else if (validPtrs && code == Py_NE) {
218 return PythonQtConv::GetPyBool(!areSamePtrs);
219 return PythonQtConv::GetPyBool(!areSamePtrs);
219 }
220 }
220 Py_INCREF(Py_NotImplemented);
221 Py_INCREF(Py_NotImplemented);
221 return Py_NotImplemented;
222 return Py_NotImplemented;
222 }
223 }
223
224
224 QByteArray memberName;
225 QByteArray memberName;
225 switch (code) {
226 switch (code) {
226 case Py_LT:
227 case Py_LT:
227 {
228 {
228 static QByteArray name = "__lt__";
229 static QByteArray name = "__lt__";
229 memberName = name;
230 memberName = name;
230 }
231 }
231 break;
232 break;
232
233
233 case Py_LE:
234 case Py_LE:
234 {
235 {
235 static QByteArray name = "__le__";
236 static QByteArray name = "__le__";
236 memberName = name;
237 memberName = name;
237 }
238 }
238 break;
239 break;
239
240
240 case Py_EQ:
241 case Py_EQ:
241 {
242 {
242 static QByteArray name = "__eq__";
243 static QByteArray name = "__eq__";
243 memberName = name;
244 memberName = name;
244 }
245 }
245 break;
246 break;
246
247
247 case Py_NE:
248 case Py_NE:
248 {
249 {
249 static QByteArray name = "__ne__";
250 static QByteArray name = "__ne__";
250 memberName = name;
251 memberName = name;
251 }
252 }
252 break;
253 break;
253
254
254 case Py_GT:
255 case Py_GT:
255 {
256 {
256 static QByteArray name = "__gt__";
257 static QByteArray name = "__gt__";
257 memberName = name;
258 memberName = name;
258 }
259 }
259 break;
260 break;
260
261
261 case Py_GE:
262 case Py_GE:
262 {
263 {
263 static QByteArray name = "__ge__";
264 static QByteArray name = "__ge__";
264 memberName = name;
265 memberName = name;
265 }
266 }
266 break;
267 break;
267 }
268 }
268
269
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 // TODO get rid of tuple
272 // TODO get rid of tuple
272 PyObject* args = PyTuple_New(1);
273 PyObject* args = PyTuple_New(1);
273 Py_INCREF(other);
274 Py_INCREF(other);
274 PyTuple_SET_ITEM(args, 0, other);
275 PyTuple_SET_ITEM(args, 0, other);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 Py_DECREF(args);
277 Py_DECREF(args);
277 return result;
278 return result;
278 } else {
279 } else {
279 // not implemented, let python try something else!
280 // not implemented, let python try something else!
280 Py_INCREF(Py_NotImplemented);
281 Py_INCREF(Py_NotImplemented);
281 return Py_NotImplemented;
282 return Py_NotImplemented;
282 }
283 }
283 }
284 }
284
285
285
286
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 {
288 {
288 return PyString_FromString(obj->ob_type->tp_name);
289 return PyString_FromString(obj->ob_type->tp_name);
289 }
290 }
290
291
291 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
292 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
292 {
293 {
293 char *name = NULL;
294 char *name = NULL;
294 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
295 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
295 return NULL;
296 return NULL;
296 }
297 }
297 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
298 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
298 }
299 }
299
300
300 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
301 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
301 {
302 {
302 return PythonQt::self()->helpCalled(obj->classInfo());
303 return PythonQt::self()->helpCalled(obj->classInfo());
303 }
304 }
304
305
305 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
306 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
306 {
307 {
307 PythonQtInstanceWrapper_deleteObject(self, true);
308 PythonQtInstanceWrapper_deleteObject(self, true);
308 Py_INCREF(Py_None);
309 Py_INCREF(Py_None);
309 return Py_None;
310 return Py_None;
310 }
311 }
311
312
312
313
313 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
314 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
314 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
315 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
315 "Return the classname of the object"
316 "Return the classname of the object"
316 },
317 },
317 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
318 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
318 "Returns if the class inherits or is of given type name"
319 "Returns if the class inherits or is of given type name"
319 },
320 },
320 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
321 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
321 "Shows the help of available methods for this class"
322 "Shows the help of available methods for this class"
322 },
323 },
323 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
324 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
324 "Deletes the C++ object (at your own risk, my friend!)"
325 "Deletes the C++ object (at your own risk, my friend!)"
325 },
326 },
326 {NULL, NULL, 0, NULL} /* Sentinel */
327 {NULL, NULL, 0, NULL} /* Sentinel */
327 };
328 };
328
329
329
330
330 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
331 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
331 {
332 {
332 const char *attributeName;
333 const char *attributeName;
333 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
334 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
334
335
335 if ((attributeName = PyString_AsString(name)) == NULL) {
336 if ((attributeName = PyString_AsString(name)) == NULL) {
336 return NULL;
337 return NULL;
337 }
338 }
338
339
339 if (qstrcmp(attributeName, "__dict__")==0) {
340 if (qstrcmp(attributeName, "__dict__")==0) {
340 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
341 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
341 dict = PyDict_Copy(dict);
342 dict = PyDict_Copy(dict);
342
343
343 if (wrapper->_obj) {
344 if (wrapper->_obj) {
344 // only the properties are missing, the rest is already available from
345 // only the properties are missing, the rest is already available from
345 // PythonQtClassWrapper...
346 // PythonQtClassWrapper...
346 QStringList l = wrapper->classInfo()->propertyList();
347 QStringList l = wrapper->classInfo()->propertyList();
347 foreach (QString name, l) {
348 foreach (QString name, l) {
348 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
349 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
349 if (o) {
350 if (o) {
350 PyDict_SetItemString(dict, name.toLatin1().data(), o);
351 PyDict_SetItemString(dict, name.toLatin1().data(), o);
351 Py_DECREF(o);
352 Py_DECREF(o);
352 } else {
353 } else {
353 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
354 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
354 }
355 }
355 }
356 }
356
357
357 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
358 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
358 foreach (QByteArray name, dynamicProps) {
359 foreach (QByteArray name, dynamicProps) {
359 PyObject* o = PyObject_GetAttrString(obj, name.data());
360 PyObject* o = PyObject_GetAttrString(obj, name.data());
360 if (o) {
361 if (o) {
361 PyDict_SetItemString(dict, name.data(), o);
362 PyDict_SetItemString(dict, name.data(), o);
362 Py_DECREF(o);
363 Py_DECREF(o);
363 } else {
364 } else {
364 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
365 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
365 }
366 }
366 }
367 }
367 }
368 }
368 // Note: we do not put children into the dict, is would look confusing?!
369 // Note: we do not put children into the dict, is would look confusing?!
369 return dict;
370 return dict;
370 }
371 }
371
372
372 // first look in super, to return derived methods from base object first
373 // first look in super, to return derived methods from base object first
373 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
374 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
374 if (superAttr) {
375 if (superAttr) {
375 return superAttr;
376 return superAttr;
376 }
377 }
377 PyErr_Clear();
378 PyErr_Clear();
378
379
379 // mlabDebugConst("Python","get " << attributeName);
380 // mlabDebugConst("Python","get " << attributeName);
380
381
381 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
382 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
382 switch (member._type) {
383 switch (member._type) {
383 case PythonQtMemberInfo::Property:
384 case PythonQtMemberInfo::Property:
384 if (wrapper->_obj) {
385 if (wrapper->_obj) {
385 if (member._property.userType() != QVariant::Invalid) {
386 if (member._property.userType() != QVariant::Invalid) {
386
387
387 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
388 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
388 if (profilingCB) {
389 if (profilingCB) {
389 QString methodName = "getProperty(";
390 QString methodName = "getProperty(";
390 methodName += attributeName;
391 methodName += attributeName;
391 methodName += ")";
392 methodName += ")";
392 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
393 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
393 }
394 }
394
395
395 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
396 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
396
397
397 if (profilingCB) {
398 if (profilingCB) {
398 profilingCB(PythonQt::Leave, NULL, NULL);
399 profilingCB(PythonQt::Leave, NULL, NULL);
399 }
400 }
400
401
401 return value;
402 return value;
402
403
403 } else {
404 } else {
404 Py_INCREF(Py_None);
405 Py_INCREF(Py_None);
405 return Py_None;
406 return Py_None;
406 }
407 }
407 } else {
408 } else {
408 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
409 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
409 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
410 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
410 return NULL;
411 return NULL;
411 }
412 }
412 break;
413 break;
413 case PythonQtMemberInfo::Slot:
414 case PythonQtMemberInfo::Slot:
414 return PythonQtSlotFunction_New(member._slot, obj, NULL);
415 return PythonQtSlotFunction_New(member._slot, obj, NULL);
415 break;
416 break;
417 case PythonQtMemberInfo::Signal:
418 return PythonQtSignalFunction_New(member._slot, obj, NULL);
419 break;
416 case PythonQtMemberInfo::EnumValue:
420 case PythonQtMemberInfo::EnumValue:
417 {
421 {
418 PyObject* enumValue = member._enumValue;
422 PyObject* enumValue = member._enumValue;
419 Py_INCREF(enumValue);
423 Py_INCREF(enumValue);
420 return enumValue;
424 return enumValue;
421 }
425 }
422 break;
426 break;
423 case PythonQtMemberInfo::EnumWrapper:
427 case PythonQtMemberInfo::EnumWrapper:
424 {
428 {
425 PyObject* enumWrapper = member._enumWrapper;
429 PyObject* enumWrapper = member._enumWrapper;
426 Py_INCREF(enumWrapper);
430 Py_INCREF(enumWrapper);
427 return enumWrapper;
431 return enumWrapper;
428 }
432 }
429 break;
433 break;
430 case PythonQtMemberInfo::NotFound:
434 case PythonQtMemberInfo::NotFound:
431 {
435 {
432 static const QByteArray getterString("py_get_");
436 static const QByteArray getterString("py_get_");
433 // check for a getter slot
437 // check for a getter slot
434 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
438 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
435 if (member._type == PythonQtMemberInfo::Slot) {
439 if (member._type == PythonQtMemberInfo::Slot) {
436 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
440 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
437 }
441 }
438
442
439 // handle dynamic properties
443 // handle dynamic properties
440 if (wrapper->_obj) {
444 if (wrapper->_obj) {
441 QVariant v = wrapper->_obj->property(attributeName);
445 QVariant v = wrapper->_obj->property(attributeName);
442 if (v.isValid()) {
446 if (v.isValid()) {
443 return PythonQtConv::QVariantToPyObject(v);
447 return PythonQtConv::QVariantToPyObject(v);
444 }
448 }
445 }
449 }
446 }
450 }
447 break;
451 break;
448 default:
452 default:
449 // is an invalid type, go on
453 // is an invalid type, go on
450 break;
454 break;
451 }
455 }
452
456
453 // look for the internal methods (className(), help())
457 // look for the internal methods (className(), help())
454 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
458 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
455 if (internalMethod) {
459 if (internalMethod) {
456 return internalMethod;
460 return internalMethod;
457 }
461 }
458 PyErr_Clear();
462 PyErr_Clear();
459
463
460 if (wrapper->_obj) {
464 if (wrapper->_obj) {
461 // look for a child
465 // look for a child
462 QObjectList children = wrapper->_obj->children();
466 QObjectList children = wrapper->_obj->children();
463 for (int i = 0; i < children.count(); i++) {
467 for (int i = 0; i < children.count(); i++) {
464 QObject *child = children.at(i);
468 QObject *child = children.at(i);
465 if (child->objectName() == attributeName) {
469 if (child->objectName() == attributeName) {
466 return PythonQt::priv()->wrapQObject(child);
470 return PythonQt::priv()->wrapQObject(child);
467 }
471 }
468 }
472 }
469 }
473 }
470
474
471 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
475 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
472 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
476 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
473 return NULL;
477 return NULL;
474 }
478 }
475
479
476 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
480 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
477 {
481 {
478 QString error;
482 QString error;
479 const char *attributeName;
483 const char *attributeName;
480 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
484 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
481
485
482 if ((attributeName = PyString_AsString(name)) == NULL)
486 if ((attributeName = PyString_AsString(name)) == NULL)
483 return -1;
487 return -1;
484
488
485 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
489 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
486 if (member._type == PythonQtMemberInfo::Property) {
490 if (member._type == PythonQtMemberInfo::Property) {
487
491
488 if (!wrapper->_obj) {
492 if (!wrapper->_obj) {
489 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
493 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
490 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
494 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
491 return -1;
495 return -1;
492 }
496 }
493
497
494 QMetaProperty prop = member._property;
498 QMetaProperty prop = member._property;
495 if (prop.isWritable()) {
499 if (prop.isWritable()) {
496 QVariant v;
500 QVariant v;
497 if (prop.isEnumType()) {
501 if (prop.isEnumType()) {
498 // this will give us either a string or an int, everything else will probably be an error
502 // this will give us either a string or an int, everything else will probably be an error
499 v = PythonQtConv::PyObjToQVariant(value);
503 v = PythonQtConv::PyObjToQVariant(value);
500 } else {
504 } else {
501 int t = prop.userType();
505 int t = prop.userType();
502 v = PythonQtConv::PyObjToQVariant(value, t);
506 v = PythonQtConv::PyObjToQVariant(value, t);
503 }
507 }
504 bool success = false;
508 bool success = false;
505 if (v.isValid()) {
509 if (v.isValid()) {
506 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
510 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
507 if (profilingCB) {
511 if (profilingCB) {
508 QString methodName = "setProperty(";
512 QString methodName = "setProperty(";
509 methodName += attributeName;
513 methodName += attributeName;
510 methodName += ")";
514 methodName += ")";
511 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
515 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
512 }
516 }
513
517
514 success = prop.write(wrapper->_obj, v);
518 success = prop.write(wrapper->_obj, v);
515
519
516 if (profilingCB) {
520 if (profilingCB) {
517 profilingCB(PythonQt::Leave, NULL, NULL);
521 profilingCB(PythonQt::Leave, NULL, NULL);
518 }
522 }
519 }
523 }
520 if (success) {
524 if (success) {
521 return 0;
525 return 0;
522 } else {
526 } else {
523 error = QString("Property '") + attributeName + "' of type '" +
527 error = QString("Property '") + attributeName + "' of type '" +
524 prop.typeName() + "' does not accept an object of type "
528 prop.typeName() + "' does not accept an object of type "
525 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
529 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
526 }
530 }
527 } else {
531 } else {
528 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
532 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
529 }
533 }
530 } else if (member._type == PythonQtMemberInfo::Slot) {
534 } else if (member._type == PythonQtMemberInfo::Slot) {
531 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
535 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
536 } else if (member._type == PythonQtMemberInfo::Signal) {
537 error = QString("Signal '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
532 } else if (member._type == PythonQtMemberInfo::EnumValue) {
538 } else if (member._type == PythonQtMemberInfo::EnumValue) {
533 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
539 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
534 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
540 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
535 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
541 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
536 } else if (member._type == PythonQtMemberInfo::NotFound) {
542 } else if (member._type == PythonQtMemberInfo::NotFound) {
537 // check for a setter slot
543 // check for a setter slot
538 static const QByteArray setterString("py_set_");
544 static const QByteArray setterString("py_set_");
539 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
545 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
540 if (setter._type == PythonQtMemberInfo::Slot) {
546 if (setter._type == PythonQtMemberInfo::Slot) {
541 // call the setter and ignore the result value
547 // call the setter and ignore the result value
542 void* result;
548 void* result;
543 PyObject* args = PyTuple_New(1);
549 PyObject* args = PyTuple_New(1);
544 Py_INCREF(value);
550 Py_INCREF(value);
545 PyTuple_SET_ITEM(args, 0, value);
551 PyTuple_SET_ITEM(args, 0, value);
546 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
552 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
547 Py_DECREF(args);
553 Py_DECREF(args);
548 return 0;
554 return 0;
549 }
555 }
550
556
551 // handle dynamic properties
557 // handle dynamic properties
552 if (wrapper->_obj) {
558 if (wrapper->_obj) {
553 QVariant prop = wrapper->_obj->property(attributeName);
559 QVariant prop = wrapper->_obj->property(attributeName);
554 if (prop.isValid()) {
560 if (prop.isValid()) {
555 QVariant v = PythonQtConv::PyObjToQVariant(value);
561 QVariant v = PythonQtConv::PyObjToQVariant(value);
556 if (v.isValid()) {
562 if (v.isValid()) {
557 wrapper->_obj->setProperty(attributeName, v);
563 wrapper->_obj->setProperty(attributeName, v);
558 return 0;
564 return 0;
559 } else {
565 } else {
560 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
566 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
561 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
567 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
562 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
568 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
563 return -1;
569 return -1;
564 }
570 }
565 }
571 }
566 }
572 }
567
573
568 // if we are a derived python class, we allow setting attributes.
574 // if we are a derived python class, we allow setting attributes.
569 // if we are a direct CPP wrapper, we do NOT allow it, since
575 // if we are a direct CPP wrapper, we do NOT allow it, since
570 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
576 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
571 // and when it is recreated from a CPP pointer the attributes are gone...
577 // and when it is recreated from a CPP pointer the attributes are gone...
572 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
578 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
573 return PyBaseObject_Type.tp_setattro(obj,name,value);
579 return PyBaseObject_Type.tp_setattro(obj,name,value);
574 } else {
580 } else {
575 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
581 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
576 }
582 }
577 }
583 }
578
584
579 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
585 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
580 return -1;
586 return -1;
581 }
587 }
582
588
583 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
589 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
584 QString result;
590 QString result;
585 if (wrapper->_wrappedPtr) {
591 if (wrapper->_wrappedPtr) {
586 // first try some manually string conversions for some variants
592 // first try some manually string conversions for some variants
587 int metaid = wrapper->classInfo()->metaTypeId();
593 int metaid = wrapper->classInfo()->metaTypeId();
588 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
594 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
589 if (!result.isEmpty()) {
595 if (!result.isEmpty()) {
590 return result;
596 return result;
591 }
597 }
592 }
598 }
599 if (wrapper->_wrappedPtr || wrapper->_obj) {
593 // next, try to call py_toString
600 // next, try to call py_toString
594 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
601 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
595 if (info._type == PythonQtMemberInfo::Slot) {
602 if (info._type == PythonQtMemberInfo::Slot) {
596 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
603 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
597 if (resultObj) {
604 if (resultObj) {
598 // TODO this is one conversion too much, would be nicer to call the slot directly...
605 // TODO this is one conversion too much, would be nicer to call the slot directly...
599 result = PythonQtConv::PyObjGetString(resultObj);
606 result = PythonQtConv::PyObjGetString(resultObj);
600 Py_DECREF(resultObj);
607 Py_DECREF(resultObj);
601 }
608 }
602 }
609 }
610 }
603 return result;
611 return result;
604 }
612 }
605
613
606 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
614 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
607 {
615 {
608 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
616 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
609
617
610 // QByteArray should be directly returned as a str
618 // QByteArray should be directly returned as a str
611 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
619 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
612 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
620 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
613 if (b->data()) {
621 if (b->data()) {
614 return PyString_FromStringAndSize(b->data(), b->size());
622 return PyString_FromStringAndSize(b->data(), b->size());
615 } else {
623 } else {
616 return PyString_FromString("");
624 return PyString_FromString("");
617 }
625 }
618 }
626 }
619
627
620 const char* typeName = obj->ob_type->tp_name;
628 const char* typeName = obj->ob_type->tp_name;
621 QObject *qobj = wrapper->_obj;
629 QObject *qobj = wrapper->_obj;
622 QString str = getStringFromObject(wrapper);
630 QString str = getStringFromObject(wrapper);
623 if (!str.isEmpty()) {
631 if (!str.isEmpty()) {
624 return PyString_FromFormat("%s", str.toLatin1().constData());
632 return PyString_FromFormat("%s", str.toLatin1().constData());
625 }
633 }
626 if (wrapper->_wrappedPtr) {
634 if (wrapper->_wrappedPtr) {
627 if (wrapper->_obj) {
635 if (wrapper->_obj) {
628 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
636 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
629 } else {
637 } else {
630 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
638 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
631 }
639 }
632 } else {
640 } else {
633 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
641 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
634 }
642 }
635 }
643 }
636
644
637 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
645 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
638 {
646 {
639 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
647 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
640 const char* typeName = obj->ob_type->tp_name;
648 const char* typeName = obj->ob_type->tp_name;
641
649
642 QObject *qobj = wrapper->_obj;
650 QObject *qobj = wrapper->_obj;
643 QString str = getStringFromObject(wrapper);
651 QString str = getStringFromObject(wrapper);
644 if (!str.isEmpty()) {
652 if (!str.isEmpty()) {
645 if (str.startsWith(typeName)) {
653 if (str.startsWith(typeName)) {
646 return PyString_FromFormat("%s", str.toLatin1().constData());
654 return PyString_FromFormat("%s", str.toLatin1().constData());
647 } else {
655 } else {
648 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
656 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
649 }
657 }
650 }
658 }
651 if (wrapper->_wrappedPtr) {
659 if (wrapper->_wrappedPtr) {
652 if (wrapper->_obj) {
660 if (wrapper->_obj) {
653 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
661 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
654 } else {
662 } else {
655 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
663 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
656 }
664 }
657 } else {
665 } else {
658 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
666 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
659 }
667 }
660 }
668 }
661
669
662 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
670 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
663 {
671 {
664 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
672 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
665 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
673 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
666 }
674 }
667
675
668
676
669 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
677 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
670 {
678 {
671 if (obj->_wrappedPtr != NULL) {
679 if (obj->_wrappedPtr != NULL) {
672 return reinterpret_cast<long>(obj->_wrappedPtr);
680 return reinterpret_cast<long>(obj->_wrappedPtr);
673 } else {
681 } else {
674 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
682 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
675 return reinterpret_cast<long>(qobj);
683 return reinterpret_cast<long>(qobj);
676 }
684 }
677 }
685 }
678
686
679
687
680
688
681 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
689 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
682 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
690 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
683 0, /* nb_add */
691 0, /* nb_add */
684 0, /* nb_subtract */
692 0, /* nb_subtract */
685 0, /* nb_multiply */
693 0, /* nb_multiply */
686 0, /* nb_divide */
694 0, /* nb_divide */
687 0, /* nb_remainder */
695 0, /* nb_remainder */
688 0, /* nb_divmod */
696 0, /* nb_divmod */
689 0, /* nb_power */
697 0, /* nb_power */
690 0, /* nb_negative */
698 0, /* nb_negative */
691 0, /* nb_positive */
699 0, /* nb_positive */
692 0, /* nb_absolute */
700 0, /* nb_absolute */
693 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
701 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
694 0, /* nb_invert */
702 0, /* nb_invert */
695 0, /* nb_lshift */
703 0, /* nb_lshift */
696 0, /* nb_rshift */
704 0, /* nb_rshift */
697 0, /* nb_and */
705 0, /* nb_and */
698 0, /* nb_xor */
706 0, /* nb_xor */
699 0, /* nb_or */
707 0, /* nb_or */
700 0, /* nb_coerce */
708 0, /* nb_coerce */
701 0, /* nb_int */
709 0, /* nb_int */
702 0, /* nb_long */
710 0, /* nb_long */
703 0, /* nb_float */
711 0, /* nb_float */
704 0, /* nb_oct */
712 0, /* nb_oct */
705 0, /* nb_hex */
713 0, /* nb_hex */
706 0, /* nb_inplace_add */
714 0, /* nb_inplace_add */
707 0, /* nb_inplace_subtract */
715 0, /* nb_inplace_subtract */
708 0, /* nb_inplace_multiply */
716 0, /* nb_inplace_multiply */
709 0, /* nb_inplace_divide */
717 0, /* nb_inplace_divide */
710 0, /* nb_inplace_remainder */
718 0, /* nb_inplace_remainder */
711 0, /* nb_inplace_power */
719 0, /* nb_inplace_power */
712 0, /* nb_inplace_lshift */
720 0, /* nb_inplace_lshift */
713 0, /* nb_inplace_rshift */
721 0, /* nb_inplace_rshift */
714 0, /* nb_inplace_and */
722 0, /* nb_inplace_and */
715 0, /* nb_inplace_xor */
723 0, /* nb_inplace_xor */
716 0, /* nb_inplace_or */
724 0, /* nb_inplace_or */
717 0, /* nb_floor_divide */
725 0, /* nb_floor_divide */
718 0, /* nb_true_divide */
726 0, /* nb_true_divide */
719 0, /* nb_inplace_floor_divide */
727 0, /* nb_inplace_floor_divide */
720 0, /* nb_inplace_true_divide */
728 0, /* nb_inplace_true_divide */
721 };
729 };
722
730
723 PyTypeObject PythonQtInstanceWrapper_Type = {
731 PyTypeObject PythonQtInstanceWrapper_Type = {
724 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
732 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
725 0, /*ob_size*/
733 0, /*ob_size*/
726 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
734 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
727 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
735 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
728 0, /*tp_itemsize*/
736 0, /*tp_itemsize*/
729 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
737 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
730 0, /*tp_print*/
738 0, /*tp_print*/
731 0, /*tp_getattr*/
739 0, /*tp_getattr*/
732 0, /*tp_setattr*/
740 0, /*tp_setattr*/
733 0, /*tp_compare*/
741 0, /*tp_compare*/
734 PythonQtInstanceWrapper_repr, /*tp_repr*/
742 PythonQtInstanceWrapper_repr, /*tp_repr*/
735 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
743 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
736 0, /*tp_as_sequence*/
744 0, /*tp_as_sequence*/
737 0, /*tp_as_mapping*/
745 0, /*tp_as_mapping*/
738 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
746 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
739 0, /*tp_call*/
747 0, /*tp_call*/
740 PythonQtInstanceWrapper_str, /*tp_str*/
748 PythonQtInstanceWrapper_str, /*tp_str*/
741 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
749 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
742 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
750 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
743 0, /*tp_as_buffer*/
751 0, /*tp_as_buffer*/
744 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
752 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
745 "PythonQtInstanceWrapper object", /* tp_doc */
753 "PythonQtInstanceWrapper object", /* tp_doc */
746 0, /* tp_traverse */
754 0, /* tp_traverse */
747 0, /* tp_clear */
755 0, /* tp_clear */
748 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
756 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
749 0, /* tp_weaklistoffset */
757 0, /* tp_weaklistoffset */
750 0, /* tp_iter */
758 0, /* tp_iter */
751 0, /* tp_iternext */
759 0, /* tp_iternext */
752 0, /* tp_methods */
760 0, /* tp_methods */
753 0, /* tp_members */
761 0, /* tp_members */
754 0, /* tp_getset */
762 0, /* tp_getset */
755 0, /* tp_base */
763 0, /* tp_base */
756 0, /* tp_dict */
764 0, /* tp_dict */
757 0, /* tp_descr_get */
765 0, /* tp_descr_get */
758 0, /* tp_descr_set */
766 0, /* tp_descr_set */
759 0, /* tp_dictoffset */
767 0, /* tp_dictoffset */
760 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
768 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
761 0, /* tp_alloc */
769 0, /* tp_alloc */
762 PythonQtInstanceWrapper_new, /* tp_new */
770 PythonQtInstanceWrapper_new, /* tp_new */
763 };
771 };
764
772
765 //-------------------------------------------------------
773 //-------------------------------------------------------
766
774
@@ -1,350 +1,352
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include <iostream>
44 #include <iostream>
45
45
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48
48
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 {
50 {
51 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
52 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
53 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
56 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QList<QByteArray> names = meta.parameterTypes();
61 QList<QByteArray> names = meta.parameterTypes();
62 foreach (const QByteArray& name, names) {
62 foreach (const QByteArray& name, names) {
63 fillParameterInfo(type, name, classInfo);
63 fillParameterInfo(type, name, classInfo);
64 _parameters.append(type);
64 _parameters.append(type);
65 }
65 }
66 }
66 }
67
67
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
69 {
69 {
70 ParameterInfo type;
70 ParameterInfo type;
71 fillParameterInfo(type, typeName, NULL);
71 fillParameterInfo(type, typeName, NULL);
72 _parameters.append(type);
72 _parameters.append(type);
73 foreach (const QByteArray& name, args) {
73 foreach (const QByteArray& name, args) {
74 fillParameterInfo(type, name, NULL);
74 fillParameterInfo(type, name, NULL);
75 _parameters.append(type);
75 _parameters.append(type);
76 }
76 }
77 }
77 }
78
78
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
80 {
80 {
81 QByteArray sig(signal.signature());
81 QByteArray sig(signal.signature());
82 sig = sig.mid(sig.indexOf('('));
82 sig = sig.mid(sig.indexOf('('));
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
85 if (!result) {
85 if (!result) {
86 result = new PythonQtMethodInfo(signal, classInfo);
86 result = new PythonQtMethodInfo(signal, classInfo);
87 _cachedSignatures.insert(fullSig, result);
87 _cachedSignatures.insert(fullSig, result);
88 }
88 }
89 return result;
89 return result;
90 }
90 }
91
91
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
93 {
93 {
94 QByteArray typeName = args[0];
94 QByteArray typeName = args[0];
95 QList<QByteArray> arguments;
95 QList<QByteArray> arguments;
96 QByteArray fullSig = typeName;
96 QByteArray fullSig = typeName;
97 fullSig += "(";
97 fullSig += "(";
98 for (int i =1;i<numArgs; i++) {
98 for (int i =1;i<numArgs; i++) {
99 if (i>1) {
99 if (i>1) {
100 fullSig += ",";
100 fullSig += ",";
101 }
101 }
102 arguments << QByteArray(args[i]);
102 QByteArray arg(args[i]);
103 fullSig += arg;
104 arguments << arg;
103 }
105 }
104 fullSig += ")";
106 fullSig += ")";
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
107 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
106 if (!result) {
108 if (!result) {
107 result = new PythonQtMethodInfo(typeName, arguments);
109 result = new PythonQtMethodInfo(typeName, arguments);
108 _cachedSignatures.insert(fullSig, result);
110 _cachedSignatures.insert(fullSig, result);
109 }
111 }
110 return result;
112 return result;
111 }
113 }
112
114
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
115 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
114 {
116 {
115 QByteArray name = orgName;
117 QByteArray name = orgName;
116
118
117 type.enumWrapper = NULL;
119 type.enumWrapper = NULL;
118
120
119 int len = name.length();
121 int len = name.length();
120 if (len>0) {
122 if (len>0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
123 if (strncmp(name.constData(), "const ", 6)==0) {
122 name = name.mid(6);
124 name = name.mid(6);
123 len -= 6;
125 len -= 6;
124 type.isConst = true;
126 type.isConst = true;
125 } else {
127 } else {
126 type.isConst = false;
128 type.isConst = false;
127 }
129 }
128 char pointerCount = 0;
130 char pointerCount = 0;
129 bool hadReference = false;
131 bool hadReference = false;
130 // remove * and & from the end of the string, handle & and * the same way
132 // remove * and & from the end of the string, handle & and * the same way
131 while (name.at(len-1) == '*') {
133 while (name.at(len-1) == '*') {
132 len--;
134 len--;
133 pointerCount++;
135 pointerCount++;
134 }
136 }
135 while (name.at(len-1) == '&') {
137 while (name.at(len-1) == '&') {
136 len--;
138 len--;
137 hadReference = true;
139 hadReference = true;
138 }
140 }
139 if (len!=name.length()) {
141 if (len!=name.length()) {
140 name = name.left(len);
142 name = name.left(len);
141 }
143 }
142 type.pointerCount = pointerCount;
144 type.pointerCount = pointerCount;
143
145
144 QByteArray alias = _parameterNameAliases.value(name);
146 QByteArray alias = _parameterNameAliases.value(name);
145 if (!alias.isEmpty()) {
147 if (!alias.isEmpty()) {
146 name = alias;
148 name = alias;
147 }
149 }
148
150
149 type.typeId = nameToType(name);
151 type.typeId = nameToType(name);
150 if ((type.pointerCount == 0) && type.typeId == Unknown) {
152 if ((type.pointerCount == 0) && type.typeId == Unknown) {
151 type.typeId = QMetaType::type(name.constData());
153 type.typeId = QMetaType::type(name.constData());
152 if (type.typeId == QMetaType::Void) {
154 if (type.typeId == QMetaType::Void) {
153 type.typeId = Unknown;
155 type.typeId = Unknown;
154 }
156 }
155 }
157 }
156 type.name = name;
158 type.name = name;
157
159
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
160 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
159 bool isLocalEnum;
161 bool isLocalEnum;
160 // TODOXXX: make use of this flag!
162 // TODOXXX: make use of this flag!
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
163 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
162 }
164 }
163 } else {
165 } else {
164 type.typeId = QMetaType::Void;
166 type.typeId = QMetaType::Void;
165 type.pointerCount = 0;
167 type.pointerCount = 0;
166 type.isConst = false;
168 type.isConst = false;
167 }
169 }
168 }
170 }
169
171
170 int PythonQtMethodInfo::nameToType(const char* name)
172 int PythonQtMethodInfo::nameToType(const char* name)
171 {
173 {
172 if (_parameterTypeDict.isEmpty()) {
174 if (_parameterTypeDict.isEmpty()) {
173 // we could also use QMetaType::nameToType, but that does a string compare search
175 // we could also use QMetaType::nameToType, but that does a string compare search
174 // and does not support QVariant
176 // and does not support QVariant
175
177
176 // QMetaType names
178 // QMetaType names
177 _parameterTypeDict.insert("long", QMetaType::Long);
179 _parameterTypeDict.insert("long", QMetaType::Long);
178 _parameterTypeDict.insert("int", QMetaType::Int);
180 _parameterTypeDict.insert("int", QMetaType::Int);
179 _parameterTypeDict.insert("short", QMetaType::Short);
181 _parameterTypeDict.insert("short", QMetaType::Short);
180 _parameterTypeDict.insert("char", QMetaType::Char);
182 _parameterTypeDict.insert("char", QMetaType::Char);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
183 _parameterTypeDict.insert("ulong", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
184 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
185 _parameterTypeDict.insert("uint", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
186 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
187 _parameterTypeDict.insert("ushort", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
188 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
189 _parameterTypeDict.insert("uchar", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
190 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
191 _parameterTypeDict.insert("bool", QMetaType::Bool);
190 _parameterTypeDict.insert("float", QMetaType::Float);
192 _parameterTypeDict.insert("float", QMetaType::Float);
191 _parameterTypeDict.insert("double", QMetaType::Double);
193 _parameterTypeDict.insert("double", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
194 _parameterTypeDict.insert("qreal", QMetaType::Double);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
195 _parameterTypeDict.insert("QChar", QMetaType::QChar);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
196 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
195 _parameterTypeDict.insert("QString", QMetaType::QString);
197 _parameterTypeDict.insert("QString", QMetaType::QString);
196 _parameterTypeDict.insert("", QMetaType::Void);
198 _parameterTypeDict.insert("", QMetaType::Void);
197 _parameterTypeDict.insert("void", QMetaType::Void);
199 _parameterTypeDict.insert("void", QMetaType::Void);
198 // QVariant names
200 // QVariant names
199 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
201 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
200 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
202 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
201 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
203 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
202 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
204 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
203 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
205 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
204 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
206 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
205 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
206 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
207 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
210 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
211 _parameterTypeDict.insert("QDate", QMetaType::QDate);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
212 _parameterTypeDict.insert("QTime", QMetaType::QTime);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
213 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
214 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
215 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
216 _parameterTypeDict.insert("QRect", QMetaType::QRect);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
217 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
219 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
218 _parameterTypeDict.insert("QSize", QMetaType::QSize);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
219 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
221 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
220 _parameterTypeDict.insert("QLine", QMetaType::QLine);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
221 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
223 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
222 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
223 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
225 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
224 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
225 _parameterTypeDict.insert("QFont", QMetaType::QFont);
227 _parameterTypeDict.insert("QFont", QMetaType::QFont);
226 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
228 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
227 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
229 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
228 _parameterTypeDict.insert("QColor", QMetaType::QColor);
230 _parameterTypeDict.insert("QColor", QMetaType::QColor);
229 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
231 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
230 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
232 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
231 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
233 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
232 _parameterTypeDict.insert("QImage", QMetaType::QImage);
234 _parameterTypeDict.insert("QImage", QMetaType::QImage);
233 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
235 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
234 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
236 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
235 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
237 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
236 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
238 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
237 _parameterTypeDict.insert("QPen", QMetaType::QPen);
239 _parameterTypeDict.insert("QPen", QMetaType::QPen);
238 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
240 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
239 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
241 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
240 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
242 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
241 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
243 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
242 // own special types... (none so far, could be e.g. ObjectList
244 // own special types... (none so far, could be e.g. ObjectList
243 }
245 }
244 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
246 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
245 if (it!=_parameterTypeDict.end()) {
247 if (it!=_parameterTypeDict.end()) {
246 return it.value();
248 return it.value();
247 } else {
249 } else {
248 return PythonQtMethodInfo::Unknown;
250 return PythonQtMethodInfo::Unknown;
249 }
251 }
250 }
252 }
251
253
252 void PythonQtMethodInfo::cleanupCachedMethodInfos()
254 void PythonQtMethodInfo::cleanupCachedMethodInfos()
253 {
255 {
254 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
256 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
255 while (i.hasNext()) {
257 while (i.hasNext()) {
256 delete i.next().value();
258 delete i.next().value();
257 }
259 }
258 }
260 }
259
261
260 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
262 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
261 {
263 {
262 _parameterNameAliases.insert(alias, name);
264 _parameterNameAliases.insert(alias, name);
263 }
265 }
264
266
265 //-------------------------------------------------------------------------------------------------
267 //-------------------------------------------------------------------------------------------------
266
268
267 void PythonQtSlotInfo::deleteOverloadsAndThis()
269 void PythonQtSlotInfo::deleteOverloadsAndThis()
268 {
270 {
269 PythonQtSlotInfo* cur = this;
271 PythonQtSlotInfo* cur = this;
270 while(cur->nextInfo()) {
272 while(cur->nextInfo()) {
271 PythonQtSlotInfo* next = cur->nextInfo();
273 PythonQtSlotInfo* next = cur->nextInfo();
272 delete cur;
274 delete cur;
273 cur = next;
275 cur = next;
274 }
276 }
275 }
277 }
276
278
277
279
278 QString PythonQtSlotInfo::fullSignature()
280 QString PythonQtSlotInfo::fullSignature()
279 {
281 {
280 bool skipFirstArg = isInstanceDecorator();
282 bool skipFirstArg = isInstanceDecorator();
281 QString result = _meta.typeName();
283 QString result = _meta.typeName();
282 QByteArray sig = slotName();
284 QByteArray sig = slotName();
283 QList<QByteArray> names = _meta.parameterNames();
285 QList<QByteArray> names = _meta.parameterNames();
284
286
285 bool isStatic = false;
287 bool isStatic = false;
286 bool isConstructor = false;
288 bool isConstructor = false;
287 bool isDestructor = false;
289 bool isDestructor = false;
288
290
289 if (_type == ClassDecorator) {
291 if (_type == ClassDecorator) {
290 if (sig.startsWith("new_")) {
292 if (sig.startsWith("new_")) {
291 sig = sig.mid(4);
293 sig = sig.mid(4);
292 isConstructor = true;
294 isConstructor = true;
293 } else if (sig.startsWith("delete_")) {
295 } else if (sig.startsWith("delete_")) {
294 sig = sig.mid(7);
296 sig = sig.mid(7);
295 isDestructor = true;
297 isDestructor = true;
296 } else if(sig.startsWith("static_")) {
298 } else if(sig.startsWith("static_")) {
297 isStatic = true;
299 isStatic = true;
298 sig = sig.mid(7);
300 sig = sig.mid(7);
299 int idx = sig.indexOf("_");
301 int idx = sig.indexOf("_");
300 if (idx>=0) {
302 if (idx>=0) {
301 sig = sig.mid(idx+1);
303 sig = sig.mid(idx+1);
302 }
304 }
303 }
305 }
304 }
306 }
305
307
306 result += QByteArray(" ") + sig;
308 result += QByteArray(" ") + sig;
307 result += "(";
309 result += "(";
308
310
309 int lastEntry = _parameters.count()-1;
311 int lastEntry = _parameters.count()-1;
310 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
312 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
311 if (_parameters.at(i).isConst) {
313 if (_parameters.at(i).isConst) {
312 result += "const ";
314 result += "const ";
313 }
315 }
314 result += _parameters.at(i).name;
316 result += _parameters.at(i).name;
315 if (_parameters.at(i).pointerCount) {
317 if (_parameters.at(i).pointerCount) {
316 QByteArray stars;
318 QByteArray stars;
317 stars.fill('*', _parameters.at(i).pointerCount);
319 stars.fill('*', _parameters.at(i).pointerCount);
318 result += stars;
320 result += stars;
319 }
321 }
320 if (!names.at(i-1).isEmpty()) {
322 if (!names.at(i-1).isEmpty()) {
321 result += " ";
323 result += " ";
322 result += names.at(i-1);
324 result += names.at(i-1);
323 }
325 }
324 if (i!=lastEntry) {
326 if (i!=lastEntry) {
325 result += ", ";
327 result += ", ";
326 }
328 }
327 }
329 }
328 result += ")";
330 result += ")";
329
331
330 if (isStatic) {
332 if (isStatic) {
331 result = QString("static ") + result;
333 result = QString("static ") + result;
332 }
334 }
333 if (isConstructor) {
335 if (isConstructor) {
334 // result = QString("constructor ") + result;
336 // result = QString("constructor ") + result;
335 }
337 }
336 if (isDestructor) {
338 if (isDestructor) {
337 result = QString("~") + result;
339 result = QString("~") + result;
338 }
340 }
339 return result;
341 return result;
340 }
342 }
341
343
342
344
343 QByteArray PythonQtSlotInfo::slotName()
345 QByteArray PythonQtSlotInfo::slotName()
344 {
346 {
345 QByteArray sig(_meta.signature());
347 QByteArray sig(_meta.signature());
346 int idx = sig.indexOf('(');
348 int idx = sig.indexOf('(');
347 sig = sig.left(idx);
349 sig = sig.left(idx);
348 return sig;
350 return sig;
349 }
351 }
350
352
@@ -1,233 +1,242
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSignalReceiver.cpp
35 // \file PythonQtSignalReceiver.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtSignalReceiver.h"
42 #include "PythonQtSignalReceiver.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include "PythonQtMethodInfo.h"
44 #include "PythonQtMethodInfo.h"
45 #include "PythonQtConversion.h"
45 #include "PythonQtConversion.h"
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaMethod>
47 #include <QMetaMethod>
48 #include "funcobject.h"
48 #include "funcobject.h"
49
49
50 void PythonQtSignalTarget::call(void **arguments) const {
50 void PythonQtSignalTarget::call(void **arguments) const {
51 PyObject* result = call(_callable, methodInfo(), arguments);
51 PyObject* result = call(_callable, methodInfo(), arguments);
52 if (result) {
52 if (result) {
53 Py_DECREF(result);
53 Py_DECREF(result);
54 }
54 }
55 }
55 }
56
56
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
58 {
58 {
59 Q_UNUSED(skipFirstArgumentOfMethodInfo)
59 Q_UNUSED(skipFirstArgumentOfMethodInfo)
60
60
61 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
61 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
62 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
62 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
63
63
64 int numPythonArgs = -1;
64 int numPythonArgs = -1;
65 if (PyFunction_Check(callable)) {
65 if (PyFunction_Check(callable)) {
66 PyObject* o = callable;
66 PyObject* o = callable;
67 PyFunctionObject* func = (PyFunctionObject*)o;
67 PyFunctionObject* func = (PyFunctionObject*)o;
68 PyCodeObject* code = (PyCodeObject*)func->func_code;
68 PyCodeObject* code = (PyCodeObject*)func->func_code;
69 if (!(code->co_flags & 0x04)) {
69 if (!(code->co_flags & CO_VARARGS)) {
70 numPythonArgs = code->co_argcount;
70 numPythonArgs = code->co_argcount;
71 } else {
71 } else {
72 // variable numbers of arguments allowed
72 // variable numbers of arguments allowed
73 }
73 }
74 } else if (PyMethod_Check(callable)) {
74 } else if (PyMethod_Check(callable)) {
75 PyObject* o = callable;
75 PyObject* o = callable;
76 PyMethodObject* method = (PyMethodObject*)o;
76 PyMethodObject* method = (PyMethodObject*)o;
77 if (PyFunction_Check(method->im_func)) {
77 if (PyFunction_Check(method->im_func)) {
78 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
78 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
79 PyCodeObject* code = (PyCodeObject*)func->func_code;
79 PyCodeObject* code = (PyCodeObject*)func->func_code;
80 if (!(code->co_flags & 0x04)) {
80 if (!(code->co_flags & CO_VARARGS)) {
81 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
81 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
82 } else {
82 } else {
83 // variable numbers of arguments allowed
83 // variable numbers of arguments allowed
84 }
84 }
85 }
85 }
86 }
86 }
87
87
88 const PythonQtMethodInfo* m = methodInfos;
88 const PythonQtMethodInfo* m = methodInfos;
89 // parameterCount includes return value:
89 // parameterCount includes return value:
90 int count = m->parameterCount();
90 int count = m->parameterCount();
91 if (numPythonArgs!=-1) {
91 if (numPythonArgs!=-1) {
92 if (count>numPythonArgs+1) {
92 if (count>numPythonArgs+1) {
93 // take less arguments
93 // take less arguments
94 count = numPythonArgs+1;
94 count = numPythonArgs+1;
95 }
95 }
96 }
96 }
97
97
98 PyObject* pargs = NULL;
98 PyObject* pargs = NULL;
99 if (count>1) {
99 if (count>1) {
100 pargs = PyTuple_New(count-1);
100 pargs = PyTuple_New(count-1);
101 }
101 }
102 bool err = false;
102 bool err = false;
103 // transform Qt values to Python
103 // transform Qt values to Python
104 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
104 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
105 for (int i = 1; i < count; i++) {
105 for (int i = 1; i < count; i++) {
106 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
106 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
107 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
107 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
108 if (arg) {
108 if (arg) {
109 // steals reference, no unref
109 // steals reference, no unref
110 PyTuple_SetItem(pargs, i-1,arg);
110 PyTuple_SetItem(pargs, i-1,arg);
111 } else {
111 } else {
112 err = true;
112 err = true;
113 break;
113 break;
114 }
114 }
115 }
115 }
116
116
117 PyObject* result = NULL;
117 PyObject* result = NULL;
118 if (!err) {
118 if (!err) {
119 PyErr_Clear();
119 PyErr_Clear();
120 result = PyObject_CallObject(callable, pargs);
120 result = PyObject_CallObject(callable, pargs);
121 if (result) {
121 if (result) {
122 // ok
122 // ok
123 } else {
123 } else {
124 PythonQt::self()->handleError();
124 PythonQt::self()->handleError();
125 }
125 }
126 }
126 }
127 if (pargs) {
127 if (pargs) {
128 // free the arguments again
128 // free the arguments again
129 Py_DECREF(pargs);
129 Py_DECREF(pargs);
130 }
130 }
131
131
132 return result;
132 return result;
133 }
133 }
134
134
135 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const
135 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const
136 {
136 {
137 return PyObject_Compare(callable, _callable) == 0 && signalId==_signalId;
137 return PyObject_Compare(callable, _callable) == 0 && signalId==_signalId;
138 }
138 }
139
139
140 //------------------------------------------------------------------------------
140 //------------------------------------------------------------------------------
141
141
142 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
142 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
143 {
143 {
144 _obj = obj;
144 _obj = obj;
145
145
146 // fetch the class info for object, since we will need to for correct enum resolution in
146 // fetch the class info for object, since we will need to for correct enum resolution in
147 // signals
147 // signals
148 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
148 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
149 if (!_objClassInfo || !_objClassInfo->isQObject()) {
149 if (!_objClassInfo || !_objClassInfo->isQObject()) {
150 PythonQt::self()->registerClass(obj->metaObject());
150 PythonQt::self()->registerClass(obj->metaObject());
151 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
151 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
152 }
152 }
153 // force decorator/enum creation
153 // force decorator/enum creation
154 _objClassInfo->decorator();
154 _objClassInfo->decorator();
155
155
156 _slotCount = staticMetaObject.methodOffset();
156 _slotCount = staticMetaObject.methodOffset();
157 }
157 }
158
158
159 PythonQtSignalReceiver::~PythonQtSignalReceiver()
159 PythonQtSignalReceiver::~PythonQtSignalReceiver()
160 {
160 {
161 PythonQt::priv()->removeSignalEmitter(_obj);
161 PythonQt::priv()->removeSignalEmitter(_obj);
162 }
162 }
163
163
164
164
165 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
165 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
166 {
166 {
167 bool flag = false;
167 bool flag = false;
168 int sigId = getSignalIndex(signal);
168 int sigId = getSignalIndex(signal);
169 if (sigId>=0) {
169 if (sigId>=0) {
170 // create PythonQtMethodInfo from signal
170 // create PythonQtMethodInfo from signal
171 QMetaMethod meta = _obj->metaObject()->method(sigId);
171 QMetaMethod meta = _obj->metaObject()->method(sigId);
172 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
172 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
173 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
173 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
174 _targets.append(t);
174 _targets.append(t);
175 // now connect to ourselves with the new slot id
175 // now connect to ourselves with the new slot id
176 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
176 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
177
177
178 _slotCount++;
178 _slotCount++;
179 flag = true;
179 flag = true;
180 }
180 }
181 return flag;
181 return flag;
182 }
182 }
183
183
184 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
184 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
185 {
185 {
186 bool found = false;
186 bool found = false;
187 int sigId = getSignalIndex(signal);
187 int sigId = getSignalIndex(signal);
188 if (sigId>=0) {
188 if (sigId>=0) {
189 QMutableListIterator<PythonQtSignalTarget> i(_targets);
189 QMutableListIterator<PythonQtSignalTarget> i(_targets);
190 if (callable) {
190 while (i.hasNext()) {
191 while (i.hasNext()) {
191 if (i.next().isSame(sigId, callable)) {
192 if (i.next().isSame(sigId, callable)) {
192 i.remove();
193 i.remove();
193 found = true;
194 found = true;
194 break;
195 break;
195 }
196 }
196 }
197 }
198 } else {
199 while (i.hasNext()) {
200 if (i.next().signalId() == sigId) {
201 i.remove();
202 found = true;
203 }
204 }
205 }
197 }
206 }
198 return found;
207 return found;
199 }
208 }
200
209
201 void PythonQtSignalReceiver::removeSignalHandlers()
210 void PythonQtSignalReceiver::removeSignalHandlers()
202 {
211 {
203 _targets.clear();
212 _targets.clear();
204 }
213 }
205
214
206 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
215 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
207 {
216 {
208 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
217 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
209 if (sigId<0) {
218 if (sigId<0) {
210 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
219 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
211 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
220 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
212 }
221 }
213 return sigId;
222 return sigId;
214 }
223 }
215
224
216 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
225 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
217 {
226 {
218 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
227 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
219 if (c != QMetaObject::InvokeMetaMethod) {
228 if (c != QMetaObject::InvokeMetaMethod) {
220 QObject::qt_metacall(c, id, arguments);
229 QObject::qt_metacall(c, id, arguments);
221 }
230 }
222
231
223 bool found = false;
232 bool found = false;
224 foreach(const PythonQtSignalTarget& t, _targets) {
233 foreach(const PythonQtSignalTarget& t, _targets) {
225 if (t.slotId() == id) {
234 if (t.slotId() == id) {
226 found = true;
235 found = true;
227 t.call(arguments);
236 t.call(arguments);
228 break;
237 break;
229 }
238 }
230 }
239 }
231 return 0;
240 return 0;
232 }
241 }
233
242
@@ -1,142 +1,143
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSignalReceiver.h
38 // \file PythonQtSignalReceiver.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtPythonInclude.h"
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include "PythonQtObjectPtr.h"
48 #include "PythonQtObjectPtr.h"
49
49
50 class PythonQtMethodInfo;
50 class PythonQtMethodInfo;
51 class PythonQtClassInfo;
51 class PythonQtClassInfo;
52
52
53 //! stores information about a signal target
53 //! stores information about a signal target
54 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
55 */
55 */
56 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 class PYTHONQT_EXPORT PythonQtSignalTarget {
57 public:
57 public:
58 PythonQtSignalTarget() {
58 PythonQtSignalTarget() {
59 _signalId = -1;
59 _signalId = -1;
60 _methodInfo = NULL;
60 _methodInfo = NULL;
61 _slotId = -1;
61 _slotId = -1;
62 }
62 }
63
63
64 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
65 {
65 {
66 _signalId = signalId;
66 _signalId = signalId;
67 _slotId = slotId;
67 _slotId = slotId;
68 _methodInfo = methodInfo;
68 _methodInfo = methodInfo;
69 _callable = callable;
69 _callable = callable;
70 };
70 };
71
71
72 ~PythonQtSignalTarget() {
72 ~PythonQtSignalTarget() {
73 };
73 };
74
74
75 //! get the id of the original signal
75 //! get the id of the original signal
76 int signalId() const { return _signalId; }
76 int signalId() const { return _signalId; }
77
77
78 //! get the id that was assigned to this simulated slot
78 //! get the id that was assigned to this simulated slot
79 int slotId() const { return _slotId; }
79 int slotId() const { return _slotId; }
80
80
81 //! get the signals parameter info
81 //! get the signals parameter info
82 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
83
83
84 //! call the python callable with the given arguments (as defined in methodInfo)
84 //! call the python callable with the given arguments (as defined in methodInfo)
85 void call(void **arguments) const;
85 void call(void **arguments) const;
86
86
87 //! check if it is the same signal target
87 //! check if it is the same signal target
88 bool isSame(int signalId, PyObject* callable) const;
88 bool isSame(int signalId, PyObject* callable) const;
89
89
90 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
91 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
92
92
93 private:
93 private:
94 int _signalId;
94 int _signalId;
95 int _slotId;
95 int _slotId;
96 const PythonQtMethodInfo* _methodInfo;
96 const PythonQtMethodInfo* _methodInfo;
97 PythonQtObjectPtr _callable;
97 PythonQtObjectPtr _callable;
98 };
98 };
99
99
100 //! base class for signal receivers
100 //! base class for signal receivers
101 /*!
101 /*!
102 */
102 */
103 class PythonQtSignalReceiverBase : public QObject {
103 class PythonQtSignalReceiverBase : public QObject {
104 Q_OBJECT
104 Q_OBJECT
105 public:
105 public:
106 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
107 };
107 };
108
108
109 //! receives all signals for one QObject
109 //! receives all signals for one QObject
110 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
111 */
111 */
112 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
113
113
114 public:
114 public:
115 PythonQtSignalReceiver(QObject* obj);
115 PythonQtSignalReceiver(QObject* obj);
116 ~PythonQtSignalReceiver();
116 ~PythonQtSignalReceiver();
117
117
118 //! add a signal handler
118 //! add a signal handler
119 bool addSignalHandler(const char* signal, PyObject* callable);
119 bool addSignalHandler(const char* signal, PyObject* callable);
120
120
121 //! remove a signal handler
121 //! remove a signal handler for given callable (or all callables on that signal if callable is NULL)
122 bool removeSignalHandler(const char* signal, PyObject* callable);
122 bool removeSignalHandler(const char* signal, PyObject* callable = NULL);
123
123
124 //! remove all signal handlers
124 //! remove all signal handlers
125 void removeSignalHandlers();
125 void removeSignalHandlers();
126
126
127 //! we implement this method to simulate a number of slots that match the ids in _targets
127 //! we implement this method to simulate a number of slots that match the ids in _targets
128 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
128 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
129
129
130 private:
130 private:
131 //! get the index of the signal
131 //! get the index of the signal
132 int getSignalIndex(const char* signal);
132 int getSignalIndex(const char* signal);
133
133
134 QObject* _obj;
134 QObject* _obj;
135 PythonQtClassInfo* _objClassInfo;
135 PythonQtClassInfo* _objClassInfo;
136 int _slotCount;
136 int _slotCount;
137 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
137 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
138 QList<PythonQtSignalTarget> _targets;
138 QList<PythonQtSignalTarget> _targets;
139 };
139 };
140
140
141
141
142 #endif
142 #endif
143
@@ -1,556 +1,658
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #include <exception>
50 #include <exception>
51 #include <stdexcept>
51 #include <stdexcept>
52
52
53 #include <QByteArray>
54
53 #define PYTHONQT_MAX_ARGS 32
55 #define PYTHONQT_MAX_ARGS 32
54
56
55
57
56 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
58 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
57 {
59 {
58 static unsigned int recursiveEntry = 0;
60 static unsigned int recursiveEntry = 0;
59
61
60 if (directReturnValuePointer) {
62 if (directReturnValuePointer) {
61 *directReturnValuePointer = NULL;
63 *directReturnValuePointer = NULL;
62 }
64 }
63 // store the current storage position, so that we can get back to this state after a slot is called
65 // store the current storage position, so that we can get back to this state after a slot is called
64 // (do this locally, so that we have all positions on the stack
66 // (do this locally, so that we have all positions on the stack
65 PythonQtValueStoragePosition globalValueStoragePos;
67 PythonQtValueStoragePosition globalValueStoragePos;
66 PythonQtValueStoragePosition globalPtrStoragePos;
68 PythonQtValueStoragePosition globalPtrStoragePos;
67 PythonQtValueStoragePosition globalVariantStoragePos;
69 PythonQtValueStoragePosition globalVariantStoragePos;
68 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
70 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
69 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
71 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
70 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
72 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
71
73
72 recursiveEntry++;
74 recursiveEntry++;
73
75
74 // the arguments that are passed to qt_metacall
76 // the arguments that are passed to qt_metacall
75 void* argList[PYTHONQT_MAX_ARGS];
77 void* argList[PYTHONQT_MAX_ARGS];
76 PyObject* result = NULL;
78 PyObject* result = NULL;
77 int argc = info->parameterCount();
79 int argc = info->parameterCount();
78 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
80 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
79
81
80 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
82 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
81 // set return argument to NULL
83 // set return argument to NULL
82 argList[0] = NULL;
84 argList[0] = NULL;
83
85
84 bool ok = true;
86 bool ok = true;
85 bool skipFirst = false;
87 bool skipFirst = false;
86 if (info->isInstanceDecorator()) {
88 if (info->isInstanceDecorator()) {
87 skipFirst = true;
89 skipFirst = true;
88
90
89 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
91 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
90 void* arg1 = firstArgument;
92 void* arg1 = firstArgument;
91 if (!arg1) {
93 if (!arg1) {
92 arg1 = objectToCall;
94 arg1 = objectToCall;
93 }
95 }
94 if (arg1) {
96 if (arg1) {
95 // upcast to correct parent class
97 // upcast to correct parent class
96 arg1 = ((char*)arg1)+info->upcastingOffset();
98 arg1 = ((char*)arg1)+info->upcastingOffset();
97 }
99 }
98
100
99 argList[1] = &arg1;
101 argList[1] = &arg1;
100 if (ok) {
102 if (ok) {
101 for (int i = 2; i<argc && ok; i++) {
103 for (int i = 2; i<argc && ok; i++) {
102 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
104 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
103 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
105 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
104 if (argList[i]==NULL) {
106 if (argList[i]==NULL) {
105 ok = false;
107 ok = false;
106 break;
108 break;
107 }
109 }
108 }
110 }
109 }
111 }
110 } else {
112 } else {
111 for (int i = 1; i<argc && ok; i++) {
113 for (int i = 1; i<argc && ok; i++) {
112 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
114 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
113 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
115 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
114 if (argList[i]==NULL) {
116 if (argList[i]==NULL) {
115 ok = false;
117 ok = false;
116 break;
118 break;
117 }
119 }
118 }
120 }
119 }
121 }
120
122
121 if (ok) {
123 if (ok) {
122 // parameters are ok, now create the qt return value which is assigned to by metacall
124 // parameters are ok, now create the qt return value which is assigned to by metacall
123 if (returnValueParam.typeId != QMetaType::Void) {
125 if (returnValueParam.typeId != QMetaType::Void) {
124 // create empty default value for the return value
126 // create empty default value for the return value
125 if (!directReturnValuePointer) {
127 if (!directReturnValuePointer) {
126 // create empty default value for the return value
128 // create empty default value for the return value
127 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
129 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
128 if (argList[0]==NULL) {
130 if (argList[0]==NULL) {
129 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
131 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
130 // pass its internal pointer
132 // pass its internal pointer
131 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
133 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
132 if (info && info->pythonQtClassWrapper()) {
134 if (info && info->pythonQtClassWrapper()) {
133 PyObject* emptyTuple = PyTuple_New(0);
135 PyObject* emptyTuple = PyTuple_New(0);
134 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
136 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
135 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
137 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
136 if (result) {
138 if (result) {
137 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
139 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
138 }
140 }
139 Py_DECREF(emptyTuple);
141 Py_DECREF(emptyTuple);
140 }
142 }
141 }
143 }
142 } else {
144 } else {
143 // we can use our pointer directly!
145 // we can use our pointer directly!
144 argList[0] = directReturnValuePointer;
146 argList[0] = directReturnValuePointer;
145 }
147 }
146 }
148 }
147
149
148
150
149 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
151 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
150 if (profilingCB) {
152 if (profilingCB) {
151 const char* className = NULL;
153 const char* className = NULL;
152 if (info->decorator()) {
154 if (info->decorator()) {
153 className = info->decorator()->metaObject()->className();
155 className = info->decorator()->metaObject()->className();
154 } else {
156 } else {
155 className = objectToCall->metaObject()->className();
157 className = objectToCall->metaObject()->className();
156 }
158 }
157
159
158 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
160 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
159 }
161 }
160
162
161 // invoke the slot via metacall
163 // invoke the slot via metacall
162 bool hadException = false;
164 bool hadException = false;
165 QObject* obj = info->decorator()?info->decorator():objectToCall;
166 if (!obj) {
167 hadException = true;
168 PyErr_SetString(PyExc_RuntimeError, "Trying to call a slot on a deleted QObject!");
169 } else {
163 try {
170 try {
164 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
171 obj->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
165 } catch (std::bad_alloc & e) {
172 } catch (std::bad_alloc & e) {
166 hadException = true;
173 hadException = true;
167 QByteArray what("std::bad_alloc: ");
174 QByteArray what("std::bad_alloc: ");
168 what += e.what();
175 what += e.what();
169 PyErr_SetString(PyExc_MemoryError, what.constData());
176 PyErr_SetString(PyExc_MemoryError, what.constData());
170 } catch (std::runtime_error & e) {
177 } catch (std::runtime_error & e) {
171 hadException = true;
178 hadException = true;
172 QByteArray what("std::runtime_error: ");
179 QByteArray what("std::runtime_error: ");
173 what += e.what();
180 what += e.what();
174 PyErr_SetString(PyExc_RuntimeError, what.constData());
181 PyErr_SetString(PyExc_RuntimeError, what.constData());
175 } catch (std::logic_error & e) {
182 } catch (std::logic_error & e) {
176 hadException = true;
183 hadException = true;
177 QByteArray what("std::logic_error: ");
184 QByteArray what("std::logic_error: ");
178 what += e.what();
185 what += e.what();
179 PyErr_SetString(PyExc_RuntimeError, what.constData());
186 PyErr_SetString(PyExc_RuntimeError, what.constData());
180 } catch (std::exception& e) {
187 } catch (std::exception& e) {
181 hadException = true;
188 hadException = true;
182 QByteArray what("std::exception: ");
189 QByteArray what("std::exception: ");
183 what += e.what();
190 what += e.what();
184 PyErr_SetString(PyExc_StandardError, what.constData());
191 PyErr_SetString(PyExc_StandardError, what.constData());
185 }
192 }
193 }
186
194
187 if (profilingCB) {
195 if (profilingCB) {
188 profilingCB(PythonQt::Leave, NULL, NULL);
196 profilingCB(PythonQt::Leave, NULL, NULL);
189 }
197 }
190
198
191 // handle the return value (which in most cases still needs to be converted to a Python object)
199 // handle the return value (which in most cases still needs to be converted to a Python object)
192 if (!hadException) {
200 if (!hadException) {
193 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
201 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
194 if (directReturnValuePointer) {
202 if (directReturnValuePointer) {
195 result = NULL;
203 result = NULL;
196 } else {
204 } else {
197 // the resulting object maybe present already, because we created it above at 1)...
205 // the resulting object maybe present already, because we created it above at 1)...
198 if (!result) {
206 if (!result) {
199 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
207 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
200 }
208 }
201 }
209 }
202 } else {
210 } else {
203 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
211 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
204 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
212 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
205 result = NULL;
213 result = NULL;
206 }
214 }
207 } else {
215 } else {
208 result = NULL;
216 result = NULL;
209 }
217 }
210 }
218 }
211 recursiveEntry--;
219 recursiveEntry--;
212
220
213 // reset the parameter storage position to the stored pos to "pop" the parameter stack
221 // reset the parameter storage position to the stored pos to "pop" the parameter stack
214 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
222 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
215 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
223 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
216 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
224 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
217
225
218 *pythonReturnValue = result;
226 *pythonReturnValue = result;
219 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
227 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
220 return result || (directReturnValuePointer && *directReturnValuePointer);
228 return result || (directReturnValuePointer && *directReturnValuePointer);
221 }
229 }
222
230
223 //-----------------------------------------------------------------------------------
231 //-----------------------------------------------------------------------------------
224
232
225 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
233 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
226
234
227 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
235 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
228 {
236 {
229 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
237 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
230 PythonQtSlotInfo* info = f->m_ml;
238 return PythonQtMemberFunction_Call(f->m_ml, f->m_self, args, kw);
231 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
239 }
232 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
240
241 PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw)
242 {
243 if (PyObject_TypeCheck(m_self, &PythonQtInstanceWrapper_Type)) {
244 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) m_self;
233 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
245 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
234 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
246 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
235 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
247 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
236 return NULL;
248 return NULL;
237 } else {
249 } else {
238 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
250 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
239 }
251 }
240 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
252 } else if (m_self->ob_type == &PythonQtClassWrapper_Type) {
241 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
253 PythonQtClassWrapper* type = (PythonQtClassWrapper*) m_self;
242 if (info->isClassDecorator()) {
254 if (info->isClassDecorator()) {
243 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
255 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
244 } else {
256 } else {
245 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
257 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
246 Py_ssize_t argc = PyTuple_Size(args);
258 Py_ssize_t argc = PyTuple_Size(args);
247 if (argc>0) {
259 if (argc>0) {
248 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
260 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
249 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
261 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
250 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
262 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
251 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
263 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
252 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
264 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
253 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
265 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
254 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
266 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
255 return NULL;
267 return NULL;
256 }
268 }
257 // strip the first argument...
269 // strip the first argument...
258 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
270 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
259 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
271 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
260 Py_DECREF(newargs);
272 Py_DECREF(newargs);
261 return result;
273 return result;
262 } else {
274 } else {
263 // first arg is not of correct type!
275 // first arg is not of correct type!
264 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
276 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
265 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
277 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
266 return NULL;
278 return NULL;
267 }
279 }
268 } else {
280 } else {
269 // wrong number of args
281 // wrong number of args
270 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
282 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
271 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
283 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
272 return NULL;
284 return NULL;
273 }
285 }
274 }
286 }
275 }
287 }
276 return NULL;
288 return NULL;
277 }
289 }
278
290
279 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
291 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
280 {
292 {
281 int argc = args?PyTuple_Size(args):0;
293 int argc = args?PyTuple_Size(args):0;
282
294
283 #ifdef PYTHONQT_DEBUG
295 #ifdef PYTHONQT_DEBUG
284 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
296 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
285 #endif
297 #endif
286
298
287 PyObject* r = NULL;
299 PyObject* r = NULL;
288 bool ok = false;
300 bool ok = false;
289 if (directReturnValuePointer) {
301 if (directReturnValuePointer) {
290 *directReturnValuePointer = NULL;
302 *directReturnValuePointer = NULL;
291 }
303 }
292 if (info->nextInfo()) {
304 if (info->nextInfo()) {
293 // overloaded slot call, try on all slots with strict conversion first
305 // overloaded slot call, try on all slots with strict conversion first
294 bool strict = true;
306 bool strict = true;
295 PythonQtSlotInfo* i = info;
307 PythonQtSlotInfo* i = info;
296 while (i) {
308 while (i) {
297 bool skipFirst = i->isInstanceDecorator();
309 bool skipFirst = i->isInstanceDecorator();
298 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
310 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
299 PyErr_Clear();
311 PyErr_Clear();
300 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
312 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
301 if (PyErr_Occurred() || ok) break;
313 if (PyErr_Occurred() || ok) break;
302 }
314 }
303 i = i->nextInfo();
315 i = i->nextInfo();
304 if (!i) {
316 if (!i) {
305 if (strict) {
317 if (strict) {
306 // one more run without being strict
318 // one more run without being strict
307 strict = false;
319 strict = false;
308 i = info;
320 i = info;
309 }
321 }
310 }
322 }
311 }
323 }
312 if (!ok && !PyErr_Occurred()) {
324 if (!ok && !PyErr_Occurred()) {
313 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
325 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
314 PythonQtSlotInfo* i = info;
326 PythonQtSlotInfo* i = info;
315 while (i) {
327 while (i) {
316 e += QString(i->fullSignature()) + "\n";
328 e += QString(i->fullSignature()) + "\n";
317 i = i->nextInfo();
329 i = i->nextInfo();
318 }
330 }
319 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
331 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
320 }
332 }
321 } else {
333 } else {
322 // simple (non-overloaded) slot call
334 // simple (non-overloaded) slot call
323 bool skipFirst = info->isInstanceDecorator();
335 bool skipFirst = info->isInstanceDecorator();
324 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
336 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
325 PyErr_Clear();
337 PyErr_Clear();
326 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
338 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
327 if (!ok && !PyErr_Occurred()) {
339 if (!ok && !PyErr_Occurred()) {
328 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
340 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
329 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
341 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
330 }
342 }
331 } else {
343 } else {
332 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
344 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
333 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
345 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
334 }
346 }
335 }
347 }
336
348
337 return r;
349 return r;
338 }
350 }
339
351
340 PyObject *
352 PyObject *
341 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
353 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
342 {
354 {
343 PythonQtSlotFunctionObject *op;
355 PythonQtSlotFunctionObject *op;
344 op = pythonqtslot_free_list;
356 op = pythonqtslot_free_list;
345 if (op != NULL) {
357 if (op != NULL) {
346 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
358 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
347 PyObject_INIT(op, &PythonQtSlotFunction_Type);
359 PyObject_INIT(op, &PythonQtSlotFunction_Type);
348 }
360 }
349 else {
361 else {
350 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
362 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
351 if (op == NULL)
363 if (op == NULL)
352 return NULL;
364 return NULL;
353 }
365 }
354 op->m_ml = ml;
366 op->m_ml = ml;
355 Py_XINCREF(self);
367 Py_XINCREF(self);
356 op->m_self = self;
368 op->m_self = self;
357 Py_XINCREF(module);
369 Py_XINCREF(module);
358 op->m_module = module;
370 op->m_module = module;
359 PyObject_GC_Track(op);
371 PyObject_GC_Track(op);
360 return (PyObject *)op;
372 return (PyObject *)op;
361 }
373 }
362
374
363 PythonQtSlotInfo*
375 PythonQtSlotInfo*
364 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
376 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
365 {
377 {
366 if (!PythonQtSlotFunction_Check(op)) {
378 if (!PythonQtSlotFunction_Check(op)) {
367 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
379 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
368 return NULL;
380 return NULL;
369 }
381 }
370 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
382 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
371 }
383 }
372
384
373 PyObject *
385 PyObject *
374 PythonQtSlotFunction_GetSelf(PyObject *op)
386 PythonQtSlotFunction_GetSelf(PyObject *op)
375 {
387 {
376 if (!PythonQtSlotFunction_Check(op)) {
388 if (!PythonQtSlotFunction_Check(op)) {
377 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
389 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
378 return NULL;
390 return NULL;
379 }
391 }
380 return ((PythonQtSlotFunctionObject *)op) -> m_self;
392 return ((PythonQtSlotFunctionObject *)op) -> m_self;
381 }
393 }
382
394
383 /* Methods (the standard built-in methods, that is) */
395 /* Methods (the standard built-in methods, that is) */
384
396
385 static void
397 static void
386 meth_dealloc(PythonQtSlotFunctionObject *m)
398 meth_dealloc(PythonQtSlotFunctionObject *m)
387 {
399 {
388 PyObject_GC_UnTrack(m);
400 PyObject_GC_UnTrack(m);
389 Py_XDECREF(m->m_self);
401 Py_XDECREF(m->m_self);
390 Py_XDECREF(m->m_module);
402 Py_XDECREF(m->m_module);
391 m->m_self = (PyObject *)pythonqtslot_free_list;
403 m->m_self = (PyObject *)pythonqtslot_free_list;
392 pythonqtslot_free_list = m;
404 pythonqtslot_free_list = m;
393 }
405 }
394
406
395 static PyObject *
407 static PyObject *
396 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
408 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
397 {
409 {
398 Py_INCREF(Py_None);
410 Py_INCREF(Py_None);
399 return Py_None;
411 return Py_None;
400 }
412 }
401
413
402 static PyObject *
414 static PyObject *
403 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
415 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
404 {
416 {
405 return PyString_FromString(m->m_ml->metaMethod()->signature());
417 return PyString_FromString(m->m_ml->metaMethod()->signature());
406 }
418 }
407
419
408 static int
420 static int
409 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
421 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
410 {
422 {
411 int err;
423 int err;
412 if (m->m_self != NULL) {
424 if (m->m_self != NULL) {
413 err = visit(m->m_self, arg);
425 err = visit(m->m_self, arg);
414 if (err)
426 if (err)
415 return err;
427 return err;
416 }
428 }
417 if (m->m_module != NULL) {
429 if (m->m_module != NULL) {
418 err = visit(m->m_module, arg);
430 err = visit(m->m_module, arg);
419 if (err)
431 if (err)
420 return err;
432 return err;
421 }
433 }
422 return 0;
434 return 0;
423 }
435 }
424
436
425 static PyObject *
437 static PyObject *
426 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
438 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
427 {
439 {
428 PyObject *self;
440 PyObject *self;
429 if (PyEval_GetRestricted()) {
441 if (PyEval_GetRestricted()) {
430 PyErr_SetString(PyExc_RuntimeError,
442 PyErr_SetString(PyExc_RuntimeError,
431 "method.__self__ not accessible in restricted mode");
443 "method.__self__ not accessible in restricted mode");
432 return NULL;
444 return NULL;
433 }
445 }
434 self = m->m_self;
446 self = m->m_self;
435 if (self == NULL)
447 if (self == NULL)
436 self = Py_None;
448 self = Py_None;
437 Py_INCREF(self);
449 Py_INCREF(self);
438 return self;
450 return self;
439 }
451 }
440
452
441 static PyGetSetDef meth_getsets [] = {
453 static PyGetSetDef meth_getsets [] = {
442 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
454 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
443 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
455 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
444 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
456 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
445 {NULL, NULL, NULL,NULL},
457 {NULL, NULL, NULL,NULL},
446 };
458 };
447
459
448 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
460 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
449 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
461 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
450 #endif
462 #endif
451
463
452 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
464 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
453
465
454 static PyMemberDef meth_members[] = {
466 static PyMemberDef meth_members[] = {
455 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
467 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
456 {NULL}
468 {NULL}
457 };
469 };
458
470
471 static PyObject *PythonQtSlotFunction_parameterTypes(PythonQtSlotFunctionObject* type)
472 {
473 return PythonQtMemberFunction_parameterTypes(type->m_ml);
474 }
475
476 static PyObject *PythonQtSlotFunction_parameterNames(PythonQtSlotFunctionObject* type)
477 {
478 return PythonQtMemberFunction_parameterNames(type->m_ml);
479 }
480
481 static PyObject *PythonQtSlotFunction_typeName(PythonQtSlotFunctionObject* type)
482 {
483 return PythonQtMemberFunction_typeName(type->m_ml);
484 }
485
486 PyObject *PythonQtMemberFunction_parameterTypes(PythonQtSlotInfo* theInfo)
487 {
488 PythonQtSlotInfo* info = theInfo;
489 int count = 0;
490 while (info) {
491 info = info->nextInfo();
492 count++;
493 }
494 info = theInfo;
495 PyObject* result = PyTuple_New(count);
496 for (int j = 0;j<count;j++) {
497 QList<QByteArray> types = info->metaMethod()->parameterTypes();
498 PyObject* tuple = PyTuple_New(types.count());
499 for (int i = 0; i<types.count();i++) {
500 PyTuple_SET_ITEM(tuple, i, PyString_FromString(types.at(i).constData()));
501 }
502 info = info->nextInfo();
503 PyTuple_SET_ITEM(result, j, tuple);
504 }
505 return result;
506 }
507
508 PyObject *PythonQtMemberFunction_parameterNames(PythonQtSlotInfo* theInfo)
509 {
510 PythonQtSlotInfo* info = theInfo;
511 int count = 0;
512 while (info) {
513 info = info->nextInfo();
514 count++;
515 }
516 info = theInfo;
517 PyObject* result = PyTuple_New(count);
518 for (int j = 0;j<count;j++) {
519 QList<QByteArray> names = info->metaMethod()->parameterNames();
520 PyObject* tuple = PyTuple_New(names.count());
521 for (int i = 0; i<names.count();i++) {
522 PyTuple_SET_ITEM(tuple, i, PyString_FromString(names.at(i).constData()));
523 }
524 info = info->nextInfo();
525 PyTuple_SET_ITEM(result, j, tuple);
526 }
527 return result;
528 }
529
530 PyObject *PythonQtMemberFunction_typeName(PythonQtSlotInfo* theInfo)
531 {
532 PythonQtSlotInfo* info = theInfo;
533 int count = 0;
534 while (info) {
535 info = info->nextInfo();
536 count++;
537 }
538 info = theInfo;
539 PyObject* result = PyTuple_New(count);
540 for (int j = 0;j<count;j++) {
541 QByteArray name = info->metaMethod()->typeName();
542 PyTuple_SET_ITEM(result, j, PyString_FromString(name.constData()));
543 info = info->nextInfo();
544 }
545 return result;
546 }
547
548 static PyMethodDef meth_methods[] = {
549 {"parameterTypes", (PyCFunction)PythonQtSlotFunction_parameterTypes, METH_NOARGS,
550 "Returns a tuple of tuples of the C++ parameter types for all overloads of the slot"
551 },
552 {"parameterNames", (PyCFunction)PythonQtSlotFunction_parameterNames, METH_NOARGS,
553 "Returns a tuple of tuples of the C++ parameter type names (if available), for all overloads of the slot"
554 },
555 {"typeName", (PyCFunction)PythonQtSlotFunction_typeName, METH_NOARGS,
556 "Returns a tuple of the C++ return value types of each slot overload"
557 },
558 {NULL, NULL, 0 , NULL} /* Sentinel */
559 };
560
459 static PyObject *
561 static PyObject *
460 meth_repr(PythonQtSlotFunctionObject *f)
562 meth_repr(PythonQtSlotFunctionObject *f)
461 {
563 {
462 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
564 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
463 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
565 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
464 return PyString_FromFormat("<unbound qt slot %s of %s type>",
566 return PyString_FromFormat("<unbound qt slot %s of %s type>",
465 f->m_ml->slotName().data(),
567 f->m_ml->slotName().data(),
466 self->classInfo()->className());
568 self->classInfo()->className());
467 } else {
569 } else {
468 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
570 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
469 f->m_ml->slotName().data(),
571 f->m_ml->slotName().data(),
470 f->m_self->ob_type->tp_name,
572 f->m_self->ob_type->tp_name,
471 f->m_self);
573 f->m_self);
472 }
574 }
473 }
575 }
474
576
475 static int
577 static int
476 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
578 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
477 {
579 {
478 if (a->m_self != b->m_self)
580 if (a->m_self != b->m_self)
479 return (a->m_self < b->m_self) ? -1 : 1;
581 return (a->m_self < b->m_self) ? -1 : 1;
480 if (a->m_ml == b->m_ml)
582 if (a->m_ml == b->m_ml)
481 return 0;
583 return 0;
482 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
584 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
483 return -1;
585 return -1;
484 else
586 else
485 return 1;
587 return 1;
486 }
588 }
487
589
488 static long
590 static long
489 meth_hash(PythonQtSlotFunctionObject *a)
591 meth_hash(PythonQtSlotFunctionObject *a)
490 {
592 {
491 long x,y;
593 long x,y;
492 if (a->m_self == NULL)
594 if (a->m_self == NULL)
493 x = 0;
595 x = 0;
494 else {
596 else {
495 x = PyObject_Hash(a->m_self);
597 x = PyObject_Hash(a->m_self);
496 if (x == -1)
598 if (x == -1)
497 return -1;
599 return -1;
498 }
600 }
499 y = _Py_HashPointer((void*)(a->m_ml));
601 y = _Py_HashPointer((void*)(a->m_ml));
500 if (y == -1)
602 if (y == -1)
501 return -1;
603 return -1;
502 x ^= y;
604 x ^= y;
503 if (x == -1)
605 if (x == -1)
504 x = -2;
606 x = -2;
505 return x;
607 return x;
506 }
608 }
507
609
508
610
509 PyTypeObject PythonQtSlotFunction_Type = {
611 PyTypeObject PythonQtSlotFunction_Type = {
510 PyObject_HEAD_INIT(&PyType_Type)
612 PyObject_HEAD_INIT(&PyType_Type)
511 0,
613 0,
512 "builtin_qt_slot",
614 "builtin_qt_slot",
513 sizeof(PythonQtSlotFunctionObject),
615 sizeof(PythonQtSlotFunctionObject),
514 0,
616 0,
515 (destructor)meth_dealloc, /* tp_dealloc */
617 (destructor)meth_dealloc, /* tp_dealloc */
516 0, /* tp_print */
618 0, /* tp_print */
517 0, /* tp_getattr */
619 0, /* tp_getattr */
518 0, /* tp_setattr */
620 0, /* tp_setattr */
519 (cmpfunc)meth_compare, /* tp_compare */
621 (cmpfunc)meth_compare, /* tp_compare */
520 (reprfunc)meth_repr, /* tp_repr */
622 (reprfunc)meth_repr, /* tp_repr */
521 0, /* tp_as_number */
623 0, /* tp_as_number */
522 0, /* tp_as_sequence */
624 0, /* tp_as_sequence */
523 0, /* tp_as_mapping */
625 0, /* tp_as_mapping */
524 (hashfunc)meth_hash, /* tp_hash */
626 (hashfunc)meth_hash, /* tp_hash */
525 PythonQtSlotFunction_Call, /* tp_call */
627 PythonQtSlotFunction_Call, /* tp_call */
526 0, /* tp_str */
628 0, /* tp_str */
527 PyObject_GenericGetAttr, /* tp_getattro */
629 PyObject_GenericGetAttr, /* tp_getattro */
528 0, /* tp_setattro */
630 0, /* tp_setattro */
529 0, /* tp_as_buffer */
631 0, /* tp_as_buffer */
530 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
632 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
531 0, /* tp_doc */
633 0, /* tp_doc */
532 (traverseproc)meth_traverse, /* tp_traverse */
634 (traverseproc)meth_traverse, /* tp_traverse */
533 0, /* tp_clear */
635 0, /* tp_clear */
534 0, /* tp_richcompare */
636 0, /* tp_richcompare */
535 0, /* tp_weaklistoffset */
637 0, /* tp_weaklistoffset */
536 0, /* tp_iter */
638 0, /* tp_iter */
537 0, /* tp_iternext */
639 0, /* tp_iternext */
538 0, /* tp_methods */
640 meth_methods, /* tp_methods */
539 meth_members, /* tp_members */
641 meth_members, /* tp_members */
540 meth_getsets, /* tp_getset */
642 meth_getsets, /* tp_getset */
541 0, /* tp_base */
643 0, /* tp_base */
542 0, /* tp_dict */
644 0, /* tp_dict */
543 };
645 };
544
646
545 /* Clear out the free list */
647 /* Clear out the free list */
546
648
547 void
649 void
548 PythonQtSlotFunction_Fini(void)
650 PythonQtSlotFunction_Fini(void)
549 {
651 {
550 while (pythonqtslot_free_list) {
652 while (pythonqtslot_free_list) {
551 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
653 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
552 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
654 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
553 PyObject_GC_Del(v);
655 PyObject_GC_Del(v);
554 }
656 }
555 }
657 }
556
658
@@ -1,81 +1,85
1 #ifndef _PYTHONQTSLOT_H
1 #ifndef _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSlot.h
38 // \file PythonQtSlot.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtPythonInclude.h"
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include "structmember.h"
48 #include "structmember.h"
49
49
50 class PythonQtSlotInfo;
50 class PythonQtSlotInfo;
51
51
52 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
52 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
53
53
54 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
54 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
55
55
56 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
56 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
57 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
57 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
58
58
59 /* Macros for direct access to these values. Type checks are *not*
59 /* Macros for direct access to these values. Type checks are *not*
60 done, so use with care. */
60 done, so use with care. */
61 #define PythonQtSlotFunction_GET_SELF(func) \
61 #define PythonQtSlotFunction_GET_SELF(func) \
62 (((PythonQtSlotFunctionObject *)func) -> m_self)
62 (((PythonQtSlotFunctionObject *)func) -> m_self)
63
63
64 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
64 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
65
65
66 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
66 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
67
67
68
69 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
70 PyObject *);
69 PyObject *);
71
70
71 PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw);
72 PyObject *PythonQtMemberFunction_parameterTypes(PythonQtSlotInfo* theInfo);
73 PyObject *PythonQtMemberFunction_parameterNames(PythonQtSlotInfo* theInfo);
74 PyObject *PythonQtMemberFunction_typeName(PythonQtSlotInfo* theInfo);
75
72 //! defines a python object that stores a Qt slot info
76 //! defines a python object that stores a Qt slot info
73 typedef struct {
77 typedef struct {
74 PyObject_HEAD
78 PyObject_HEAD
75 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
79 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
76 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
80 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
77 PyObject *m_module; /* The __module__ attribute, can be anything */
81 PyObject *m_module; /* The __module__ attribute, can be anything */
78 } PythonQtSlotFunctionObject;
82 } PythonQtSlotFunctionObject;
79
83
80
84
81 #endif
85 #endif
@@ -1,315 +1,318
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtStdDecorators.cpp
35 // \file PythonQtStdDecorators.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdDecorators.h"
42 #include "PythonQtStdDecorators.h"
43 #include "PythonQt.h"
43 #include "PythonQt.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include <QCoreApplication>
45 #include <QCoreApplication>
46
46
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
48 {
48 {
49 bool result = false;
49 bool result = false;
50 QByteArray signalTmp;
50 QByteArray signalTmp;
51 char first = signal.at(0);
51 char first = signal.at(0);
52 if (first>='0' && first<='9') {
52 if (first>='0' && first<='9') {
53 signalTmp = signal;
53 signalTmp = signal;
54 } else {
54 } else {
55 signalTmp = "2" + signal;
55 signalTmp = "2" + signal;
56 }
56 }
57
57
58 if (sender) {
58 if (sender) {
59 result = PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
59 result = PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
60 if (!result) {
60 if (!result) {
61 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
61 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
62 qWarning("PythonQt: QObject::connect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
62 qWarning("PythonQt: QObject::connect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
63 }
63 }
64 }
64 }
65 }
65 }
66 return result;
66 return result;
67 }
67 }
68
68
69 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
69 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
70 {
70 {
71 bool r = false;
71 bool r = false;
72 if (sender && receiver) {
72 if (sender && receiver) {
73 QByteArray signalTmp;
73 QByteArray signalTmp;
74 char first = signal.at(0);
74 char first = signal.at(0);
75 if (first>='0' && first<='9') {
75 if (first>='0' && first<='9') {
76 signalTmp = signal;
76 signalTmp = signal;
77 } else {
77 } else {
78 signalTmp = "2" + signal;
78 signalTmp = "2" + signal;
79 }
79 }
80
80
81 QByteArray slotTmp;
81 QByteArray slotTmp;
82 first = slot.at(0);
82 first = slot.at(0);
83 if (first>='0' && first<='9') {
83 if (first>='0' && first<='9') {
84 slotTmp = slot;
84 slotTmp = slot;
85 } else {
85 } else {
86 slotTmp = "1" + slot;
86 slotTmp = "1" + slot;
87 }
87 }
88 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
88 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
89 }
89 }
90 return r;
90 return r;
91 }
91 }
92
92
93 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
93 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
94 {
94 {
95 bool result = false;
95 bool result = false;
96 QByteArray signalTmp;
96 QByteArray signalTmp;
97 char first = signal.at(0);
97 char first = signal.at(0);
98 if (first>='0' && first<='9') {
98 if (first>='0' && first<='9') {
99 signalTmp = signal;
99 signalTmp = signal;
100 } else {
100 } else {
101 signalTmp = "2" + signal;
101 signalTmp = "2" + signal;
102 }
102 }
103 if (sender) {
103 if (sender) {
104 result = PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
104 result = PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
105 if (callable == NULL) {
106 result |= QObject::disconnect(sender, signalTmp, NULL, NULL);
107 }
105 if (!result) {
108 if (!result) {
106 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
109 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
107 qWarning("PythonQt: QObject::disconnect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
110 qWarning("PythonQt: QObject::disconnect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
108 }
111 }
109 }
112 }
110 }
113 }
111 return result;
114 return result;
112 }
115 }
113
116
114 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
117 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
115 {
118 {
116 bool r = false;
119 bool r = false;
117 if (sender && receiver) {
120 if (sender && receiver) {
118 QByteArray signalTmp;
121 QByteArray signalTmp;
119 char first = signal.at(0);
122 char first = signal.at(0);
120 if (first>='0' && first<='9') {
123 if (first>='0' && first<='9') {
121 signalTmp = signal;
124 signalTmp = signal;
122 } else {
125 } else {
123 signalTmp = "2" + signal;
126 signalTmp = "2" + signal;
124 }
127 }
125
128
126 QByteArray slotTmp;
129 QByteArray slotTmp;
127 first = slot.at(0);
130 first = slot.at(0);
128 if (first>='0' && first<='9') {
131 if (first>='0' && first<='9') {
129 slotTmp = slot;
132 slotTmp = slot;
130 } else {
133 } else {
131 slotTmp = "1" + slot;
134 slotTmp = "1" + slot;
132 }
135 }
133
136
134 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
137 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
135 }
138 }
136 return r;
139 return r;
137 }
140 }
138
141
139 QObject* PythonQtStdDecorators::parent(QObject* o) {
142 QObject* PythonQtStdDecorators::parent(QObject* o) {
140 return o->parent();
143 return o->parent();
141 }
144 }
142
145
143 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
146 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
144 {
147 {
145 o->setParent(parent);
148 o->setParent(parent);
146 }
149 }
147
150
148 const QObjectList* PythonQtStdDecorators::children(QObject* o)
151 const QObjectList* PythonQtStdDecorators::children(QObject* o)
149 {
152 {
150 return &o->children();
153 return &o->children();
151 }
154 }
152
155
153 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
156 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
154 {
157 {
155 return o->setProperty(name, value);
158 return o->setProperty(name, value);
156 }
159 }
157
160
158 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
161 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
159 {
162 {
160 return o->property(name);
163 return o->property(name);
161 }
164 }
162
165
163 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
166 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
164 {
167 {
165 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
168 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
166 }
169 }
167
170
168 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
171 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
169 {
172 {
170 const QMetaObject* meta = NULL;
173 const QMetaObject* meta = NULL;
171 const char* typeName = NULL;
174 const char* typeName = NULL;
172
175
173 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
176 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
174 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
177 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
175 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
178 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
176 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
179 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
177 } else if (PyString_Check(type)) {
180 } else if (PyString_Check(type)) {
178 typeName = PyString_AsString(type);
181 typeName = PyString_AsString(type);
179 }
182 }
180
183
181 if (!typeName && !meta)
184 if (!typeName && !meta)
182 return NULL;
185 return NULL;
183
186
184 return findChild(parent, typeName, meta, name);
187 return findChild(parent, typeName, meta, name);
185 }
188 }
186
189
187 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
190 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
188 {
191 {
189 const QMetaObject* meta = NULL;
192 const QMetaObject* meta = NULL;
190 const char* typeName = NULL;
193 const char* typeName = NULL;
191
194
192 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
195 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
193 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
196 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
194 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
197 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
195 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
198 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
196 } else if (PyString_Check(type)) {
199 } else if (PyString_Check(type)) {
197 typeName = PyString_AsString(type);
200 typeName = PyString_AsString(type);
198 }
201 }
199
202
200 QList<QObject*> list;
203 QList<QObject*> list;
201
204
202 if (!typeName && !meta)
205 if (!typeName && !meta)
203 return list;
206 return list;
204
207
205 findChildren(parent, typeName, meta, name, list);
208 findChildren(parent, typeName, meta, name, list);
206
209
207 return list;
210 return list;
208 }
211 }
209
212
210 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
213 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
211 {
214 {
212 const QMetaObject* meta = NULL;
215 const QMetaObject* meta = NULL;
213 const char* typeName = NULL;
216 const char* typeName = NULL;
214
217
215 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
218 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
216 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
219 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
217 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
220 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
218 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
221 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
219 } else if (PyString_Check(type)) {
222 } else if (PyString_Check(type)) {
220 typeName = PyString_AsString(type);
223 typeName = PyString_AsString(type);
221 }
224 }
222
225
223 QList<QObject*> list;
226 QList<QObject*> list;
224
227
225 if (!typeName && !meta)
228 if (!typeName && !meta)
226 return list;
229 return list;
227
230
228 findChildren(parent, typeName, meta, regExp, list);
231 findChildren(parent, typeName, meta, regExp, list);
229
232
230 return list;
233 return list;
231 }
234 }
232
235
233 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
236 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
234 {
237 {
235 const QObjectList &children = parent->children();
238 const QObjectList &children = parent->children();
236
239
237 int i;
240 int i;
238 for (i = 0; i < children.size(); ++i) {
241 for (i = 0; i < children.size(); ++i) {
239 QObject* obj = children.at(i);
242 QObject* obj = children.at(i);
240
243
241 if (!obj)
244 if (!obj)
242 return NULL;
245 return NULL;
243
246
244 // Skip if the name doesn't match.
247 // Skip if the name doesn't match.
245 if (!name.isNull() && obj->objectName() != name)
248 if (!name.isNull() && obj->objectName() != name)
246 continue;
249 continue;
247
250
248 if ((typeName && obj->inherits(typeName)) ||
251 if ((typeName && obj->inherits(typeName)) ||
249 (meta && meta->cast(obj)))
252 (meta && meta->cast(obj)))
250 return obj;
253 return obj;
251 }
254 }
252
255
253 for (i = 0; i < children.size(); ++i) {
256 for (i = 0; i < children.size(); ++i) {
254 QObject* obj = findChild(children.at(i), typeName, meta, name);
257 QObject* obj = findChild(children.at(i), typeName, meta, name);
255
258
256 if (obj != NULL)
259 if (obj != NULL)
257 return obj;
260 return obj;
258 }
261 }
259
262
260 return NULL;
263 return NULL;
261 }
264 }
262
265
263 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
266 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
264 {
267 {
265 const QObjectList& children = parent->children();
268 const QObjectList& children = parent->children();
266 int i;
269 int i;
267
270
268 for (i = 0; i < children.size(); ++i) {
271 for (i = 0; i < children.size(); ++i) {
269 QObject* obj = children.at(i);
272 QObject* obj = children.at(i);
270
273
271 if (!obj)
274 if (!obj)
272 return -1;
275 return -1;
273
276
274 // Skip if the name doesn't match.
277 // Skip if the name doesn't match.
275 if (!name.isNull() && obj->objectName() != name)
278 if (!name.isNull() && obj->objectName() != name)
276 continue;
279 continue;
277
280
278 if ((typeName && obj->inherits(typeName)) ||
281 if ((typeName && obj->inherits(typeName)) ||
279 (meta && meta->cast(obj))) {
282 (meta && meta->cast(obj))) {
280 list += obj;
283 list += obj;
281 }
284 }
282
285
283 if (findChildren(obj, typeName, meta, name, list) < 0)
286 if (findChildren(obj, typeName, meta, name, list) < 0)
284 return -1;
287 return -1;
285 }
288 }
286
289
287 return 0;
290 return 0;
288 }
291 }
289
292
290 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
293 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
291 {
294 {
292 const QObjectList& children = parent->children();
295 const QObjectList& children = parent->children();
293 int i;
296 int i;
294
297
295 for (i = 0; i < children.size(); ++i) {
298 for (i = 0; i < children.size(); ++i) {
296 QObject* obj = children.at(i);
299 QObject* obj = children.at(i);
297
300
298 if (!obj)
301 if (!obj)
299 return -1;
302 return -1;
300
303
301 // Skip if the name doesn't match.
304 // Skip if the name doesn't match.
302 if (regExp.indexIn(obj->objectName()) == -1)
305 if (regExp.indexIn(obj->objectName()) == -1)
303 continue;
306 continue;
304
307
305 if ((typeName && obj->inherits(typeName)) ||
308 if ((typeName && obj->inherits(typeName)) ||
306 (meta && meta->cast(obj))) {
309 (meta && meta->cast(obj))) {
307 list += obj;
310 list += obj;
308 }
311 }
309
312
310 if (findChildren(obj, typeName, meta, regExp, list) < 0)
313 if (findChildren(obj, typeName, meta, regExp, list) < 0)
311 return -1;
314 return -1;
312 }
315 }
313
316
314 return 0;
317 return 0;
315 }
318 }
@@ -1,109 +1,109
1 #ifndef _PYTHONQTSTDDECORATORS_H
1 #ifndef _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtStdDecorators.h
38 // \file PythonQtStdDecorators.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-04
41 // \date 2007-04
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtPythonInclude.h"
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48
48
49 #include <QObject>
49 #include <QObject>
50 #include <QVariantList>
50 #include <QVariantList>
51 #include <QTextDocument>
51 #include <QTextDocument>
52 #include <QColor>
52 #include <QColor>
53 #include <QDateTime>
53 #include <QDateTime>
54 #include <QDate>
54 #include <QDate>
55 #include <QTime>
55 #include <QTime>
56
56
57 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
57 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
58 {
58 {
59 Q_OBJECT
59 Q_OBJECT
60
60
61 public slots:
61 public slots:
62 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
62 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
63 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
64 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL);
65 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
65 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
66
66
67 QObject* parent(QObject* o);
67 QObject* parent(QObject* o);
68 void setParent(QObject* o, QObject* parent);
68 void setParent(QObject* o, QObject* parent);
69
69
70 const QObjectList* children(QObject* o);
70 const QObjectList* children(QObject* o);
71 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
71 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
72 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
72 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
73 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
73 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
74
74
75 bool setProperty(QObject* o, const char* name, const QVariant& value);
75 bool setProperty(QObject* o, const char* name, const QVariant& value);
76 QVariant property(QObject* o, const char* name);
76 QVariant property(QObject* o, const char* name);
77
77
78 double static_Qt_qAbs(double a) { return qAbs(a); }
78 double static_Qt_qAbs(double a) { return qAbs(a); }
79 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
79 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
80 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
80 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
81 // TODO: multi arg qDebug...
81 // TODO: multi arg qDebug...
82 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
82 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
83 // TODO: multi arg qWarning...
83 // TODO: multi arg qWarning...
84 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
84 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
85 // TODO: multi arg qCritical...
85 // TODO: multi arg qCritical...
86 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
86 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
87 // TODO: multi arg qFatal...
87 // TODO: multi arg qFatal...
88 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
88 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
89 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
89 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
90 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
90 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
91 int static_Qt_qRound(double a) { return qRound(a); }
91 int static_Qt_qRound(double a) { return qRound(a); }
92 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
92 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
93 const char* static_Qt_qVersion() { return qVersion(); }
93 const char* static_Qt_qVersion() { return qVersion(); }
94 int static_Qt_qrand() { return qrand(); }
94 int static_Qt_qrand() { return qrand(); }
95 void static_Qt_qsrand(uint a) { qsrand(a); }
95 void static_Qt_qsrand(uint a) { qsrand(a); }
96
96
97 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
97 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
98
98
99 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
99 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
100 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
100 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
101
101
102 private:
102 private:
103 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
103 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
104 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
104 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
105 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
105 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
106 };
106 };
107
107
108
108
109 #endif
109 #endif
@@ -1,45 +1,47
1 DEFINES += PYTHONQT_EXPORTS
1 DEFINES += PYTHONQT_EXPORTS
2
2
3 HEADERS += \
3 HEADERS += \
4 $$PWD/PythonQt.h \
4 $$PWD/PythonQt.h \
5 $$PWD/PythonQtStdDecorators.h \
5 $$PWD/PythonQtStdDecorators.h \
6 $$PWD/PythonQtClassInfo.h \
6 $$PWD/PythonQtClassInfo.h \
7 $$PWD/PythonQtImporter.h \
7 $$PWD/PythonQtImporter.h \
8 $$PWD/PythonQtObjectPtr.h \
8 $$PWD/PythonQtObjectPtr.h \
9 $$PWD/PythonQtSignal.h \
9 $$PWD/PythonQtSlot.h \
10 $$PWD/PythonQtSlot.h \
10 $$PWD/PythonQtStdIn.h \
11 $$PWD/PythonQtStdIn.h \
11 $$PWD/PythonQtStdOut.h \
12 $$PWD/PythonQtStdOut.h \
12 $$PWD/PythonQtMisc.h \
13 $$PWD/PythonQtMisc.h \
13 $$PWD/PythonQtMethodInfo.h \
14 $$PWD/PythonQtMethodInfo.h \
14 $$PWD/PythonQtImportFileInterface.h \
15 $$PWD/PythonQtImportFileInterface.h \
15 $$PWD/PythonQtConversion.h \
16 $$PWD/PythonQtConversion.h \
16 $$PWD/PythonQtSignalReceiver.h \
17 $$PWD/PythonQtSignalReceiver.h \
17 $$PWD/PythonQtInstanceWrapper.h \
18 $$PWD/PythonQtInstanceWrapper.h \
18 $$PWD/PythonQtClassWrapper.h \
19 $$PWD/PythonQtClassWrapper.h \
19 $$PWD/PythonQtCppWrapperFactory.h \
20 $$PWD/PythonQtCppWrapperFactory.h \
20 $$PWD/PythonQtQFileImporter.h \
21 $$PWD/PythonQtQFileImporter.h \
21 $$PWD/PythonQtQFileImporter.h \
22 $$PWD/PythonQtQFileImporter.h \
22 $$PWD/PythonQtVariants.h \
23 $$PWD/PythonQtVariants.h \
23 $$PWD/gui/PythonQtScriptingConsole.h \
24 $$PWD/gui/PythonQtScriptingConsole.h \
24 $$PWD/PythonQtSystem.h
25 $$PWD/PythonQtSystem.h
25
26
26 SOURCES += \
27 SOURCES += \
27 $$PWD/PythonQtStdDecorators.cpp \
28 $$PWD/PythonQtStdDecorators.cpp \
28 $$PWD/PythonQt.cpp \
29 $$PWD/PythonQt.cpp \
29 $$PWD/PythonQtClassInfo.cpp \
30 $$PWD/PythonQtClassInfo.cpp \
30 $$PWD/PythonQtImporter.cpp \
31 $$PWD/PythonQtImporter.cpp \
31 $$PWD/PythonQtObjectPtr.cpp \
32 $$PWD/PythonQtObjectPtr.cpp \
32 $$PWD/PythonQtStdIn.cpp \
33 $$PWD/PythonQtStdIn.cpp \
33 $$PWD/PythonQtStdOut.cpp \
34 $$PWD/PythonQtStdOut.cpp \
35 $$PWD/PythonQtSignal.cpp \
34 $$PWD/PythonQtSlot.cpp \
36 $$PWD/PythonQtSlot.cpp \
35 $$PWD/PythonQtMisc.cpp \
37 $$PWD/PythonQtMisc.cpp \
36 $$PWD/PythonQtMethodInfo.cpp \
38 $$PWD/PythonQtMethodInfo.cpp \
37 $$PWD/PythonQtConversion.cpp \
39 $$PWD/PythonQtConversion.cpp \
38 $$PWD/PythonQtSignalReceiver.cpp \
40 $$PWD/PythonQtSignalReceiver.cpp \
39 $$PWD/PythonQtInstanceWrapper.cpp \
41 $$PWD/PythonQtInstanceWrapper.cpp \
40 $$PWD/PythonQtQFileImporter.cpp \
42 $$PWD/PythonQtQFileImporter.cpp \
41 $$PWD/PythonQtClassWrapper.cpp \
43 $$PWD/PythonQtClassWrapper.cpp \
42 $$PWD/gui/PythonQtScriptingConsole.cpp \
44 $$PWD/gui/PythonQtScriptingConsole.cpp \
43
45
44 include($$PWD/../generated_cpp/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin.pri)
46 include($$PWD/../generated_cpp/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin.pri)
45 include($$PWD/../generated_cpp/com_trolltech_qt_gui_builtin/com_trolltech_qt_gui_builtin.pri)
47 include($$PWD/../generated_cpp/com_trolltech_qt_gui_builtin/com_trolltech_qt_gui_builtin.pri)
General Comments 0
You need to be logged in to leave comments. Login now