##// END OF EJS Templates
updated to upstream state in MeVisLab repository...
florianlink -
r157:78da86ccde11
parent child
Show More
@@ -1,1230 +1,1258
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 "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
61
61
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 {
63 {
64 if (!_self) {
64 if (!_self) {
65 _self = new PythonQt(flags, pythonQtModuleName);
65 _self = new PythonQt(flags, pythonQtModuleName);
66
66
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69
69
70 PythonQtRegisterToolClassesTemplateConverter(int);
70 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(float);
71 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(double);
72 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 // TODO: which other POD types should be available for QList etc.
77 // TODO: which other POD types should be available for QList etc.
78
78
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80
80
81 PythonQt_init_QtCoreBuiltin(NULL);
81 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
83
83
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99
99
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117
117
118
118
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 for (unsigned int i = 0;i<16; i++) {
124 for (unsigned int i = 0;i<16; i++) {
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 if (obj) {
126 if (obj) {
127 PyModule_AddObject(pack, names[i], obj);
127 PyModule_AddObject(pack, names[i], obj);
128 Py_INCREF(obj);
128 Py_INCREF(obj);
129 PyModule_AddObject(pack2, names[i], obj);
129 PyModule_AddObject(pack2, names[i], obj);
130 } else {
130 } else {
131 std::cerr << "method not found " << names[i];
131 std::cerr << "method not found " << names[i];
132 }
132 }
133 }
133 }
134 }
134 }
135 }
135 }
136
136
137 void PythonQt::cleanup()
137 void PythonQt::cleanup()
138 {
138 {
139 if (_self) {
139 if (_self) {
140 delete _self;
140 delete _self;
141 _self = NULL;
141 _self = NULL;
142 }
142 }
143 }
143 }
144
144
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
146 {
146 {
147 _p = new PythonQtPrivate;
147 _p = new PythonQtPrivate;
148 _p->_initFlags = flags;
148 _p->_initFlags = flags;
149
149
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
151
151
152 if ((flags & PythonAlreadyInitialized) == 0) {
152 if ((flags & PythonAlreadyInitialized) == 0) {
153 Py_SetProgramName("PythonQt");
153 Py_SetProgramName("PythonQt");
154 if (flags & IgnoreSiteModule) {
154 if (flags & IgnoreSiteModule) {
155 // this prevents the automatic importing of Python site files
155 // this prevents the automatic importing of Python site files
156 Py_NoSiteFlag = 1;
156 Py_NoSiteFlag = 1;
157 }
157 }
158 Py_Initialize();
158 Py_Initialize();
159 }
159 }
160
160
161 // add our own python object types for qt object slots
161 // add our own python object types for qt object slots
162 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
162 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
163 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
163 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
164 }
164 }
165 Py_INCREF(&PythonQtSlotFunction_Type);
165 Py_INCREF(&PythonQtSlotFunction_Type);
166
166
167 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
167 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
168 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
168 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
169 // add our own python object types for classes
169 // add our own python object types for classes
170 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
170 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
171 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
171 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
172 }
172 }
173 Py_INCREF(&PythonQtClassWrapper_Type);
173 Py_INCREF(&PythonQtClassWrapper_Type);
174
174
175 // add our own python object types for CPP instances
175 // add our own python object types for CPP instances
176 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
176 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
177 PythonQt::handleError();
177 PythonQt::handleError();
178 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 }
179 }
180 Py_INCREF(&PythonQtInstanceWrapper_Type);
180 Py_INCREF(&PythonQtInstanceWrapper_Type);
181
181
182 // add our own python object types for redirection of stdout
182 // add our own python object types for redirection of stdout
183 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
183 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
184 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
185 }
186 Py_INCREF(&PythonQtStdOutRedirectType);
186 Py_INCREF(&PythonQtStdOutRedirectType);
187
187
188 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
188 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
189
189
190 _p->setupSharedLibrarySuffixes();
190 _p->setupSharedLibrarySuffixes();
191
191
192 }
192 }
193
193
194 PythonQt::~PythonQt() {
194 PythonQt::~PythonQt() {
195 delete _p;
195 delete _p;
196 _p = NULL;
196 _p = NULL;
197 }
197 }
198
198
199 PythonQtPrivate::~PythonQtPrivate() {
199 PythonQtPrivate::~PythonQtPrivate() {
200 delete _defaultImporter;
200 delete _defaultImporter;
201 _defaultImporter = NULL;
201 _defaultImporter = NULL;
202
202
203 {
203 {
204 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
204 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
205 while (i.hasNext()) {
205 while (i.hasNext()) {
206 delete i.next().value();
206 delete i.next().value();
207 }
207 }
208 }
208 }
209 PythonQtConv::global_valueStorage.clear();
209 PythonQtConv::global_valueStorage.clear();
210 PythonQtConv::global_ptrStorage.clear();
210 PythonQtConv::global_ptrStorage.clear();
211 PythonQtConv::global_variantStorage.clear();
211 PythonQtConv::global_variantStorage.clear();
212
212
213 PythonQtMethodInfo::cleanupCachedMethodInfos();
213 PythonQtMethodInfo::cleanupCachedMethodInfos();
214 }
214 }
215
215
216 PythonQtImportFileInterface* PythonQt::importInterface()
216 PythonQtImportFileInterface* PythonQt::importInterface()
217 {
217 {
218 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
218 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
219 }
219 }
220
220
221 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
221 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
222 {
222 {
223 if (_self->_p->_noLongerWrappedCB) {
223 if (_self->_p->_noLongerWrappedCB) {
224 (*_self->_p->_noLongerWrappedCB)(o);
224 (*_self->_p->_noLongerWrappedCB)(o);
225 };
225 };
226 }
226 }
227
227
228 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
228 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
229 {
229 {
230 _p->registerClass(metaobject, package, wrapperCreator, shell);
230 _p->registerClass(metaobject, package, wrapperCreator, shell);
231 }
231 }
232
232
233 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
233 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
234 {
234 {
235 // we register all classes in the hierarchy
235 // we register all classes in the hierarchy
236 const QMetaObject* m = metaobject;
236 const QMetaObject* m = metaobject;
237 bool first = true;
237 bool first = true;
238 while (m) {
238 while (m) {
239 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
239 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
240 if (!info->pythonQtClassWrapper()) {
240 if (!info->pythonQtClassWrapper()) {
241 info->setTypeSlots(typeSlots);
241 info->setTypeSlots(typeSlots);
242 info->setupQObject(m);
242 info->setupQObject(m);
243 createPythonQtClassWrapper(info, package, module);
243 createPythonQtClassWrapper(info, package, module);
244 if (m->superClass()) {
244 if (m->superClass()) {
245 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
245 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
246 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
246 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
247 }
247 }
248 } else if (first && module) {
249 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
250 // since it might have been placed into "private" earlier on.
251 // If the wrapper was already added to module before, it is just readded, which does no harm.
252 PyObject* classWrapper = info->pythonQtClassWrapper();
253 // AddObject steals a reference, so we need to INCREF
254 Py_INCREF(classWrapper);
255 PyModule_AddObject(module, info->className(), classWrapper);
248 }
256 }
249 if (first) {
257 if (first) {
250 first = false;
258 first = false;
251 if (wrapperCreator) {
259 if (wrapperCreator) {
252 info->setDecoratorProvider(wrapperCreator);
260 info->setDecoratorProvider(wrapperCreator);
253 }
261 }
254 if (shell) {
262 if (shell) {
255 info->setShellSetInstanceWrapperCB(shell);
263 info->setShellSetInstanceWrapperCB(shell);
256 }
264 }
257 }
265 }
258 m = m->superClass();
266 m = m->superClass();
259 }
267 }
260 }
268 }
261
269
262 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
270 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
263 {
271 {
264 PyObject* pack = module?module:packageByName(package);
272 PyObject* pack = module?module:packageByName(package);
265 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
273 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
266 PyModule_AddObject(pack, info->className(), pyobj);
274 PyModule_AddObject(pack, info->className(), pyobj);
267 if (!module && package && strncmp(package,"Qt",2)==0) {
275 if (!module && package && strncmp(package,"Qt",2)==0) {
268 // since PyModule_AddObject steals the reference, we need a incref once more...
276 // since PyModule_AddObject steals the reference, we need a incref once more...
269 Py_INCREF(pyobj);
277 Py_INCREF(pyobj);
270 // put all qt objects into Qt as well
278 // put all qt objects into Qt as well
271 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
279 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
272 }
280 }
273 info->setPythonQtClassWrapper(pyobj);
281 info->setPythonQtClassWrapper(pyobj);
274 }
282 }
275
283
276 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
284 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
277 {
285 {
278 if (!obj) {
286 if (!obj) {
279 Py_INCREF(Py_None);
287 Py_INCREF(Py_None);
280 return Py_None;
288 return Py_None;
281 }
289 }
282 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
290 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
283 if (!wrap) {
291 if (!wrap) {
284 // smuggling it in...
292 // smuggling it in...
285 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
293 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
286 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
294 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
287 registerClass(obj->metaObject());
295 registerClass(obj->metaObject());
288 classInfo = _knownClassInfos.value(obj->metaObject()->className());
296 classInfo = _knownClassInfos.value(obj->metaObject()->className());
289 }
297 }
290 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
298 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
291 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
299 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
292 } else {
300 } else {
293 Py_INCREF(wrap);
301 Py_INCREF(wrap);
294 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
302 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
295 }
303 }
296 return (PyObject*)wrap;
304 return (PyObject*)wrap;
297 }
305 }
298
306
299 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
307 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
300 {
308 {
301 if (!ptr) {
309 if (!ptr) {
302 Py_INCREF(Py_None);
310 Py_INCREF(Py_None);
303 return Py_None;
311 return Py_None;
304 }
312 }
305
313
306 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
314 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
307 if (!wrap) {
315 if (!wrap) {
308 PythonQtClassInfo* info = _knownClassInfos.value(name);
316 PythonQtClassInfo* info = _knownClassInfos.value(name);
309 if (!info) {
317 if (!info) {
310 // maybe it is a PyObject, which we can return directly
318 // maybe it is a PyObject, which we can return directly
311 if (name == "PyObject") {
319 if (name == "PyObject") {
312 PyObject* p = (PyObject*)ptr;
320 PyObject* p = (PyObject*)ptr;
313 Py_INCREF(p);
321 Py_INCREF(p);
314 return p;
322 return p;
315 }
323 }
316
324
317 // we do not know the metaobject yet, but we might know it by it's name:
325 // we do not know the metaobject yet, but we might know it by it's name:
318 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
326 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
319 // yes, we know it, so we can convert to QObject
327 // yes, we know it, so we can convert to QObject
320 QObject* qptr = (QObject*)ptr;
328 QObject* qptr = (QObject*)ptr;
321 registerClass(qptr->metaObject());
329 registerClass(qptr->metaObject());
322 info = _knownClassInfos.value(qptr->metaObject()->className());
330 info = _knownClassInfos.value(qptr->metaObject()->className());
323 }
331 }
324 }
332 }
325 if (info && info->isQObject()) {
333 if (info && info->isQObject()) {
326 QObject* qptr = (QObject*)ptr;
334 QObject* qptr = (QObject*)ptr;
327 // if the object is a derived object, we want to switch the class info to the one of the derived class:
335 // if the object is a derived object, we want to switch the class info to the one of the derived class:
328 if (name!=(qptr->metaObject()->className())) {
336 if (name!=(qptr->metaObject()->className())) {
329 registerClass(qptr->metaObject());
337 registerClass(qptr->metaObject());
330 info = _knownClassInfos.value(qptr->metaObject()->className());
338 info = _knownClassInfos.value(qptr->metaObject()->className());
331 }
339 }
332 wrap = createNewPythonQtInstanceWrapper(qptr, info);
340 wrap = createNewPythonQtInstanceWrapper(qptr, info);
333 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
341 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
334 return (PyObject*)wrap;
342 return (PyObject*)wrap;
335 }
343 }
336
344
337 // not a known QObject, so try our wrapper factory:
345 // not a known QObject, so try our wrapper factory:
338 QObject* wrapper = NULL;
346 QObject* wrapper = NULL;
339 for (int i=0; i<_cppWrapperFactories.size(); i++) {
347 for (int i=0; i<_cppWrapperFactories.size(); i++) {
340 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
348 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
341 if (wrapper) {
349 if (wrapper) {
342 break;
350 break;
343 }
351 }
344 }
352 }
345
353
346 if (info) {
354 if (info) {
347 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
355 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
348 ptr = info->castDownIfPossible(ptr, &info);
356 ptr = info->castDownIfPossible(ptr, &info);
349 }
357 }
350
358
351 if (!info || info->pythonQtClassWrapper()==NULL) {
359 if (!info || info->pythonQtClassWrapper()==NULL) {
352 // still unknown, register as CPP class
360 // still unknown, register as CPP class
353 registerCPPClass(name.constData());
361 registerCPPClass(name.constData());
354 info = _knownClassInfos.value(name);
362 info = _knownClassInfos.value(name);
355 }
363 }
356 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
364 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
357 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
365 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
358 info->setMetaObject(wrapper->metaObject());
366 info->setMetaObject(wrapper->metaObject());
359 }
367 }
360 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
368 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
361 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
369 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
362 } else {
370 } else {
363 Py_INCREF(wrap);
371 Py_INCREF(wrap);
364 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
372 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
365 }
373 }
366 return (PyObject*)wrap;
374 return (PyObject*)wrap;
367 }
375 }
368
376
369 PyObject* PythonQtPrivate::dummyTuple() {
377 PyObject* PythonQtPrivate::dummyTuple() {
370 static PyObject* dummyTuple = NULL;
378 static PyObject* dummyTuple = NULL;
371 if (dummyTuple==NULL) {
379 if (dummyTuple==NULL) {
372 dummyTuple = PyTuple_New(1);
380 dummyTuple = PyTuple_New(1);
373 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
381 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
374 }
382 }
375 return dummyTuple;
383 return dummyTuple;
376 }
384 }
377
385
378
386
379 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
387 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
380 // call the associated class type to create a new instance...
388 // call the associated class type to create a new instance...
381 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
389 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
382
390
383 result->setQObject(obj);
391 result->setQObject(obj);
384 result->_wrappedPtr = wrappedPtr;
392 result->_wrappedPtr = wrappedPtr;
385 result->_ownedByPythonQt = false;
393 result->_ownedByPythonQt = false;
386 result->_useQMetaTypeDestroy = false;
394 result->_useQMetaTypeDestroy = false;
387
395
388 if (wrappedPtr) {
396 if (wrappedPtr) {
389 _wrappedObjects.insert(wrappedPtr, result);
397 _wrappedObjects.insert(wrappedPtr, result);
390 } else {
398 } else {
391 _wrappedObjects.insert(obj, result);
399 _wrappedObjects.insert(obj, result);
392 if (obj->parent()== NULL && _wrappedCB) {
400 if (obj->parent()== NULL && _wrappedCB) {
393 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
401 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
394 (*_wrappedCB)(obj);
402 (*_wrappedCB)(obj);
395 }
403 }
396 }
404 }
397 return result;
405 return result;
398 }
406 }
399
407
400 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
408 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
401 PythonQtClassWrapper* result;
409 PythonQtClassWrapper* result;
402
410
403 PyObject* className = PyString_FromString(info->className());
411 PyObject* className = PyString_FromString(info->className());
404
412
405 PyObject* baseClasses = PyTuple_New(1);
413 PyObject* baseClasses = PyTuple_New(1);
406 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
414 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
407
415
408 PyObject* typeDict = PyDict_New();
416 PyObject* typeDict = PyDict_New();
409 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
417 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
410 PyDict_SetItemString(typeDict, "__module__", moduleName);
418 PyDict_SetItemString(typeDict, "__module__", moduleName);
411
419
412 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
420 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
413
421
414 // set the class info so that PythonQtClassWrapper_new can read it
422 // set the class info so that PythonQtClassWrapper_new can read it
415 _currentClassInfoForClassWrapperCreation = info;
423 _currentClassInfoForClassWrapperCreation = info;
416 // create the new type object by calling the type
424 // create the new type object by calling the type
417 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
425 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
418
426
419 Py_DECREF(baseClasses);
427 Py_DECREF(baseClasses);
420 Py_DECREF(typeDict);
428 Py_DECREF(typeDict);
421 Py_DECREF(args);
429 Py_DECREF(args);
422 Py_DECREF(className);
430 Py_DECREF(className);
423
431
424 return result;
432 return result;
425 }
433 }
426
434
427 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
435 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
428 {
436 {
429 PyObject* args = Py_BuildValue("(i)", enumValue);
437 PyObject* args = Py_BuildValue("(i)", enumValue);
430 PyObject* result = PyObject_Call(enumType, args, NULL);
438 PyObject* result = PyObject_Call(enumType, args, NULL);
431 Py_DECREF(args);
439 Py_DECREF(args);
432 return result;
440 return result;
433 }
441 }
434
442
435 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
443 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
436 PyObject* result;
444 PyObject* result;
437
445
438 PyObject* className = PyString_FromString(enumName);
446 PyObject* className = PyString_FromString(enumName);
439
447
440 PyObject* baseClasses = PyTuple_New(1);
448 PyObject* baseClasses = PyTuple_New(1);
441 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
449 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
442
450
443 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
451 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
444 PyObject* typeDict = PyDict_New();
452 PyObject* typeDict = PyDict_New();
445 PyDict_SetItemString(typeDict, "__module__", module);
453 PyDict_SetItemString(typeDict, "__module__", module);
446
454
447 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
455 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
448
456
449 // create the new int derived type object by calling the core type
457 // create the new int derived type object by calling the core type
450 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
458 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
451
459
452 Py_DECREF(baseClasses);
460 Py_DECREF(baseClasses);
453 Py_DECREF(typeDict);
461 Py_DECREF(typeDict);
454 Py_DECREF(args);
462 Py_DECREF(args);
455 Py_DECREF(className);
463 Py_DECREF(className);
456
464
457 return result;
465 return result;
458 }
466 }
459
467
460 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
468 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
461 {
469 {
462 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
470 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
463 if (!r) {
471 if (!r) {
464 r = new PythonQtSignalReceiver(obj);
472 r = new PythonQtSignalReceiver(obj);
465 _p->_signalReceivers.insert(obj, r);
473 _p->_signalReceivers.insert(obj, r);
466 }
474 }
467 return r;
475 return r;
468 }
476 }
469
477
470 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
478 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
471 {
479 {
472 bool flag = false;
480 bool flag = false;
473 PythonQtObjectPtr callable = lookupCallable(module, objectname);
481 PythonQtObjectPtr callable = lookupCallable(module, objectname);
474 if (callable) {
482 if (callable) {
475 PythonQtSignalReceiver* r = getSignalReceiver(obj);
483 PythonQtSignalReceiver* r = getSignalReceiver(obj);
476 flag = r->addSignalHandler(signal, callable);
484 flag = r->addSignalHandler(signal, callable);
477 if (!flag) {
485 if (!flag) {
478 // signal not found
486 // signal not found
479 }
487 }
480 } else {
488 } else {
481 // callable not found
489 // callable not found
482 }
490 }
483 return flag;
491 return flag;
484 }
492 }
485
493
486 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
494 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
487 {
495 {
488 bool flag = false;
496 bool flag = false;
489 PythonQtSignalReceiver* r = getSignalReceiver(obj);
497 PythonQtSignalReceiver* r = getSignalReceiver(obj);
490 if (r) {
498 if (r) {
491 flag = r->addSignalHandler(signal, receiver);
499 flag = r->addSignalHandler(signal, receiver);
492 }
500 }
493 return flag;
501 return flag;
494 }
502 }
495
503
496 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
504 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
497 {
505 {
498 bool flag = false;
506 bool flag = false;
499 PythonQtObjectPtr callable = lookupCallable(module, objectname);
507 PythonQtObjectPtr callable = lookupCallable(module, objectname);
500 if (callable) {
508 if (callable) {
501 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
509 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
502 if (r) {
510 if (r) {
503 flag = r->removeSignalHandler(signal, callable);
511 flag = r->removeSignalHandler(signal, callable);
504 }
512 }
505 } else {
513 } else {
506 // callable not found
514 // callable not found
507 }
515 }
508 return flag;
516 return flag;
509 }
517 }
510
518
511 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
519 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
512 {
520 {
513 bool flag = false;
521 bool flag = false;
514 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
522 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
515 if (r) {
523 if (r) {
516 flag = r->removeSignalHandler(signal, receiver);
524 flag = r->removeSignalHandler(signal, receiver);
517 }
525 }
518 return flag;
526 return flag;
519 }
527 }
520
528
521 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
529 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
522 {
530 {
523 PythonQtObjectPtr p = lookupObject(module, name);
531 PythonQtObjectPtr p = lookupObject(module, name);
524 if (p) {
532 if (p) {
525 if (PyCallable_Check(p)) {
533 if (PyCallable_Check(p)) {
526 return p;
534 return p;
527 }
535 }
528 }
536 }
529 PyErr_Clear();
537 PyErr_Clear();
530 return NULL;
538 return NULL;
531 }
539 }
532
540
533 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
541 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
534 {
542 {
535 QStringList l = name.split('.');
543 QStringList l = name.split('.');
536 PythonQtObjectPtr p = module;
544 PythonQtObjectPtr p = module;
537 PythonQtObjectPtr prev;
545 PythonQtObjectPtr prev;
538 QString s;
546 QString s;
539 QByteArray b;
547 QByteArray b;
540 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
548 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
541 prev = p;
549 prev = p;
542 b = (*i).toLatin1();
550 b = (*i).toLatin1();
543 if (PyDict_Check(p)) {
551 if (PyDict_Check(p)) {
544 p = PyDict_GetItemString(p, b.data());
552 p = PyDict_GetItemString(p, b.data());
545 } else {
553 } else {
546 p.setNewRef(PyObject_GetAttrString(p, b.data()));
554 p.setNewRef(PyObject_GetAttrString(p, b.data()));
547 }
555 }
548 }
556 }
549 PyErr_Clear();
557 PyErr_Clear();
550 return p;
558 return p;
551 }
559 }
552
560
553 PythonQtObjectPtr PythonQt::getMainModule() {
561 PythonQtObjectPtr PythonQt::getMainModule() {
554 //both borrowed
562 //both borrowed
555 PythonQtObjectPtr dict = PyImport_GetModuleDict();
563 PythonQtObjectPtr dict = PyImport_GetModuleDict();
556 return PyDict_GetItemString(dict, "__main__");
564 return PyDict_GetItemString(dict, "__main__");
557 }
565 }
558
566
559 PythonQtObjectPtr PythonQt::importModule(const QString& name)
567 PythonQtObjectPtr PythonQt::importModule(const QString& name)
560 {
568 {
561 PythonQtObjectPtr mod;
569 PythonQtObjectPtr mod;
562 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
570 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
563 return mod;
571 return mod;
564 }
572 }
565
573
566
574
567 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
575 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
568 QVariant result;
576 QVariant result;
569 if (pycode) {
577 if (pycode) {
570 PyObject* dict = NULL;
578 PyObject* dict = NULL;
571 if (PyModule_Check(object)) {
579 if (PyModule_Check(object)) {
572 dict = PyModule_GetDict(object);
580 dict = PyModule_GetDict(object);
573 } else if (PyDict_Check(object)) {
581 } else if (PyDict_Check(object)) {
574 dict = object;
582 dict = object;
575 }
583 }
576 PyObject* r = NULL;
584 PyObject* r = NULL;
577 if (dict) {
585 if (dict) {
578 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
586 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
579 }
587 }
580 if (r) {
588 if (r) {
581 result = PythonQtConv::PyObjToQVariant(r);
589 result = PythonQtConv::PyObjToQVariant(r);
582 Py_DECREF(r);
590 Py_DECREF(r);
583 } else {
591 } else {
584 handleError();
592 handleError();
585 }
593 }
586 } else {
594 } else {
587 handleError();
595 handleError();
588 }
596 }
589 return result;
597 return result;
590 }
598 }
591
599
592 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
600 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
593 {
601 {
594 QVariant result;
602 QVariant result;
595 PythonQtObjectPtr p;
603 PythonQtObjectPtr p;
596 PyObject* dict = NULL;
604 PyObject* dict = NULL;
597 if (PyModule_Check(object)) {
605 if (PyModule_Check(object)) {
598 dict = PyModule_GetDict(object);
606 dict = PyModule_GetDict(object);
599 } else if (PyDict_Check(object)) {
607 } else if (PyDict_Check(object)) {
600 dict = object;
608 dict = object;
601 }
609 }
602 if (dict) {
610 if (dict) {
603 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
611 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
604 }
612 }
605 if (p) {
613 if (p) {
606 result = PythonQtConv::PyObjToQVariant(p);
614 result = PythonQtConv::PyObjToQVariant(p);
607 } else {
615 } else {
608 handleError();
616 handleError();
609 }
617 }
610 return result;
618 return result;
611 }
619 }
612
620
613 void PythonQt::evalFile(PyObject* module, const QString& filename)
621 void PythonQt::evalFile(PyObject* module, const QString& filename)
614 {
622 {
615 PythonQtObjectPtr code = parseFile(filename);
623 PythonQtObjectPtr code = parseFile(filename);
616 if (code) {
624 if (code) {
617 evalCode(module, code);
625 evalCode(module, code);
618 } else {
626 } else {
619 handleError();
627 handleError();
620 }
628 }
621 }
629 }
622
630
623 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
631 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
624 {
632 {
625 PythonQtObjectPtr p;
633 PythonQtObjectPtr p;
626 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
634 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
627 if (!p) {
635 if (!p) {
628 handleError();
636 handleError();
629 }
637 }
630 return p;
638 return p;
631 }
639 }
632
640
633 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
641 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
634 {
642 {
635 PythonQtObjectPtr code = parseFile(filename);
643 PythonQtObjectPtr code = parseFile(filename);
636 PythonQtObjectPtr module = _p->createModule(name, code);
644 PythonQtObjectPtr module = _p->createModule(name, code);
637 return module;
645 return module;
638 }
646 }
639
647
640 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
648 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
641 {
649 {
642 PyErr_Clear();
650 PyErr_Clear();
643 QString scriptCode = script;
651 QString scriptCode = script;
644 if (scriptCode.isEmpty()) {
652 if (scriptCode.isEmpty()) {
645 // we always need at least a linefeed
653 // we always need at least a linefeed
646 scriptCode = "\n";
654 scriptCode = "\n";
647 }
655 }
648 PythonQtObjectPtr pycode;
656 PythonQtObjectPtr pycode;
649 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
657 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
650 PythonQtObjectPtr module = _p->createModule(name, pycode);
658 PythonQtObjectPtr module = _p->createModule(name, pycode);
651 return module;
659 return module;
652 }
660 }
653
661
654 PythonQtObjectPtr PythonQt::createUniqueModule()
662 PythonQtObjectPtr PythonQt::createUniqueModule()
655 {
663 {
656 static QString pyQtStr("PythonQt_module");
664 static QString pyQtStr("PythonQt_module");
657 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
665 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
658 return createModuleFromScript(moduleName);
666 return createModuleFromScript(moduleName);
659 }
667 }
660
668
661 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
669 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
662 {
670 {
663 if (PyModule_Check(object)) {
671 if (PyModule_Check(object)) {
664 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
672 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
665 } else if (PyDict_Check(object)) {
673 } else if (PyDict_Check(object)) {
666 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
674 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
667 } else {
675 } else {
668 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
676 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
669 }
677 }
670 }
678 }
671
679
672 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
680 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
673 {
681 {
674 if (PyModule_Check(object)) {
682 if (PyModule_Check(object)) {
675 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
683 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
676 } else if (PyDict_Check(object)) {
684 } else if (PyDict_Check(object)) {
677 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
685 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
678 } else {
686 } else {
679 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
687 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
680 }
688 }
681 }
689 }
682
690
683 void PythonQt::removeVariable(PyObject* object, const QString& name)
691 void PythonQt::removeVariable(PyObject* object, const QString& name)
684 {
692 {
685 if (PyDict_Check(object)) {
693 if (PyDict_Check(object)) {
686 PyDict_DelItemString(object, name.toLatin1().data());
694 PyDict_DelItemString(object, name.toLatin1().data());
687 } else {
695 } else {
688 PyObject_DelAttrString(object, name.toLatin1().data());
696 PyObject_DelAttrString(object, name.toLatin1().data());
689 }
697 }
690 }
698 }
691
699
692 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
700 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
693 {
701 {
694 QVariant result;
702 QVariant result;
695 PythonQtObjectPtr obj = lookupObject(object, objectname);
703 PythonQtObjectPtr obj = lookupObject(object, objectname);
696 if (obj) {
704 if (obj) {
697 result = PythonQtConv::PyObjToQVariant(obj);
705 result = PythonQtConv::PyObjToQVariant(obj);
698 }
706 }
699 return result;
707 return result;
700 }
708 }
701
709
702 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
710 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
703 {
711 {
704 QStringList results;
712 QStringList results;
705
713
706 PythonQtObjectPtr object;
714 PythonQtObjectPtr object;
707 if (objectname.isEmpty()) {
715 if (objectname.isEmpty()) {
708 object = module;
716 object = module;
709 } else {
717 } else {
710 object = lookupObject(module, objectname);
718 object = lookupObject(module, objectname);
711 if (!object && type == CallOverloads) {
719 if (!object && type == CallOverloads) {
712 PyObject* dict = lookupObject(module, "__builtins__");
720 PyObject* dict = lookupObject(module, "__builtins__");
713 if (dict) {
721 if (dict) {
714 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
722 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
715 }
723 }
716 }
724 }
717 }
725 }
718
726
719 if (object) {
727 if (object) {
720 if (type == CallOverloads) {
728 if (type == CallOverloads) {
721 if (PythonQtSlotFunction_Check(object)) {
729 if (PythonQtSlotFunction_Check(object)) {
722 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
730 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
723 PythonQtSlotInfo* info = o->m_ml;
731 PythonQtSlotInfo* info = o->m_ml;
724
732
725 while (info) {
733 while (info) {
726 results << info->fullSignature();
734 results << info->fullSignature();
727 info = info->nextInfo();
735 info = info->nextInfo();
728 }
736 }
729 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
737 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
730 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
738 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
731 PythonQtSlotInfo* info = o->classInfo()->constructors();
739 PythonQtSlotInfo* info = o->classInfo()->constructors();
732
740
733 while (info) {
741 while (info) {
734 results << info->fullSignature();
742 results << info->fullSignature();
735 info = info->nextInfo();
743 info = info->nextInfo();
736 }
744 }
737 } else {
745 } else {
738 //TODO: use pydoc!
746 //TODO: use pydoc!
739 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
747 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
740 if (doc) {
748 if (doc) {
741 results << PyString_AsString(doc);
749 results << PyString_AsString(doc);
742 Py_DECREF(doc);
750 Py_DECREF(doc);
743 }
751 }
744 }
752 }
745 } else {
753 } else {
746 PyObject* keys = NULL;
754 PyObject* keys = NULL;
747 bool isDict = false;
755 bool isDict = false;
748 if (PyDict_Check(object)) {
756 if (PyDict_Check(object)) {
749 keys = PyDict_Keys(object);
757 keys = PyDict_Keys(object);
750 isDict = true;
758 isDict = true;
751 } else {
759 } else {
752 keys = PyObject_Dir(object);
760 keys = PyObject_Dir(object);
753 }
761 }
754 if (keys) {
762 if (keys) {
755 int count = PyList_Size(keys);
763 int count = PyList_Size(keys);
756 PyObject* key;
764 PyObject* key;
757 PyObject* value;
765 PyObject* value;
758 QString keystr;
766 QString keystr;
759 for (int i = 0;i<count;i++) {
767 for (int i = 0;i<count;i++) {
760 key = PyList_GetItem(keys,i);
768 key = PyList_GetItem(keys,i);
761 if (isDict) {
769 if (isDict) {
762 value = PyDict_GetItem(object, key);
770 value = PyDict_GetItem(object, key);
763 Py_INCREF(value);
771 Py_INCREF(value);
764 } else {
772 } else {
765 value = PyObject_GetAttr(object, key);
773 value = PyObject_GetAttr(object, key);
766 }
774 }
767 if (!value) continue;
775 if (!value) continue;
768 keystr = PyString_AsString(key);
776 keystr = PyString_AsString(key);
769 static const QString underscoreStr("__tmp");
777 static const QString underscoreStr("__tmp");
770 if (!keystr.startsWith(underscoreStr)) {
778 if (!keystr.startsWith(underscoreStr)) {
771 switch (type) {
779 switch (type) {
772 case Anything:
780 case Anything:
773 results << keystr;
781 results << keystr;
774 break;
782 break;
775 case Class:
783 case Class:
776 if (value->ob_type == &PyClass_Type) {
784 if (value->ob_type == &PyClass_Type) {
777 results << keystr;
785 results << keystr;
778 }
786 }
779 break;
787 break;
780 case Variable:
788 case Variable:
781 if (value->ob_type != &PyClass_Type
789 if (value->ob_type != &PyClass_Type
782 && value->ob_type != &PyCFunction_Type
790 && value->ob_type != &PyCFunction_Type
783 && value->ob_type != &PyFunction_Type
791 && value->ob_type != &PyFunction_Type
784 && value->ob_type != &PyModule_Type
792 && value->ob_type != &PyModule_Type
785 ) {
793 ) {
786 results << keystr;
794 results << keystr;
787 }
795 }
788 break;
796 break;
789 case Function:
797 case Function:
790 if (value->ob_type == &PyFunction_Type ||
798 if (value->ob_type == &PyFunction_Type ||
791 value->ob_type == &PyMethod_Type
799 value->ob_type == &PyMethod_Type
792 ) {
800 ) {
793 results << keystr;
801 results << keystr;
794 }
802 }
795 break;
803 break;
796 case Module:
804 case Module:
797 if (value->ob_type == &PyModule_Type) {
805 if (value->ob_type == &PyModule_Type) {
798 results << keystr;
806 results << keystr;
799 }
807 }
800 break;
808 break;
801 default:
809 default:
802 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
810 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
803 }
811 }
804 }
812 }
805 Py_DECREF(value);
813 Py_DECREF(value);
806 }
814 }
807 Py_DECREF(keys);
815 Py_DECREF(keys);
808 }
816 }
809 }
817 }
810 }
818 }
811 return results;
819 return results;
812 }
820 }
813
821
814 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
822 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
815 {
823 {
816 PythonQtObjectPtr callable = lookupCallable(object, name);
824 PythonQtObjectPtr callable = lookupCallable(object, name);
817 if (callable) {
825 if (callable) {
818 return call(callable, args);
826 return call(callable, args);
819 } else {
827 } else {
820 return QVariant();
828 return QVariant();
821 }
829 }
822 }
830 }
823
831
824 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
832 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
825 {
833 {
826 QVariant r;
834 QVariant r;
827 PythonQtObjectPtr result;
835 PythonQtObjectPtr result;
828 result.setNewRef(callAndReturnPyObject(callable, args));
836 result.setNewRef(callAndReturnPyObject(callable, args));
829 if (result) {
837 if (result) {
830 r = PythonQtConv::PyObjToQVariant(result);
838 r = PythonQtConv::PyObjToQVariant(result);
831 } else {
839 } else {
832 PythonQt::self()->handleError();
840 PythonQt::self()->handleError();
833 }
841 }
834 return r;
842 return r;
835 }
843 }
836
844
837 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
845 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
838 {
846 {
839 PyObject* result = NULL;
847 PyObject* result = NULL;
840 if (callable) {
848 if (callable) {
841 PythonQtObjectPtr pargs;
849 PythonQtObjectPtr pargs;
842 int count = args.size();
850 int count = args.size();
843 if (count>0) {
851 if (count>0) {
844 pargs.setNewRef(PyTuple_New(count));
852 pargs.setNewRef(PyTuple_New(count));
845 }
853 }
846 bool err = false;
854 bool err = false;
847 // transform QVariants to Python
855 // transform QVariants to Python
848 for (int i = 0; i < count; i++) {
856 for (int i = 0; i < count; i++) {
849 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
857 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
850 if (arg) {
858 if (arg) {
851 // steals reference, no unref
859 // steals reference, no unref
852 PyTuple_SetItem(pargs, i,arg);
860 PyTuple_SetItem(pargs, i,arg);
853 } else {
861 } else {
854 err = true;
862 err = true;
855 break;
863 break;
856 }
864 }
857 }
865 }
858
866
859 if (!err) {
867 if (!err) {
860 PyErr_Clear();
868 PyErr_Clear();
861 result = PyObject_CallObject(callable, pargs);
869 result = PyObject_CallObject(callable, pargs);
862 }
870 }
863 }
871 }
864 return result;
872 return result;
865 }
873 }
866
874
867 void PythonQt::addInstanceDecorators(QObject* o)
875 void PythonQt::addInstanceDecorators(QObject* o)
868 {
876 {
869 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
877 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
870 }
878 }
871
879
872 void PythonQt::addClassDecorators(QObject* o)
880 void PythonQt::addClassDecorators(QObject* o)
873 {
881 {
874 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
882 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
875 }
883 }
876
884
877 void PythonQt::addDecorators(QObject* o)
885 void PythonQt::addDecorators(QObject* o)
878 {
886 {
879 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
887 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
880 }
888 }
881
889
882 void PythonQt::registerQObjectClassNames(const QStringList& names)
890 void PythonQt::registerQObjectClassNames(const QStringList& names)
883 {
891 {
884 _p->registerQObjectClassNames(names);
892 _p->registerQObjectClassNames(names);
885 }
893 }
886
894
887 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
895 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
888 {
896 {
889 _p->_importInterface = importInterface;
897 _p->_importInterface = importInterface;
890 PythonQtImport::init();
898 PythonQtImport::init();
891 }
899 }
892
900
893 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
901 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
894 {
902 {
895 _p->_importIgnorePaths = paths;
903 _p->_importIgnorePaths = paths;
896 }
904 }
897
905
898 const QStringList& PythonQt::getImporterIgnorePaths()
906 const QStringList& PythonQt::getImporterIgnorePaths()
899 {
907 {
900 return _p->_importIgnorePaths;
908 return _p->_importIgnorePaths;
901 }
909 }
902
910
903 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
911 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
904 {
912 {
905 _p->_cppWrapperFactories.append(factory);
913 _p->_cppWrapperFactories.append(factory);
906 }
914 }
907
915
908 //---------------------------------------------------------------------------------------------------
916 //---------------------------------------------------------------------------------------------------
909 PythonQtPrivate::PythonQtPrivate()
917 PythonQtPrivate::PythonQtPrivate()
910 {
918 {
911 _importInterface = NULL;
919 _importInterface = NULL;
912 _defaultImporter = new PythonQtQFileImporter;
920 _defaultImporter = new PythonQtQFileImporter;
913 _noLongerWrappedCB = NULL;
921 _noLongerWrappedCB = NULL;
914 _wrappedCB = NULL;
922 _wrappedCB = NULL;
915 _currentClassInfoForClassWrapperCreation = NULL;
923 _currentClassInfoForClassWrapperCreation = NULL;
924 _profilingCB = NULL;
916 }
925 }
917
926
918 void PythonQtPrivate::setupSharedLibrarySuffixes()
927 void PythonQtPrivate::setupSharedLibrarySuffixes()
919 {
928 {
920 _sharedLibrarySuffixes.clear();
929 _sharedLibrarySuffixes.clear();
921 PythonQtObjectPtr imp;
930 PythonQtObjectPtr imp;
922 imp.setNewRef(PyImport_ImportModule("imp"));
931 imp.setNewRef(PyImport_ImportModule("imp"));
923 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
932 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
924 QVariant result = imp.call("get_suffixes");
933 QVariant result = imp.call("get_suffixes");
934 #ifdef __linux
935 #ifdef _DEBUG
936 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
937 // This is a workaround, because python does not append the '_d' suffix on Linux
938 // and would always load the release library otherwise.
939 _sharedLibrarySuffixes << "_d.so";
940 #endif
941 #endif
925 foreach (QVariant entry, result.toList()) {
942 foreach (QVariant entry, result.toList()) {
926 QVariantList suffixEntry = entry.toList();
943 QVariantList suffixEntry = entry.toList();
927 if (suffixEntry.count()==3) {
944 if (suffixEntry.count()==3) {
928 int code = suffixEntry.at(2).toInt();
945 int code = suffixEntry.at(2).toInt();
929 if (code == cExtensionCode) {
946 if (code == cExtensionCode) {
930 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
947 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
931 }
948 }
932 }
949 }
933 }
950 }
934 }
951 }
935
952
936 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
953 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
937 {
954 {
938 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
955 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
939 _currentClassInfoForClassWrapperCreation = NULL;
956 _currentClassInfoForClassWrapperCreation = NULL;
940 return info;
957 return info;
941 }
958 }
942
959
943 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
960 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
944 {
961 {
945 o->setParent(this);
962 o->setParent(this);
946 int numMethods = o->metaObject()->methodCount();
963 int numMethods = o->metaObject()->methodCount();
947 for (int i = 0; i < numMethods; i++) {
964 for (int i = 0; i < numMethods; i++) {
948 QMetaMethod m = o->metaObject()->method(i);
965 QMetaMethod m = o->metaObject()->method(i);
949 if ((m.methodType() == QMetaMethod::Method ||
966 if ((m.methodType() == QMetaMethod::Method ||
950 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
967 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
951 if (qstrncmp(m.signature(), "new_", 4)==0) {
968 if (qstrncmp(m.signature(), "new_", 4)==0) {
952 if ((decoTypes & ConstructorDecorator) == 0) continue;
969 if ((decoTypes & ConstructorDecorator) == 0) continue;
953 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
970 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
954 if (info->parameters().at(0).pointerCount == 1) {
971 if (info->parameters().at(0).pointerCount == 1) {
955 QByteArray signature = m.signature();
972 QByteArray signature = m.signature();
956 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
973 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
957 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
974 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
958 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
975 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
959 classInfo->addConstructor(newSlot);
976 classInfo->addConstructor(newSlot);
960 }
977 }
961 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
978 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
962 if ((decoTypes & DestructorDecorator) == 0) continue;
979 if ((decoTypes & DestructorDecorator) == 0) continue;
963 QByteArray signature = m.signature();
980 QByteArray signature = m.signature();
964 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
981 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
965 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
982 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
966 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
983 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
967 classInfo->setDestructor(newSlot);
984 classInfo->setDestructor(newSlot);
968 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
985 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
969 if ((decoTypes & StaticDecorator) == 0) continue;
986 if ((decoTypes & StaticDecorator) == 0) continue;
970 QByteArray signature = m.signature();
987 QByteArray signature = m.signature();
971 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
988 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
972 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
989 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
973 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
990 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
974 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
991 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
975 classInfo->addDecoratorSlot(newSlot);
992 classInfo->addDecoratorSlot(newSlot);
976 } else {
993 } else {
977 if ((decoTypes & InstanceDecorator) == 0) continue;
994 if ((decoTypes & InstanceDecorator) == 0) continue;
978 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
995 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
979 if (info->parameters().count()>1) {
996 if (info->parameters().count()>1) {
980 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
997 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
981 if (p.pointerCount==1) {
998 if (p.pointerCount==1) {
982 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
999 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
983 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1000 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
984 classInfo->addDecoratorSlot(newSlot);
1001 classInfo->addDecoratorSlot(newSlot);
985 }
1002 }
986 }
1003 }
987 }
1004 }
988 }
1005 }
989 }
1006 }
990 }
1007 }
991
1008
992 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1009 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
993 {
1010 {
994 foreach(QString name, names) {
1011 foreach(QString name, names) {
995 _knownQObjectClassNames.insert(name.toLatin1(), true);
1012 _knownQObjectClassNames.insert(name.toLatin1(), true);
996 }
1013 }
997 }
1014 }
998
1015
999 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1016 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1000 {
1017 {
1001 _signalReceivers.remove(obj);
1018 _signalReceivers.remove(obj);
1002 }
1019 }
1003
1020
1004 bool PythonQt::handleError()
1021 bool PythonQt::handleError()
1005 {
1022 {
1006 bool flag = false;
1023 bool flag = false;
1007 if (PyErr_Occurred()) {
1024 if (PyErr_Occurred()) {
1008
1025
1009 // currently we just print the error and the stderr handler parses the errors
1026 // currently we just print the error and the stderr handler parses the errors
1010 PyErr_Print();
1027 PyErr_Print();
1011
1028
1012 /*
1029 /*
1013 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1030 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1014 PyObject *ptype;
1031 PyObject *ptype;
1015 PyObject *pvalue;
1032 PyObject *pvalue;
1016 PyObject *ptraceback;
1033 PyObject *ptraceback;
1017 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1034 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1018
1035
1019 Py_XDECREF(ptype);
1036 Py_XDECREF(ptype);
1020 Py_XDECREF(pvalue);
1037 Py_XDECREF(pvalue);
1021 Py_XDECREF(ptraceback);
1038 Py_XDECREF(ptraceback);
1022 */
1039 */
1023 PyErr_Clear();
1040 PyErr_Clear();
1024 flag = true;
1041 flag = true;
1025 }
1042 }
1026 return flag;
1043 return flag;
1027 }
1044 }
1028
1045
1029 void PythonQt::addSysPath(const QString& path)
1046 void PythonQt::addSysPath(const QString& path)
1030 {
1047 {
1031 PythonQtObjectPtr sys;
1048 PythonQtObjectPtr sys;
1032 sys.setNewRef(PyImport_ImportModule("sys"));
1049 sys.setNewRef(PyImport_ImportModule("sys"));
1033 PythonQtObjectPtr obj = lookupObject(sys, "path");
1050 PythonQtObjectPtr obj = lookupObject(sys, "path");
1034 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1051 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1035 }
1052 }
1036
1053
1037 void PythonQt::overwriteSysPath(const QStringList& paths)
1054 void PythonQt::overwriteSysPath(const QStringList& paths)
1038 {
1055 {
1039 PythonQtObjectPtr sys;
1056 PythonQtObjectPtr sys;
1040 sys.setNewRef(PyImport_ImportModule("sys"));
1057 sys.setNewRef(PyImport_ImportModule("sys"));
1041 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1058 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1042 }
1059 }
1043
1060
1044 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1061 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1045 {
1062 {
1046 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1063 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1047 }
1064 }
1048
1065
1049 void PythonQt::stdOutRedirectCB(const QString& str)
1066 void PythonQt::stdOutRedirectCB(const QString& str)
1050 {
1067 {
1051 emit PythonQt::self()->pythonStdOut(str);
1068 emit PythonQt::self()->pythonStdOut(str);
1052 }
1069 }
1053
1070
1054 void PythonQt::stdErrRedirectCB(const QString& str)
1071 void PythonQt::stdErrRedirectCB(const QString& str)
1055 {
1072 {
1056 emit PythonQt::self()->pythonStdErr(str);
1073 emit PythonQt::self()->pythonStdErr(str);
1057 }
1074 }
1058
1075
1059 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1076 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1060 {
1077 {
1061 _p->_wrappedCB = cb;
1078 _p->_wrappedCB = cb;
1062 }
1079 }
1063
1080
1064 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1081 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1065 {
1082 {
1066 _p->_noLongerWrappedCB = cb;
1083 _p->_noLongerWrappedCB = cb;
1067 }
1084 }
1068
1085
1086 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1087 {
1088 _p->_profilingCB = cb;
1089 }
1069
1090
1070
1091
1071 static PyMethodDef PythonQtMethods[] = {
1092 static PyMethodDef PythonQtMethods[] = {
1072 {NULL, NULL, 0, NULL}
1093 {NULL, NULL, 0, NULL}
1073 };
1094 };
1074
1095
1075 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1096 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1076 {
1097 {
1077 QByteArray name = "PythonQt";
1098 QByteArray name = "PythonQt";
1078 if (!pythonQtModuleName.isEmpty()) {
1099 if (!pythonQtModuleName.isEmpty()) {
1079 name = pythonQtModuleName;
1100 name = pythonQtModuleName;
1080 }
1101 }
1081 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1102 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1082 _p->_pythonQtModuleName = name;
1103 _p->_pythonQtModuleName = name;
1083
1104
1084 if (redirectStdOut) {
1105 if (redirectStdOut) {
1085 PythonQtObjectPtr sys;
1106 PythonQtObjectPtr sys;
1086 PythonQtObjectPtr out;
1107 PythonQtObjectPtr out;
1087 PythonQtObjectPtr err;
1108 PythonQtObjectPtr err;
1088 sys.setNewRef(PyImport_ImportModule("sys"));
1109 sys.setNewRef(PyImport_ImportModule("sys"));
1089 // create a redirection object for stdout and stderr
1110 // create a redirection object for stdout and stderr
1090 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1111 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1091 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1112 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1092 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1113 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1093 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1114 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1094 // replace the built in file objects with our own objects
1115 // replace the built in file objects with our own objects
1095 PyModule_AddObject(sys, "stdout", out);
1116 PyModule_AddObject(sys, "stdout", out);
1096 PyModule_AddObject(sys, "stderr", err);
1117 PyModule_AddObject(sys, "stderr", err);
1097 }
1118 }
1098 }
1119 }
1099
1120
1100 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1121 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1101 {
1122 {
1102 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1123 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1103 }
1124 }
1104
1125
1105
1126
1106 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1127 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1107 {
1128 {
1108 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1129 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1109 if (!info) {
1130 if (!info) {
1110 info = new PythonQtClassInfo();
1131 info = new PythonQtClassInfo();
1111 info->setupCPPObject(typeName);
1132 info->setupCPPObject(typeName);
1112 _knownClassInfos.insert(typeName, info);
1133 _knownClassInfos.insert(typeName, info);
1113 }
1134 }
1114 return info;
1135 return info;
1115 }
1136 }
1116
1137
1117 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1138 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1118 {
1139 {
1119 _p->addPolymorphicHandler(typeName, cb);
1140 _p->addPolymorphicHandler(typeName, cb);
1120 }
1141 }
1121
1142
1122 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1143 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1123 {
1144 {
1124 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1145 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1125 info->addPolymorphicHandler(cb);
1146 info->addPolymorphicHandler(cb);
1126 }
1147 }
1127
1148
1128 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1149 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1129 {
1150 {
1130 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1151 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1131 }
1152 }
1132
1153
1133 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1154 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1134 {
1155 {
1135 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1156 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1136 if (info) {
1157 if (info) {
1137 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1158 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1138 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1159 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1139 return true;
1160 return true;
1140 } else {
1161 } else {
1141 return false;
1162 return false;
1142 }
1163 }
1143 }
1164 }
1144
1165
1145 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1166 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1146 {
1167 {
1147 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1168 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1148 if (!info->pythonQtClassWrapper()) {
1169 if (!info->pythonQtClassWrapper()) {
1149 info->setTypeSlots(typeSlots);
1170 info->setTypeSlots(typeSlots);
1150 info->setupCPPObject(typeName);
1171 info->setupCPPObject(typeName);
1151 createPythonQtClassWrapper(info, package, module);
1172 createPythonQtClassWrapper(info, package, module);
1152 }
1173 }
1153 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1174 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1154 addParentClass(typeName, parentTypeName, 0);
1175 addParentClass(typeName, parentTypeName, 0);
1155 }
1176 }
1156 if (wrapperCreator) {
1177 if (wrapperCreator) {
1157 info->setDecoratorProvider(wrapperCreator);
1178 info->setDecoratorProvider(wrapperCreator);
1158 }
1179 }
1159 if (shell) {
1180 if (shell) {
1160 info->setShellSetInstanceWrapperCB(shell);
1181 info->setShellSetInstanceWrapperCB(shell);
1161 }
1182 }
1162 }
1183 }
1163
1184
1164 PyObject* PythonQtPrivate::packageByName(const char* name)
1185 PyObject* PythonQtPrivate::packageByName(const char* name)
1165 {
1186 {
1166 if (name==NULL || name[0]==0) {
1187 if (name==NULL || name[0]==0) {
1167 name = "private";
1188 name = "private";
1168 }
1189 }
1169 PyObject* v = _packages.value(name);
1190 PyObject* v = _packages.value(name);
1170 if (!v) {
1191 if (!v) {
1171 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1192 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1172 _packages.insert(name, v);
1193 _packages.insert(name, v);
1173 // AddObject steals the reference, so increment it!
1194 // AddObject steals the reference, so increment it!
1174 Py_INCREF(v);
1195 Py_INCREF(v);
1175 PyModule_AddObject(_pythonQtModule, name, v);
1196 PyModule_AddObject(_pythonQtModule, name, v);
1176 }
1197 }
1177 return v;
1198 return v;
1178 }
1199 }
1179
1200
1180 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1201 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1181 {
1202 {
1182 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;
1203 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;
1183 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1204 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1184 PythonQt::self()->handleError();
1205 PythonQt::self()->handleError();
1185 }
1206 }
1186
1207
1187 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1208 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1188 {
1209 {
1189 if (_p->_initFlags & ExternalHelp) {
1210 if (_p->_initFlags & ExternalHelp) {
1190 emit pythonHelpRequest(QByteArray(info->className()));
1211 emit pythonHelpRequest(QByteArray(info->className()));
1191 return Py_BuildValue("");
1212 return Py_BuildValue("");
1192 } else {
1213 } else {
1193 return PyString_FromString(info->help().toLatin1().data());
1214 return PyString_FromString(info->help().toLatin1().data());
1194 }
1215 }
1195 }
1216 }
1196
1217
1218 void PythonQt::clearNotFoundCachedMembers()
1219 {
1220 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1221 info->clearNotFoundCachedMembers();
1222 }
1223 }
1224
1197 void PythonQtPrivate::removeWrapperPointer(void* obj)
1225 void PythonQtPrivate::removeWrapperPointer(void* obj)
1198 {
1226 {
1199 _wrappedObjects.remove(obj);
1227 _wrappedObjects.remove(obj);
1200 }
1228 }
1201
1229
1202 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1230 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1203 {
1231 {
1204 _wrappedObjects.insert(obj, wrapper);
1232 _wrappedObjects.insert(obj, wrapper);
1205 }
1233 }
1206
1234
1207 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1235 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1208 {
1236 {
1209 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1237 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1210 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1238 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1211 // this is a wrapper whose QObject was already removed due to destruction
1239 // this is a wrapper whose QObject was already removed due to destruction
1212 // so the obj pointer has to be a new QObject with the same address...
1240 // so the obj pointer has to be a new QObject with the same address...
1213 // we remove the old one and set the copy to NULL
1241 // we remove the old one and set the copy to NULL
1214 wrap->_objPointerCopy = NULL;
1242 wrap->_objPointerCopy = NULL;
1215 removeWrapperPointer(obj);
1243 removeWrapperPointer(obj);
1216 wrap = NULL;
1244 wrap = NULL;
1217 }
1245 }
1218 return wrap;
1246 return wrap;
1219 }
1247 }
1220
1248
1221 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1249 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1222 {
1250 {
1223 PythonQtObjectPtr result;
1251 PythonQtObjectPtr result;
1224 if (pycode) {
1252 if (pycode) {
1225 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1253 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1226 } else {
1254 } else {
1227 PythonQt::self()->handleError();
1255 PythonQt::self()->handleError();
1228 }
1256 }
1229 return result;
1257 return result;
1230 }
1258 }
@@ -1,634 +1,656
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 <QObject>
50 #include <QObject>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QList>
52 #include <QList>
53 #include <QHash>
53 #include <QHash>
54 #include <QByteArray>
54 #include <QByteArray>
55 #include <QStringList>
55 #include <QStringList>
56 #include <QtDebug>
56 #include <QtDebug>
57 #include <iostream>
57 #include <iostream>
58
58
59
59
60 class PythonQtClassInfo;
60 class PythonQtClassInfo;
61 class PythonQtPrivate;
61 class PythonQtPrivate;
62 class PythonQtMethodInfo;
62 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
67
67
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
71
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
73
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75
75
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
79 }
79 }
80
80
81 //! callback to create a QObject lazily
81 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
83
84 //! helper template to create a derived QObject class
84 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
86
87 //! The main interface to the Python Qt binding, realized as a singleton
87 //! The main interface to the Python Qt binding, realized as a singleton
88 /*!
88 /*!
89 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
89 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
90 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
90 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
91 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
91 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
92 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
92 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
93 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
93 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
94 code in the scope of a dict.
94 code in the scope of a dict.
95 */
95 */
96 class PYTHONQT_EXPORT PythonQt : public QObject {
96 class PYTHONQT_EXPORT PythonQt : public QObject {
97
97
98 Q_OBJECT
98 Q_OBJECT
99
99
100 public:
100 public:
101
101
102 //! flags that can be passed to PythonQt::init()
102 //! flags that can be passed to PythonQt::init()
103 enum InitFlags {
103 enum InitFlags {
104 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
104 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
105 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
105 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
106 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
106 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
107 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
107 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
108 };
108 };
109
109
110 //! flags that tell PythonQt which operators to expect on the registered type
110 //! flags that tell PythonQt which operators to expect on the registered type
111 enum TypeSlots {
111 enum TypeSlots {
112 Type_Add = 1,
112 Type_Add = 1,
113 Type_Subtract = 1 << 1,
113 Type_Subtract = 1 << 1,
114 Type_Multiply = 1 << 2,
114 Type_Multiply = 1 << 2,
115 Type_Divide = 1 << 3,
115 Type_Divide = 1 << 3,
116 Type_Mod = 1 << 4,
116 Type_Mod = 1 << 4,
117 Type_And = 1 << 5,
117 Type_And = 1 << 5,
118 Type_Or = 1 << 6,
118 Type_Or = 1 << 6,
119 Type_Xor = 1 << 7,
119 Type_Xor = 1 << 7,
120 Type_LShift = 1 << 8,
120 Type_LShift = 1 << 8,
121 Type_RShift = 1 << 9,
121 Type_RShift = 1 << 9,
122
122
123 Type_InplaceAdd = 1 << 10,
123 Type_InplaceAdd = 1 << 10,
124 Type_InplaceSubtract = 1 << 11,
124 Type_InplaceSubtract = 1 << 11,
125 Type_InplaceMultiply = 1 << 12,
125 Type_InplaceMultiply = 1 << 12,
126 Type_InplaceDivide = 1 << 13,
126 Type_InplaceDivide = 1 << 13,
127 Type_InplaceMod = 1 << 14,
127 Type_InplaceMod = 1 << 14,
128 Type_InplaceAnd = 1 << 15,
128 Type_InplaceAnd = 1 << 15,
129 Type_InplaceOr = 1 << 16,
129 Type_InplaceOr = 1 << 16,
130 Type_InplaceXor = 1 << 17,
130 Type_InplaceXor = 1 << 17,
131 Type_InplaceLShift = 1 << 18,
131 Type_InplaceLShift = 1 << 18,
132 Type_InplaceRShift = 1 << 19,
132 Type_InplaceRShift = 1 << 19,
133
133
134 // Not yet needed/nicely mappable/generated...
134 // Not yet needed/nicely mappable/generated...
135 //Type_Positive = 1 << 29,
135 //Type_Positive = 1 << 29,
136 //Type_Negative = 1 << 29,
136 //Type_Negative = 1 << 29,
137 //Type_Abs = 1 << 29,
137 //Type_Abs = 1 << 29,
138 //Type_Hash = 1 << 29,
138 //Type_Hash = 1 << 29,
139
139
140 Type_Invert = 1 << 29,
140 Type_Invert = 1 << 29,
141 Type_RichCompare = 1 << 30,
141 Type_RichCompare = 1 << 30,
142 Type_NonZero = 1 << 31,
142 Type_NonZero = 1 << 31,
143
143
144 };
144 };
145
145
146 //! enum for profiling callback
147 enum ProfilingCallbackState {
148 Enter = 1,
149 Leave = 2
150 };
151
152 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
153 //! they are NULL.
154 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
155
146 //---------------------------------------------------------------------------
156 //---------------------------------------------------------------------------
147 //! \name Singleton Initialization
157 //! \name Singleton Initialization
148 //@{
158 //@{
149
159
150 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
160 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
151 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
161 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
152 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
162 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
153 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
163 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
154
164
155 //! cleanup of the singleton
165 //! cleanup of the singleton
156 static void cleanup();
166 static void cleanup();
157
167
158 //! get the singleton instance
168 //! get the singleton instance
159 static PythonQt* self() { return _self; }
169 static PythonQt* self() { return _self; }
160
170
161 //@}
171 //@}
162
172
163 //! defines the object types for introspection
173 //! defines the object types for introspection
164 enum ObjectType {
174 enum ObjectType {
165 Class,
175 Class,
166 Function,
176 Function,
167 Variable,
177 Variable,
168 Module,
178 Module,
169 Anything,
179 Anything,
170 CallOverloads
180 CallOverloads
171 };
181 };
172
182
173 //---------------------------------------------------------------------------
183 //---------------------------------------------------------------------------
174 //! \name Modules
184 //! \name Modules
175 //@{
185 //@{
176
186
177 //! get the __main__ module of python
187 //! get the __main__ module of python
178 PythonQtObjectPtr getMainModule();
188 PythonQtObjectPtr getMainModule();
179
189
180 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
190 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
181 //! If a module is already imported, this returns the already imported module.
191 //! If a module is already imported, this returns the already imported module.
182 PythonQtObjectPtr importModule(const QString& name);
192 PythonQtObjectPtr importModule(const QString& name);
183
193
184 //! creates the new module \c name and evaluates the given file in the context of that module
194 //! creates the new module \c name and evaluates the given file in the context of that module
185 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
195 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
186 //! to a module later on.
196 //! to a module later on.
187 //! The user needs to make sure that the \c name is unique in the python module dictionary.
197 //! The user needs to make sure that the \c name is unique in the python module dictionary.
188 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
198 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
189
199
190 //! creates the new module \c name and evaluates the given script in the context of that module.
200 //! creates the new module \c name and evaluates the given script in the context of that module.
191 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
201 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
192 //! to a module later on.
202 //! to a module later on.
193 //! The user needs to make sure that the \c name is unique in the python module dictionary.
203 //! The user needs to make sure that the \c name is unique in the python module dictionary.
194 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
204 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
195
205
196 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
206 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
197 //! script code
207 //! script code
198 PythonQtObjectPtr createUniqueModule();
208 PythonQtObjectPtr createUniqueModule();
199
209
200 //@}
210 //@}
201
211
202 //---------------------------------------------------------------------------
212 //---------------------------------------------------------------------------
203 //! \name Importing/Paths
213 //! \name Importing/Paths
204 //@{
214 //@{
205
215
206 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
216 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
207 void overwriteSysPath(const QStringList& paths);
217 void overwriteSysPath(const QStringList& paths);
208
218
209 //! prepend a path to sys.path to allow importing from it
219 //! prepend a path to sys.path to allow importing from it
210 void addSysPath(const QString& path);
220 void addSysPath(const QString& path);
211
221
212 //! sets the __path__ list of a module to the given list (important for local imports)
222 //! sets the __path__ list of a module to the given list (important for local imports)
213 void setModuleImportPath(PyObject* module, const QStringList& paths);
223 void setModuleImportPath(PyObject* module, const QStringList& paths);
214
224
215 //@}
225 //@}
216
226
217 //---------------------------------------------------------------------------
227 //---------------------------------------------------------------------------
218 //! \name Registering Classes
228 //! \name Registering Classes
219 //@{
229 //@{
220
230
221 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
231 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
222 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
232 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
223 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
233 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
224 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
234 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
225
235
226 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
236 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
227 //! (ownership of wrapper is passed to PythonQt)
237 //! (ownership of wrapper is passed to PythonQt)
228 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
238 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
229
239
230 This will add a wrapper object that is used to make calls to the given classname \c typeName.
240 This will add a wrapper object that is used to make calls to the given classname \c typeName.
231 All slots that take a pointer to typeName as the first argument will be callable from Python on
241 All slots that take a pointer to typeName as the first argument will be callable from Python on
232 a variant object that contains such a type.
242 a variant object that contains such a type.
233 */
243 */
234 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
244 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
235
245
236 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
246 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
237 //! and it will register the classes when it first sees a pointer to such a derived class
247 //! and it will register the classes when it first sees a pointer to such a derived class
238 void registerQObjectClassNames(const QStringList& names);
248 void registerQObjectClassNames(const QStringList& names);
239
249
240 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
250 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
241 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
251 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
242 //! type is really derived from parentType.
252 //! type is really derived from parentType.
243 //! Returns false if the typeName was not yet registered.
253 //! Returns false if the typeName was not yet registered.
244 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
254 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
245
255
246 //! add a handler for polymorphic downcasting
256 //! add a handler for polymorphic downcasting
247 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
257 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
248
258
249 //@}
259 //@}
250
260
251 //---------------------------------------------------------------------------
261 //---------------------------------------------------------------------------
252 //! \name Script Parsing and Evaluation
262 //! \name Script Parsing and Evaluation
253 //@{
263 //@{
254
264
255 //! parses the given file and returns the python code object, this can then be used to call evalCode()
265 //! parses the given file and returns the python code object, this can then be used to call evalCode()
256 PythonQtObjectPtr parseFile(const QString& filename);
266 PythonQtObjectPtr parseFile(const QString& filename);
257
267
258 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
268 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
259 //! If pycode is NULL, a python error is printed.
269 //! If pycode is NULL, a python error is printed.
260 QVariant evalCode(PyObject* object, PyObject* pycode);
270 QVariant evalCode(PyObject* object, PyObject* pycode);
261
271
262 //! evaluates the given script code and returns the result value
272 //! evaluates the given script code and returns the result value
263 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
273 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
264
274
265 //! evaluates the given script code from file
275 //! evaluates the given script code from file
266 void evalFile(PyObject* object, const QString& filename);
276 void evalFile(PyObject* object, const QString& filename);
267
277
268 //@}
278 //@}
269
279
270 //---------------------------------------------------------------------------
280 //---------------------------------------------------------------------------
271 //! \name Signal Handlers
281 //! \name Signal Handlers
272 //@{
282 //@{
273
283
274 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
284 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
275 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
285 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
276
286
277 //! remove a signal handler from the given \c signal of \c obj
287 //! remove a signal handler from the given \c signal of \c obj
278 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
288 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
279
289
280 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
290 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
281 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
291 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
282
292
283 //! remove a signal handler from the given \c signal of \c obj
293 //! remove a signal handler from the given \c signal of \c obj
284 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
294 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
285
295
286 //@}
296 //@}
287
297
288 //---------------------------------------------------------------------------
298 //---------------------------------------------------------------------------
289 //! \name Variable access
299 //! \name Variable access
290 //@{
300 //@{
291
301
292 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
302 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
293 void addObject(PyObject* object, const QString& name, QObject* qObject);
303 void addObject(PyObject* object, const QString& name, QObject* qObject);
294
304
295 //! add the given variable to the object
305 //! add the given variable to the object
296 void addVariable(PyObject* object, const QString& name, const QVariant& v);
306 void addVariable(PyObject* object, const QString& name, const QVariant& v);
297
307
298 //! remove the given variable
308 //! remove the given variable
299 void removeVariable(PyObject* module, const QString& name);
309 void removeVariable(PyObject* module, const QString& name);
300
310
301 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
311 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
302 QVariant getVariable(PyObject* object, const QString& name);
312 QVariant getVariable(PyObject* object, const QString& name);
303
313
304 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
314 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
305 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
315 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
306
316
307 //! returns the found callable object or NULL
317 //! returns the found callable object or NULL
308 //! @return new reference
318 //! @return new reference
309 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
319 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
310
320
311 //@}
321 //@}
312
322
313 //---------------------------------------------------------------------------
323 //---------------------------------------------------------------------------
314 //! \name Calling Python Objects
324 //! \name Calling Python Objects
315 //@{
325 //@{
316
326
317 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
327 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
318 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
328 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
319
329
320 //! call the given python object, returns the result converted to a QVariant
330 //! call the given python object, returns the result converted to a QVariant
321 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
331 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
322
332
323 //! call the given python object, returns the result as new PyObject
333 //! call the given python object, returns the result as new PyObject
324 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
334 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
325
335
326 //@}
336 //@}
327
337
328 //---------------------------------------------------------------------------
338 //---------------------------------------------------------------------------
329 //! \name Decorations, Constructors, Wrappers...
339 //! \name Decorations, Constructors, Wrappers...
330 //@{
340 //@{
331
341
332 //! add an object whose slots will be used as decorator slots for
342 //! add an object whose slots will be used as decorator slots for
333 //! other QObjects or CPP classes. The slots need to follow the
343 //! other QObjects or CPP classes. The slots need to follow the
334 //! convention that the first argument is a pointer to the wrapped object.
344 //! convention that the first argument is a pointer to the wrapped object.
335 //! (ownership is passed to PythonQt)
345 //! (ownership is passed to PythonQt)
336 /*!
346 /*!
337 Example:
347 Example:
338
348
339 A slot with the signature
349 A slot with the signature
340
350
341 \code
351 \code
342 bool doSomething(QWidget* w, int a)
352 bool doSomething(QWidget* w, int a)
343 \endcode
353 \endcode
344
354
345 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
355 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
346 that will be called with the concrete instance as first argument.
356 that will be called with the concrete instance as first argument.
347 So in Python you can now e.g. call
357 So in Python you can now e.g. call
348
358
349 \code
359 \code
350 someWidget.doSomething(12)
360 someWidget.doSomething(12)
351 \endcode
361 \endcode
352
362
353 without QWidget really having this method. This allows to easily make normal methods
363 without QWidget really having this method. This allows to easily make normal methods
354 of Qt classes callable by forwarding them with such decorator slots
364 of Qt classes callable by forwarding them with such decorator slots
355 or to make CPP classes (which are not derived from QObject) callable from Python.
365 or to make CPP classes (which are not derived from QObject) callable from Python.
356 */
366 */
357 void addInstanceDecorators(QObject* o);
367 void addInstanceDecorators(QObject* o);
358
368
359 //! add an object whose slots will be used as decorator slots for
369 //! add an object whose slots will be used as decorator slots for
360 //! class objects (ownership is passed to PythonQt)
370 //! class objects (ownership is passed to PythonQt)
361 /*!
371 /*!
362 The slots need to follow the following convention:
372 The slots need to follow the following convention:
363 - SomeClass* new_SomeClass(...)
373 - SomeClass* new_SomeClass(...)
364 - QVariant new_SomeClass(...)
374 - QVariant new_SomeClass(...)
365 - void delete_SomeClass(SomeClass*)
375 - void delete_SomeClass(SomeClass*)
366 - ... static_SomeClass_someName(...)
376 - ... static_SomeClass_someName(...)
367
377
368 This will add:
378 This will add:
369 - a constructor
379 - a constructor
370 - a constructor which generates a QVariant
380 - a constructor which generates a QVariant
371 - a destructor (only useful for CPP objects)
381 - a destructor (only useful for CPP objects)
372 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
382 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
373
383
374 */
384 */
375 void addClassDecorators(QObject* o);
385 void addClassDecorators(QObject* o);
376
386
377 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
387 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
378 void addDecorators(QObject* o);
388 void addDecorators(QObject* o);
379
389
380 //! add the given factory to PythonQt (ownership stays with caller)
390 //! add the given factory to PythonQt (ownership stays with caller)
381 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
391 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
382
392
383 //@}
393 //@}
384
394
385 //---------------------------------------------------------------------------
395 //---------------------------------------------------------------------------
386 //! \name Custom Importer
396 //! \name Custom Importer
387 //@{
397 //@{
388
398
389 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
399 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
390 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
400 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
391 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
401 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
392 //! This is not reversible, so even setting setImporter(NULL) afterwards will
402 //! This is not reversible, so even setting setImporter(NULL) afterwards will
393 //! keep the custom PythonQt importer with a QFile default import interface.
403 //! keep the custom PythonQt importer with a QFile default import interface.
394 //! Subsequent python import calls will make use of the passed importInterface
404 //! Subsequent python import calls will make use of the passed importInterface
395 //! which forwards all import calls to the given \c importInterface.
405 //! which forwards all import calls to the given \c importInterface.
396 //! Passing NULL will install a default QFile importer.
406 //! Passing NULL will install a default QFile importer.
397 //! (\c importInterface ownership stays with caller)
407 //! (\c importInterface ownership stays with caller)
398 void setImporter(PythonQtImportFileInterface* importInterface);
408 void setImporter(PythonQtImportFileInterface* importInterface);
399
409
400 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
410 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
401 //! (without calling setImporter or installDefaultImporter at least once, the default python import
411 //! (without calling setImporter or installDefaultImporter at least once, the default python import
402 //! mechanism is in place)
412 //! mechanism is in place)
403 //! the default importer allows to import files from anywhere QFile can read from,
413 //! the default importer allows to import files from anywhere QFile can read from,
404 //! including the Qt resource system using ":". Keep in mind that you need to extend
414 //! including the Qt resource system using ":". Keep in mind that you need to extend
405 //! "sys.path" with ":" to be able to import from the Qt resources.
415 //! "sys.path" with ":" to be able to import from the Qt resources.
406 void installDefaultImporter() { setImporter(NULL); }
416 void installDefaultImporter() { setImporter(NULL); }
407
417
408 //! set paths that the importer should ignore
418 //! set paths that the importer should ignore
409 void setImporterIgnorePaths(const QStringList& paths);
419 void setImporterIgnorePaths(const QStringList& paths);
410
420
411 //! get paths that the importer should ignore
421 //! get paths that the importer should ignore
412 const QStringList& getImporterIgnorePaths();
422 const QStringList& getImporterIgnorePaths();
413
423
414 //! get access to the file importer (if set)
424 //! get access to the file importer (if set)
415 static PythonQtImportFileInterface* importInterface();
425 static PythonQtImportFileInterface* importInterface();
416
426
417 //@}
427 //@}
418
428
419 //---------------------------------------------------------------------------
429 //---------------------------------------------------------------------------
420 //! \name Other Stuff
430 //! \name Other Stuff
421 //@{
431 //@{
422
432
423 //! get access to internal data (should not be used on the public API, but is used by some C functions)
433 //! get access to internal data (should not be used on the public API, but is used by some C functions)
424 static PythonQtPrivate* priv() { return _self->_p; }
434 static PythonQtPrivate* priv() { return _self->_p; }
425
435
426 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
436 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
427 //! The error is currently just output to the python stderr, future version might implement better trace printing
437 //! The error is currently just output to the python stderr, future version might implement better trace printing
428 bool handleError();
438 bool handleError();
429
439
440 //! clear all NotFound entries on all class infos, to ensure that
441 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
442 void clearNotFoundCachedMembers();
443
430 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
444 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
431 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
445 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
432 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
446 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
433 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
447 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
434
448
435 //! call the callback if it is set
449 //! call the callback if it is set
436 static void qObjectNoLongerWrappedCB(QObject* o);
450 static void qObjectNoLongerWrappedCB(QObject* o);
437
451
438 //! called by internal help methods
452 //! called by internal help methods
439 PyObject* helpCalled(PythonQtClassInfo* info);
453 PyObject* helpCalled(PythonQtClassInfo* info);
440
454
441 //! returns the found object or NULL
455 //! returns the found object or NULL
442 //! @return new reference
456 //! @return new reference
443 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
457 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
444
458
459 //! sets a callback that is called before and after function calls for profiling
460 void setProfilingCallback(ProfilingCB* cb);
461
445 //@}
462 //@}
446
463
447 signals:
464 signals:
448 //! emitted when python outputs something to stdout (and redirection is turned on)
465 //! emitted when python outputs something to stdout (and redirection is turned on)
449 void pythonStdOut(const QString& str);
466 void pythonStdOut(const QString& str);
450 //! emitted when python outputs something to stderr (and redirection is turned on)
467 //! emitted when python outputs something to stderr (and redirection is turned on)
451 void pythonStdErr(const QString& str);
468 void pythonStdErr(const QString& str);
452
469
453 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
470 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
454 void pythonHelpRequest(const QByteArray& cppClassName);
471 void pythonHelpRequest(const QByteArray& cppClassName);
455
472
456 private:
473 private:
457 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
474 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
458
475
459 //! callback for stdout redirection, emits pythonStdOut signal
476 //! callback for stdout redirection, emits pythonStdOut signal
460 static void stdOutRedirectCB(const QString& str);
477 static void stdOutRedirectCB(const QString& str);
461 //! callback for stderr redirection, emits pythonStdErr signal
478 //! callback for stderr redirection, emits pythonStdErr signal
462 static void stdErrRedirectCB(const QString& str);
479 static void stdErrRedirectCB(const QString& str);
463
480
464 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
481 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
465 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
482 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
466
483
467 PythonQt(int flags, const QByteArray& pythonQtModuleName);
484 PythonQt(int flags, const QByteArray& pythonQtModuleName);
468 ~PythonQt();
485 ~PythonQt();
469
486
470 static PythonQt* _self;
487 static PythonQt* _self;
471 static int _uniqueModuleCount;
488 static int _uniqueModuleCount;
472
489
473 PythonQtPrivate* _p;
490 PythonQtPrivate* _p;
474
491
475 };
492 };
476
493
477 //! internal PythonQt details
494 //! internal PythonQt details
478 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
495 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
479
496
480 Q_OBJECT
497 Q_OBJECT
481
498
482 public:
499 public:
483 PythonQtPrivate();
500 PythonQtPrivate();
484 ~PythonQtPrivate();
501 ~PythonQtPrivate();
485
502
486 enum DecoratorTypes {
503 enum DecoratorTypes {
487 StaticDecorator = 1,
504 StaticDecorator = 1,
488 ConstructorDecorator = 2,
505 ConstructorDecorator = 2,
489 DestructorDecorator = 4,
506 DestructorDecorator = 4,
490 InstanceDecorator = 8,
507 InstanceDecorator = 8,
491 AllDecorators = 0xffff
508 AllDecorators = 0xffff
492 };
509 };
493
510
494 //! get the suffixes that are used for shared libraries
511 //! get the suffixes that are used for shared libraries
495 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
512 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
496
513
497 //! returns if the id is the id for PythonQtObjectPtr
514 //! returns if the id is the id for PythonQtObjectPtr
498 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
515 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
499
516
500 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
517 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
501 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
518 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
502 //! remove the wrapper ptr again
519 //! remove the wrapper ptr again
503 void removeWrapperPointer(void* obj);
520 void removeWrapperPointer(void* obj);
504
521
505 //! add parent class relation
522 //! add parent class relation
506 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
523 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
507
524
508 //! add a handler for polymorphic downcasting
525 //! add a handler for polymorphic downcasting
509 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
526 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
510
527
511 //! lookup existing classinfo and return new if not yet present
528 //! lookup existing classinfo and return new if not yet present
512 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
529 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
513
530
514 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
531 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
515 void removeSignalEmitter(QObject* obj);
532 void removeSignalEmitter(QObject* obj);
516
533
517 //! wrap the given QObject into a Python object (or return existing wrapper!)
534 //! wrap the given QObject into a Python object (or return existing wrapper!)
518 PyObject* wrapQObject(QObject* obj);
535 PyObject* wrapQObject(QObject* obj);
519
536
520 //! 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
537 //! 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
521 PyObject* wrapPtr(void* ptr, const QByteArray& name);
538 PyObject* wrapPtr(void* ptr, const QByteArray& name);
522
539
523 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
540 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
524 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
541 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
525 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
542 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
526 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
543 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
527
544
528 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
545 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
529 //! (ownership of wrapper is passed to PythonQt)
546 //! (ownership of wrapper is passed to PythonQt)
530 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
547 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
531
548
532 This will add a wrapper object that is used to make calls to the given classname \c typeName.
549 This will add a wrapper object that is used to make calls to the given classname \c typeName.
533 All slots that take a pointer to typeName as the first argument will be callable from Python on
550 All slots that take a pointer to typeName as the first argument will be callable from Python on
534 a variant object that contains such a type.
551 a variant object that contains such a type.
535 */
552 */
536 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);
553 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);
537
554
538 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
555 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
539 //! and it will register the classes when it first sees a pointer to such a derived class
556 //! and it will register the classes when it first sees a pointer to such a derived class
540 void registerQObjectClassNames(const QStringList& names);
557 void registerQObjectClassNames(const QStringList& names);
541
558
542 //! add a decorator object
559 //! add a decorator object
543 void addDecorators(QObject* o, int decoTypes);
560 void addDecorators(QObject* o, int decoTypes);
544
561
545 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
562 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
546 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
563 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
547
564
548 //! create a new instance of the given enum type with given value (returns a new reference)
565 //! create a new instance of the given enum type with given value (returns a new reference)
549 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
566 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
550
567
551 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
568 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
552 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
569 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
553
570
554 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
571 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
555 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
572 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
556
573
557 //! get the class info for a meta object (if available)
574 //! get the class info for a meta object (if available)
558 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
575 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
559
576
560 //! get the class info for a meta object (if available)
577 //! get the class info for a meta object (if available)
561 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
578 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
562
579
563 //! creates the new module from the given pycode
580 //! creates the new module from the given pycode
564 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
581 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
565
582
566 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
583 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
567 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
584 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
568
585
569 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
586 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
570 static PyObject* dummyTuple();
587 static PyObject* dummyTuple();
571
588
572 //! called by virtual overloads when a python return value can not be converted to the required Qt type
589 //! called by virtual overloads when a python return value can not be converted to the required Qt type
573 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
590 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
574
591
575 //! get access to the PythonQt module
592 //! get access to the PythonQt module
576 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
593 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
577
594
595 //! returns the profiling callback, which may be NULL
596 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
597
578 private:
598 private:
579 //! Setup the shared library suffixes by getting them from the "imp" module.
599 //! Setup the shared library suffixes by getting them from the "imp" module.
580 void setupSharedLibrarySuffixes();
600 void setupSharedLibrarySuffixes();
581
601
582 //! create a new pythonqt class wrapper and place it in the pythonqt module
602 //! create a new pythonqt class wrapper and place it in the pythonqt module
583 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
603 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
584
604
585 //! get/create new package module (the returned object is a borrowed reference)
605 //! get/create new package module (the returned object is a borrowed reference)
586 PyObject* packageByName(const char* name);
606 PyObject* packageByName(const char* name);
587
607
588 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
608 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
589 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
609 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
590
610
591 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
611 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
592 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
612 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
593
613
594 //! stores the meta info of known Qt classes
614 //! stores the meta info of known Qt classes
595 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
615 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
596
616
597 //! names of qobject derived classes that can be casted to qobject savely
617 //! names of qobject derived classes that can be casted to qobject savely
598 QHash<QByteArray, bool> _knownQObjectClassNames;
618 QHash<QByteArray, bool> _knownQObjectClassNames;
599
619
600 //! stores signal receivers for QObjects
620 //! stores signal receivers for QObjects
601 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
621 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
602
622
603 //! the PythonQt python module
623 //! the PythonQt python module
604 PythonQtObjectPtr _pythonQtModule;
624 PythonQtObjectPtr _pythonQtModule;
605
625
606 //! the name of the PythonQt python module
626 //! the name of the PythonQt python module
607 QByteArray _pythonQtModuleName;
627 QByteArray _pythonQtModuleName;
608
628
609 //! the importer interface (if set)
629 //! the importer interface (if set)
610 PythonQtImportFileInterface* _importInterface;
630 PythonQtImportFileInterface* _importInterface;
611
631
612 //! the default importer
632 //! the default importer
613 PythonQtQFileImporter* _defaultImporter;
633 PythonQtQFileImporter* _defaultImporter;
614
634
615 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
635 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
616 PythonQtQObjectWrappedCB* _wrappedCB;
636 PythonQtQObjectWrappedCB* _wrappedCB;
617
637
618 QStringList _importIgnorePaths;
638 QStringList _importIgnorePaths;
619 QStringList _sharedLibrarySuffixes;
639 QStringList _sharedLibrarySuffixes;
620
640
621 //! the cpp object wrapper factories
641 //! the cpp object wrapper factories
622 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
642 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
623
643
624 QHash<QByteArray, PyObject*> _packages;
644 QHash<QByteArray, PyObject*> _packages;
625
645
626 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
646 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
627
647
648 PythonQt::ProfilingCB* _profilingCB;
649
628 int _initFlags;
650 int _initFlags;
629 int _PythonQtObjectPtr_metaId;
651 int _PythonQtObjectPtr_metaId;
630
652
631 friend class PythonQt;
653 friend class PythonQt;
632 };
654 };
633
655
634 #endif
656 #endif
@@ -1,849 +1,868
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) {
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 = strlen(memberName);
162 int memberNameLen = 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 = strlen(memberName);
215 int memberNameLen = 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(bool metaOnly)
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) {
471 if (_isQObject && _meta && !metaOnly) {
472 l = propertyList();
472 l = propertyList();
473 }
473 }
474
474
475 // normal slots of QObject (or wrapper QObject)
475 // normal slots of QObject (or wrapper QObject)
476 if (!metaOnly && _meta) {
476 if (!metaOnly && _meta) {
477 int numMethods = _meta->methodCount();
477 int numMethods = _meta->methodCount();
478 bool skipQObj = !_isQObject;
478 bool skipQObj = !_isQObject;
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
480 QMetaMethod m = _meta->method(i);
480 QMetaMethod m = _meta->method(i);
481 if (((m.methodType() == QMetaMethod::Method ||
481 if (((m.methodType() == QMetaMethod::Method ||
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
483 || m.methodType()==QMetaMethod::Signal) {
483 || m.methodType()==QMetaMethod::Signal) {
484 QByteArray signa(m.signature());
484 QByteArray signa(m.signature());
485 signa = signa.left(signa.indexOf('('));
485 signa = signa.left(signa.indexOf('('));
486 l << signa;
486 l << signa;
487 }
487 }
488 }
488 }
489 }
489 }
490
490
491 {
491 {
492 // look for dynamic decorators in this class and in derived classes
492 // look for dynamic decorators in this class and in derived classes
493 QList<PythonQtClassInfo*> infos;
493 QList<PythonQtClassInfo*> infos;
494 recursiveCollectClassInfos(infos);
494 recursiveCollectClassInfos(infos);
495 foreach(PythonQtClassInfo* info, infos) {
495 foreach(PythonQtClassInfo* info, infos) {
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
497 }
497 }
498 }
498 }
499
499
500 // List enumerator keys...
500 // List enumerator keys...
501 QList<const QMetaObject*> enumMetaObjects;
501 QList<const QMetaObject*> enumMetaObjects;
502 if (_meta) {
502 if (_meta) {
503 enumMetaObjects << _meta;
503 enumMetaObjects << _meta;
504 }
504 }
505 // check enums in the class hierachy of CPP classes
505 // check enums in the class hierachy of CPP classes
506 QList<QObject*> decoObjects;
506 QList<QObject*> decoObjects;
507 recursiveCollectDecoratorObjects(decoObjects);
507 recursiveCollectDecoratorObjects(decoObjects);
508 foreach(QObject* deco, decoObjects) {
508 foreach(QObject* deco, decoObjects) {
509 enumMetaObjects << deco->metaObject();
509 enumMetaObjects << deco->metaObject();
510 }
510 }
511
511
512 foreach(const QMetaObject* meta, enumMetaObjects) {
512 foreach(const QMetaObject* meta, enumMetaObjects) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
514 QMetaEnum e = meta->enumerator(i);
514 QMetaEnum e = meta->enumerator(i);
515 l << e.name();
515 l << e.name();
516 // we do not want flags, they will cause our values to appear two times
516 // we do not want flags, they will cause our values to appear two times
517 if (e.isFlag()) continue;
517 if (e.isFlag()) continue;
518
518
519 for (int j=0; j < e.keyCount(); j++) {
519 for (int j=0; j < e.keyCount(); j++) {
520 l << QString(e.key(j));
520 l << QString(e.key(j));
521 }
521 }
522 }
522 }
523 }
523 }
524
524
525 return QSet<QString>::fromList(l).toList();
525 return QSet<QString>::fromList(l).toList();
526 }
526 }
527
527
528 const char* PythonQtClassInfo::className()
528 const char* PythonQtClassInfo::className()
529 {
529 {
530 return _wrappedClassName.constData();
530 return _wrappedClassName.constData();
531 }
531 }
532
532
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
534 {
534 {
535 if (ptr==NULL) {
535 if (ptr==NULL) {
536 return NULL;
536 return NULL;
537 }
537 }
538 if (_wrappedClassName == classname) {
538 if (_wrappedClassName == classname) {
539 return ptr;
539 return ptr;
540 }
540 }
541 foreach(const ParentClassInfo& info, _parentClasses) {
541 foreach(const ParentClassInfo& info, _parentClasses) {
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
543 if (result) {
543 if (result) {
544 return result;
544 return result;
545 }
545 }
546 }
546 }
547 return NULL;
547 return NULL;
548 }
548 }
549
549
550 bool PythonQtClassInfo::inherits(const char* name)
550 bool PythonQtClassInfo::inherits(const char* name)
551 {
551 {
552 if (_wrappedClassName == name) {
552 if (_wrappedClassName == name) {
553 return true;
553 return true;
554 }
554 }
555 foreach(const ParentClassInfo& info, _parentClasses) {
555 foreach(const ParentClassInfo& info, _parentClasses) {
556 if (info._parent->inherits(name)) {
556 if (info._parent->inherits(name)) {
557 return true;
557 return true;
558 }
558 }
559 }
559 }
560 return false;
560 return false;
561 }
561 }
562
562
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
564 {
564 {
565 if (classInfo == this) {
565 if (classInfo == this) {
566 return true;
566 return true;
567 }
567 }
568 foreach(const ParentClassInfo& info, _parentClasses) {
568 foreach(const ParentClassInfo& info, _parentClasses) {
569 if (info._parent->inherits(classInfo)) {
569 if (info._parent->inherits(classInfo)) {
570 return true;
570 return true;
571 }
571 }
572 }
572 }
573 return false;
573 return false;
574 }
574 }
575
575
576 QString PythonQtClassInfo::help()
576 QString PythonQtClassInfo::help()
577 {
577 {
578 decorator();
578 decorator();
579 QString h;
579 QString h;
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
581
581
582 if (_isQObject) {
582 if (_isQObject) {
583 h += "Properties:\n";
583 h += "Properties:\n";
584
584
585 int i;
585 int i;
586 int numProperties = _meta->propertyCount();
586 int numProperties = _meta->propertyCount();
587 for (i = 0; i < numProperties; i++) {
587 for (i = 0; i < numProperties; i++) {
588 QMetaProperty p = _meta->property(i);
588 QMetaProperty p = _meta->property(i);
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
590 }
590 }
591 }
591 }
592
592
593 if (constructors()) {
593 if (constructors()) {
594 h += "Constructors:\n";
594 h += "Constructors:\n";
595 PythonQtSlotInfo* constr = constructors();
595 PythonQtSlotInfo* constr = constructors();
596 while (constr) {
596 while (constr) {
597 h += constr->fullSignature() + "\n";
597 h += constr->fullSignature() + "\n";
598 constr = constr->nextInfo();
598 constr = constr->nextInfo();
599 }
599 }
600 }
600 }
601
601
602 h += "Slots:\n";
602 h += "Slots:\n";
603 h += "QString help()\n";
603 h += "QString help()\n";
604 h += "QString className()\n";
604 h += "QString className()\n";
605
605
606 if (_meta) {
606 if (_meta) {
607 int numMethods = _meta->methodCount();
607 int numMethods = _meta->methodCount();
608 for (int i = 0; i < numMethods; i++) {
608 for (int i = 0; i < numMethods; i++) {
609 QMetaMethod m = _meta->method(i);
609 QMetaMethod m = _meta->method(i);
610 if ((m.methodType() == QMetaMethod::Method ||
610 if ((m.methodType() == QMetaMethod::Method ||
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
612 PythonQtSlotInfo slot(this, m, i);
612 PythonQtSlotInfo slot(this, m, i);
613 h += slot.fullSignature()+ "\n";
613 h += slot.fullSignature()+ "\n";
614 }
614 }
615 }
615 }
616 }
616 }
617
617
618 // TODO xxx : decorators and enums from decorator() are missing...
618 // TODO xxx : decorators and enums from decorator() are missing...
619 // maybe we can reuse memberlist()?
619 // maybe we can reuse memberlist()?
620
620
621 if (_meta && _meta->enumeratorCount()) {
621 if (_meta && _meta->enumeratorCount()) {
622 h += "Enums:\n";
622 h += "Enums:\n";
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
624 QMetaEnum e = _meta->enumerator(i);
624 QMetaEnum e = _meta->enumerator(i);
625 h += QString(e.name()) + " {";
625 h += QString(e.name()) + " {";
626 for (int j=0; j < e.keyCount(); j++) {
626 for (int j=0; j < e.keyCount(); j++) {
627 if (j) { h+= ", "; }
627 if (j) { h+= ", "; }
628 h += e.key(j);
628 h += e.key(j);
629 }
629 }
630 h += " }\n";
630 h += " }\n";
631 }
631 }
632 }
632 }
633
633
634 if (_isQObject && _meta) {
634 if (_isQObject && _meta) {
635 int numMethods = _meta->methodCount();
635 int numMethods = _meta->methodCount();
636 if (numMethods>0) {
636 if (numMethods>0) {
637 h += "Signals:\n";
637 h += "Signals:\n";
638 for (int i = 0; i < numMethods; i++) {
638 for (int i = 0; i < numMethods; i++) {
639 QMetaMethod m = _meta->method(i);
639 QMetaMethod m = _meta->method(i);
640 if (m.methodType() == QMetaMethod::Signal) {
640 if (m.methodType() == QMetaMethod::Signal) {
641 h += QString(m.signature()) + "\n";
641 h += QString(m.signature()) + "\n";
642 }
642 }
643 }
643 }
644 }
644 }
645 }
645 }
646 return h;
646 return h;
647 }
647 }
648
648
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
650 {
650 {
651 if (!_constructors) {
651 if (!_constructors) {
652 // force creation of lazy decorator, which will register the decorators
652 // force creation of lazy decorator, which will register the decorators
653 decorator();
653 decorator();
654 }
654 }
655 return _constructors;
655 return _constructors;
656 }
656 }
657
657
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
659 {
659 {
660 if (!_destructor) {
660 if (!_destructor) {
661 // force creation of lazy decorator, which will register the decorators
661 // force creation of lazy decorator, which will register the decorators
662 decorator();
662 decorator();
663 }
663 }
664 return _destructor;
664 return _destructor;
665 }
665 }
666
666
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
668 {
668 {
669 PythonQtSlotInfo* prev = constructors();
669 PythonQtSlotInfo* prev = constructors();
670 if (prev) {
670 if (prev) {
671 info->setNextInfo(prev->nextInfo());
671 info->setNextInfo(prev->nextInfo());
672 prev->setNextInfo(info);
672 prev->setNextInfo(info);
673 } else {
673 } else {
674 _constructors = info;
674 _constructors = info;
675 }
675 }
676 }
676 }
677
677
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
679 {
679 {
680 _decoratorSlots.append(info);
680 _decoratorSlots.append(info);
681 }
681 }
682
682
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
684 {
684 {
685 if (_destructor) {
685 if (_destructor) {
686 _destructor->deleteOverloadsAndThis();
686 _destructor->deleteOverloadsAndThis();
687 }
687 }
688 _destructor = info;
688 _destructor = info;
689 }
689 }
690
690
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
692 {
692 {
693 _meta = meta;
693 _meta = meta;
694 clearCachedMembers();
694 clearCachedMembers();
695 }
695 }
696
696
697 QObject* PythonQtClassInfo::decorator()
697 QObject* PythonQtClassInfo::decorator()
698 {
698 {
699 if (!_decoratorProvider && _decoratorProviderCB) {
699 if (!_decoratorProvider && _decoratorProviderCB) {
700 _decoratorProvider = (*_decoratorProviderCB)();
700 _decoratorProvider = (*_decoratorProviderCB)();
701 if (_decoratorProvider) {
701 if (_decoratorProvider) {
702 _decoratorProvider->setParent(PythonQt::priv());
702 _decoratorProvider->setParent(PythonQt::priv());
703 // setup enums early, since they might be needed by the constructor decorators:
703 // setup enums early, since they might be needed by the constructor decorators:
704 if (!_enumsCreated) {
704 if (!_enumsCreated) {
705 createEnumWrappers();
705 createEnumWrappers();
706 }
706 }
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
708 }
708 }
709 }
709 }
710 // check if enums need to be created and create them if they are not yet created
710 // check if enums need to be created and create them if they are not yet created
711 if (!_enumsCreated) {
711 if (!_enumsCreated) {
712 createEnumWrappers();
712 createEnumWrappers();
713 }
713 }
714 return _decoratorProvider;
714 return _decoratorProvider;
715 }
715 }
716
716
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
718 {
718 {
719 PythonQtMemberInfo info = member("py_hasOwner");
719 PythonQtMemberInfo info = member("py_hasOwner");
720 if (info._type == PythonQtMemberInfo::Slot) {
720 if (info._type == PythonQtMemberInfo::Slot) {
721 void* obj = object;
721 void* obj = object;
722 bool result = false;
722 bool result = false;
723 void* args[2];
723 void* args[2];
724 args[0] = &result;
724 args[0] = &result;
725 args[1] = &obj;
725 args[1] = &obj;
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
727 return !result;
727 return !result;
728 } else {
728 } else {
729 return false;
729 return false;
730 }
730 }
731 }
731 }
732
732
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
734 {
734 {
735 if (!_polymorphicHandlers.isEmpty()) {
735 if (!_polymorphicHandlers.isEmpty()) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
737 void* resultPtr = (*cb)(ptr, resultClassName);
737 void* resultPtr = (*cb)(ptr, resultClassName);
738 if (resultPtr) {
738 if (resultPtr) {
739 return resultPtr;
739 return resultPtr;
740 }
740 }
741 }
741 }
742 }
742 }
743 foreach(const ParentClassInfo& info, _parentClasses) {
743 foreach(const ParentClassInfo& info, _parentClasses) {
744 if (!info._parent->isQObject()) {
744 if (!info._parent->isQObject()) {
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
746 if (resultPtr) {
746 if (resultPtr) {
747 return resultPtr;
747 return resultPtr;
748 }
748 }
749 }
749 }
750 }
750 }
751 return NULL;
751 return NULL;
752 }
752 }
753
753
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
755 {
755 {
756 char* className;
756 char* className;
757 // this would do downcasting recursively...
757 // this would do downcasting recursively...
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
759
759
760 // we only do downcasting on the base object, not on the whole inheritance tree...
760 // we only do downcasting on the base object, not on the whole inheritance tree...
761 void* resultPtr = NULL;
761 void* resultPtr = NULL;
762 if (!_polymorphicHandlers.isEmpty()) {
762 if (!_polymorphicHandlers.isEmpty()) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
764 resultPtr = (*cb)(ptr, &className);
764 resultPtr = (*cb)(ptr, &className);
765 if (resultPtr) {
765 if (resultPtr) {
766 break;
766 break;
767 }
767 }
768 }
768 }
769 }
769 }
770 if (resultPtr) {
770 if (resultPtr) {
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
772 } else {
772 } else {
773 *resultClassInfo = this;
773 *resultClassInfo = this;
774 resultPtr = ptr;
774 resultPtr = ptr;
775 }
775 }
776 return resultPtr;
776 return resultPtr;
777 }
777 }
778
778
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
780 {
780 {
781 if (isLocalEnum) {
781 if (isLocalEnum) {
782 *isLocalEnum = true;
782 *isLocalEnum = true;
783 }
783 }
784 int scopePos = name.lastIndexOf("::");
784 int scopePos = name.lastIndexOf("::");
785 if (scopePos != -1) {
785 if (scopePos != -1) {
786 if (isLocalEnum) {
786 if (isLocalEnum) {
787 *isLocalEnum = false;
787 *isLocalEnum = false;
788 }
788 }
789 // split into scope and enum name
789 // split into scope and enum name
790 QByteArray enumScope = name.mid(0,scopePos);
790 QByteArray enumScope = name.mid(0,scopePos);
791 QByteArray enumName = name.mid(scopePos+2);
791 QByteArray enumName = name.mid(scopePos+2);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
793 if (info) {
793 if (info) {
794 return info->findEnumWrapper(enumName);
794 return info->findEnumWrapper(enumName);
795 } else{
795 } else{
796 return NULL;
796 return NULL;
797 }
797 }
798 }
798 }
799 if (localScope) {
799 if (localScope) {
800 return localScope->findEnumWrapper(name);
800 return localScope->findEnumWrapper(name);
801 } else {
801 } else {
802 return NULL;
802 return NULL;
803 }
803 }
804 }
804 }
805
805
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
807 {
807 {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
809 QMetaEnum e = meta->enumerator(i);
809 QMetaEnum e = meta->enumerator(i);
810 PythonQtObjectPtr p;
810 PythonQtObjectPtr p;
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
812 _enumWrappers.append(p);
812 _enumWrappers.append(p);
813 }
813 }
814 }
814 }
815
815
816 void PythonQtClassInfo::createEnumWrappers()
816 void PythonQtClassInfo::createEnumWrappers()
817 {
817 {
818 if (!_enumsCreated) {
818 if (!_enumsCreated) {
819 _enumsCreated = true;
819 _enumsCreated = true;
820 if (_meta) {
820 if (_meta) {
821 createEnumWrappers(_meta);
821 createEnumWrappers(_meta);
822 }
822 }
823 if (decorator()) {
823 if (decorator()) {
824 createEnumWrappers(decorator()->metaObject());
824 createEnumWrappers(decorator()->metaObject());
825 }
825 }
826 foreach(const ParentClassInfo& info, _parentClasses) {
826 foreach(const ParentClassInfo& info, _parentClasses) {
827 info._parent->createEnumWrappers();
827 info._parent->createEnumWrappers();
828 }
828 }
829 }
829 }
830 }
830 }
831
831
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
833 // force enum creation
833 // force enum creation
834 if (!_enumsCreated) {
834 if (!_enumsCreated) {
835 createEnumWrappers();
835 createEnumWrappers();
836 }
836 }
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
839 if (qstrcmp(className, name)==0) {
839 if (qstrcmp(className, name)==0) {
840 return p.object();
840 return p.object();
841 }
841 }
842 }
842 }
843 foreach(const ParentClassInfo& info, _parentClasses) {
843 foreach(const ParentClassInfo& info, _parentClasses) {
844 PyObject* p = info._parent->findEnumWrapper(name);
844 PyObject* p = info._parent->findEnumWrapper(name);
845 if (p) return p;
845 if (p) return p;
846 }
846 }
847 return NULL;
847 return NULL;
848 }
848 }
849
849
850 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
851 {
852 _decoratorProviderCB = cb;
853 _decoratorProvider = NULL;
854 _enumsCreated = false;
855 }
856
857 void PythonQtClassInfo::clearNotFoundCachedMembers()
858 {
859 // remove all not found entries, since a new decorator means new slots,
860 // which might have been cached as "NotFound" already.
861 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
862 while (it.hasNext()) {
863 it.next();
864 if (it.value()._type == PythonQtMemberInfo::NotFound) {
865 it.remove();
866 }
867 }
868 }
@@ -1,262 +1,265
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, 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;
53 _type = Slot;
54 _slot = info;
54 _slot = info;
55 _enumValue = NULL;
55 _enumValue = NULL;
56 }
56 }
57
57
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 _type = EnumValue;
59 _type = EnumValue;
60 _slot = NULL;
60 _slot = NULL;
61 _enumValue = enumValue;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
62 _enumWrapper = NULL;
63 }
63 }
64
64
65 PythonQtMemberInfo(const QMetaProperty& prop) {
65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 _type = Property;
66 _type = Property;
67 _slot = NULL;
67 _slot = NULL;
68 _enumValue = NULL;
68 _enumValue = NULL;
69 _property = prop;
69 _property = prop;
70 _enumWrapper = NULL;
70 _enumWrapper = NULL;
71 }
71 }
72
72
73 Type _type;
73 Type _type;
74
74
75 // TODO: this could be a union...
75 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
76 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
77 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
78 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
79 QMetaProperty _property;
80 };
80 };
81
81
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
82 //! 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
83 /*! for fast lookup of slots when calling the object from Python
84 */
84 */
85 class PYTHONQT_EXPORT PythonQtClassInfo {
85 class PYTHONQT_EXPORT PythonQtClassInfo {
86
86
87 public:
87 public:
88 PythonQtClassInfo();
88 PythonQtClassInfo();
89 ~PythonQtClassInfo();
89 ~PythonQtClassInfo();
90
90
91 //! store information about parent classes
91 //! store information about parent classes
92 struct ParentClassInfo {
92 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
94 {};
95
95
96 PythonQtClassInfo* _parent;
96 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
97 int _upcastingOffset;
98 };
98 };
99
99
100
100
101 //! setup as a QObject, taking the meta object as meta information about the QObject
101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
102 void setupQObject(const QMetaObject* meta);
103
103
104 //! setup as a CPP (non-QObject), taking the classname
104 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
105 void setupCPPObject(const QByteArray& classname);
106
106
107 //! set the type capabilities
107 //! set the type capabilities
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 //! get the type capabilities
109 //! get the type capabilities
110 int typeSlots() const { return _typeSlots; }
110 int typeSlots() const { return _typeSlots; }
111
111
112 //! get the Python method definition for a given slot name (without return type and signature)
112 //! get the Python method definition for a given slot name (without return type and signature)
113 PythonQtMemberInfo member(const char* member);
113 PythonQtMemberInfo member(const char* member);
114
114
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
116 PythonQtSlotInfo* constructors();
116 PythonQtSlotInfo* constructors();
117
117
118 //! get access to the destructor slot
118 //! get access to the destructor slot
119 PythonQtSlotInfo* destructor();
119 PythonQtSlotInfo* destructor();
120
120
121 //! add a constructor, ownership is passed to classinfo
121 //! add a constructor, ownership is passed to classinfo
122 void addConstructor(PythonQtSlotInfo* info);
122 void addConstructor(PythonQtSlotInfo* info);
123
123
124 //! set a destructor, ownership is passed to classinfo
124 //! set a destructor, ownership is passed to classinfo
125 void setDestructor(PythonQtSlotInfo* info);
125 void setDestructor(PythonQtSlotInfo* info);
126
126
127 //! add a decorator slot, ownership is passed to classinfo
127 //! add a decorator slot, ownership is passed to classinfo
128 void addDecoratorSlot(PythonQtSlotInfo* info);
128 void addDecoratorSlot(PythonQtSlotInfo* info);
129
129
130 //! get the classname (either of the QObject or of the wrapped CPP object)
130 //! get the classname (either of the QObject or of the wrapped CPP object)
131 const char* className();
131 const char* className();
132
132
133 //! returns if the QObject
133 //! returns if the QObject
134 bool isQObject() { return _isQObject; }
134 bool isQObject() { return _isQObject; }
135
135
136 //! returns if the class is a CPP wrapper
136 //! returns if the class is a CPP wrapper
137 bool isCPPWrapper() { return !_isQObject; }
137 bool isCPPWrapper() { return !_isQObject; }
138
138
139 //! get the meta object
139 //! get the meta object
140 const QMetaObject* metaObject() { return _meta; }
140 const QMetaObject* metaObject() { return _meta; }
141
141
142 //! set the meta object, this will reset the caching
142 //! set the meta object, this will reset the caching
143 void setMetaObject(const QMetaObject* meta);
143 void setMetaObject(const QMetaObject* meta);
144
144
145 //! returns if this class inherits from the given classname
145 //! returns if this class inherits from the given classname
146 bool inherits(const char* classname);
146 bool inherits(const char* classname);
147
147
148 //! returns if this class inherits from the given classinfo
148 //! returns if this class inherits from the given classinfo
149 bool inherits(PythonQtClassInfo* info);
149 bool inherits(PythonQtClassInfo* info);
150
150
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
151 //! 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
152 //! 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)
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
154 void* castTo(void* ptr, const char* classname);
154 void* castTo(void* ptr, const char* classname);
155
155
156 //! get help string for the metaobject
156 //! get help string for the metaobject
157 QString help();
157 QString help();
158
158
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
160 QStringList propertyList();
160 QStringList propertyList();
161
161
162 //! get list of all members
162 //! get list of all members
163 QStringList memberList(bool metaOnly = false);
163 QStringList memberList(bool metaOnly = false);
164
164
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
166 int metaTypeId() { return _metaTypeId; }
166 int metaTypeId() { return _metaTypeId; }
167
167
168 //! set an additional decorator provider that offers additional decorator slots for this class
168 //! set an additional decorator provider that offers additional decorator slots for this class
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
170
170
171 //! get the decorator qobject instance
171 //! get the decorator qobject instance
172 QObject* decorator();
172 QObject* decorator();
173
173
174 //! add the parent class info of a CPP object
174 //! add the parent class info of a CPP object
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
176
176
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
177 //! 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);
178 bool hasOwnerMethodButNoOwner(void* object);
179
179
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
182
182
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
185
185
186 //! set the shell set instance wrapper cb
186 //! set the shell set instance wrapper cb
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
188 _shellSetInstanceWrapperCB = cb;
188 _shellSetInstanceWrapperCB = cb;
189 }
189 }
190
190
191 //! get the shell set instance wrapper cb
191 //! get the shell set instance wrapper cb
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
193 return _shellSetInstanceWrapperCB;
193 return _shellSetInstanceWrapperCB;
194 }
194 }
195
195
196 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
198
198
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
201
201
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
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
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204
204
205 //! clear all members that where cached as "NotFound"
206 void clearNotFoundCachedMembers();
207
205 private:
208 private:
206 void createEnumWrappers();
209 void createEnumWrappers();
207 void createEnumWrappers(const QMetaObject* meta);
210 void createEnumWrappers(const QMetaObject* meta);
208 PyObject* findEnumWrapper(const char* name);
211 PyObject* findEnumWrapper(const char* name);
209
212
210 //! clear all cached members
213 //! clear all cached members
211 void clearCachedMembers();
214 void clearCachedMembers();
212
215
213 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
216 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
214
217
215 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
218 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
216 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
219 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
217 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
220 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
218
221
219 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
222 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
220 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
223 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
221
224
222 bool lookForPropertyAndCache(const char* memberName);
225 bool lookForPropertyAndCache(const char* memberName);
223 bool lookForMethodAndCache(const char* memberName);
226 bool lookForMethodAndCache(const char* memberName);
224 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
227 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
225
228
226 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
229 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
227 int findCharOffset(const char* sigStart, char someChar);
230 int findCharOffset(const char* sigStart, char someChar);
228
231
229 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
232 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
230
233
231 PythonQtSlotInfo* _constructors;
234 PythonQtSlotInfo* _constructors;
232 PythonQtSlotInfo* _destructor;
235 PythonQtSlotInfo* _destructor;
233 QList<PythonQtSlotInfo*> _decoratorSlots;
236 QList<PythonQtSlotInfo*> _decoratorSlots;
234
237
235 QList<PythonQtObjectPtr> _enumWrappers;
238 QList<PythonQtObjectPtr> _enumWrappers;
236
239
237 const QMetaObject* _meta;
240 const QMetaObject* _meta;
238
241
239 QByteArray _wrappedClassName;
242 QByteArray _wrappedClassName;
240 QList<ParentClassInfo> _parentClasses;
243 QList<ParentClassInfo> _parentClasses;
241
244
242 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
245 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
243
246
244 QObject* _decoratorProvider;
247 QObject* _decoratorProvider;
245 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
248 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
246
249
247 PyObject* _pythonQtClassWrapper;
250 PyObject* _pythonQtClassWrapper;
248
251
249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
252 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
250
253
251 int _metaTypeId;
254 int _metaTypeId;
252 int _typeSlots;
255 int _typeSlots;
253
256
254 bool _isQObject;
257 bool _isQObject;
255 bool _enumsCreated;
258 bool _enumsCreated;
256
259
257 };
260 };
258
261
259 //---------------------------------------------------------------
262 //---------------------------------------------------------------
260
263
261
264
262 #endif
265 #endif
@@ -1,462 +1,494
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 "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
49 #include "PythonQtInstanceWrapper.h"
50
50
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 {
52 {
53 PyObject* result = NULL;
53 PyObject* result = NULL;
54 static QByteArray memberName = "__invert__";
54 static QByteArray memberName = "__invert__";
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 }
58 }
59 return result;
59 return result;
60 }
60 }
61
61
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 {
63 {
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 if (result) {
65 if (result) {
66 static QByteArray memberName = "__nonzero__";
66 static QByteArray memberName = "__nonzero__";
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 if (resultObj == Py_False) {
70 if (resultObj == Py_False) {
71 result = 0;
71 result = 0;
72 }
72 }
73 Py_XDECREF(resultObj);
73 Py_XDECREF(resultObj);
74 }
74 }
75 }
75 }
76 return result;
76 return result;
77 }
77 }
78
78
79
79
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 {
81 {
82 // since we disabled type checking, we can receive any object as self, but we currently only support
82 // 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.
83 // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
84 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
84 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
85 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
85 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
86 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
86 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
87 return NULL;
87 return NULL;
88 }
88 }
89 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
89 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
90 PyObject* result = NULL;
90 PyObject* result = NULL;
91 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
91 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
92 if (opSlot._type == PythonQtMemberInfo::Slot) {
92 if (opSlot._type == PythonQtMemberInfo::Slot) {
93 // TODO get rid of tuple
93 // TODO get rid of tuple
94 PyObject* args = PyTuple_New(1);
94 PyObject* args = PyTuple_New(1);
95 Py_INCREF(other);
95 Py_INCREF(other);
96 PyTuple_SET_ITEM(args, 0, other);
96 PyTuple_SET_ITEM(args, 0, other);
97 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
97 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
98 Py_DECREF(args);
98 Py_DECREF(args);
99 if (!result && !fallbackOpName.isEmpty()) {
99 if (!result && !fallbackOpName.isEmpty()) {
100 // try fallback if we did not get a result
100 // try fallback if we did not get a result
101 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
101 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
102 }
102 }
103 }
103 }
104 return result;
104 return result;
105 }
105 }
106
106
107 #define BINARY_OP(NAME) \
107 #define BINARY_OP(NAME) \
108 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
108 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
109 { \
109 { \
110 static const QByteArray opName("__" #NAME "__"); \
110 static const QByteArray opName("__" #NAME "__"); \
111 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
111 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
112 }
112 }
113
113
114 #define BINARY_OP_INPLACE(NAME) \
114 #define BINARY_OP_INPLACE(NAME) \
115 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
115 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
116 { \
116 { \
117 static const QByteArray opName("__i" #NAME "__"); \
117 static const QByteArray opName("__i" #NAME "__"); \
118 static const QByteArray fallbackName("__" #NAME "__"); \
118 static const QByteArray fallbackName("__" #NAME "__"); \
119 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
119 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
120 }
120 }
121
121
122 BINARY_OP(add)
122 BINARY_OP(add)
123 BINARY_OP(sub)
123 BINARY_OP(sub)
124 BINARY_OP(mul)
124 BINARY_OP(mul)
125 BINARY_OP(div)
125 BINARY_OP(div)
126 BINARY_OP(and)
126 BINARY_OP(and)
127 BINARY_OP(or)
127 BINARY_OP(or)
128 BINARY_OP(xor)
128 BINARY_OP(xor)
129 BINARY_OP(mod)
129 BINARY_OP(mod)
130 BINARY_OP(lshift)
130 BINARY_OP(lshift)
131 BINARY_OP(rshift)
131 BINARY_OP(rshift)
132
132
133 BINARY_OP_INPLACE(add)
133 BINARY_OP_INPLACE(add)
134 BINARY_OP_INPLACE(sub)
134 BINARY_OP_INPLACE(sub)
135 BINARY_OP_INPLACE(mul)
135 BINARY_OP_INPLACE(mul)
136 BINARY_OP_INPLACE(div)
136 BINARY_OP_INPLACE(div)
137 BINARY_OP_INPLACE(and)
137 BINARY_OP_INPLACE(and)
138 BINARY_OP_INPLACE(or)
138 BINARY_OP_INPLACE(or)
139 BINARY_OP_INPLACE(xor)
139 BINARY_OP_INPLACE(xor)
140 BINARY_OP_INPLACE(mod)
140 BINARY_OP_INPLACE(mod)
141 BINARY_OP_INPLACE(lshift)
141 BINARY_OP_INPLACE(lshift)
142 BINARY_OP_INPLACE(rshift)
142 BINARY_OP_INPLACE(rshift)
143
143
144 static void initializeSlots(PythonQtClassWrapper* wrap)
144 static void initializeSlots(PythonQtClassWrapper* wrap)
145 {
145 {
146 int typeSlots = wrap->classInfo()->typeSlots();
146 int typeSlots = wrap->classInfo()->typeSlots();
147 if (typeSlots) {
147 if (typeSlots) {
148 if (typeSlots & PythonQt::Type_Add) {
148 if (typeSlots & PythonQt::Type_Add) {
149 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
149 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
150 }
150 }
151 if (typeSlots & PythonQt::Type_Subtract) {
151 if (typeSlots & PythonQt::Type_Subtract) {
152 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
152 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
153 }
153 }
154 if (typeSlots & PythonQt::Type_Multiply) {
154 if (typeSlots & PythonQt::Type_Multiply) {
155 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
155 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
156 }
156 }
157 if (typeSlots & PythonQt::Type_Divide) {
157 if (typeSlots & PythonQt::Type_Divide) {
158 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
158 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
159 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
159 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
160 }
160 }
161 if (typeSlots & PythonQt::Type_And) {
161 if (typeSlots & PythonQt::Type_And) {
162 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
162 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
163 }
163 }
164 if (typeSlots & PythonQt::Type_Or) {
164 if (typeSlots & PythonQt::Type_Or) {
165 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
165 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
166 }
166 }
167 if (typeSlots & PythonQt::Type_Xor) {
167 if (typeSlots & PythonQt::Type_Xor) {
168 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
168 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
169 }
169 }
170 if (typeSlots & PythonQt::Type_Mod) {
170 if (typeSlots & PythonQt::Type_Mod) {
171 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
171 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
172 }
172 }
173 if (typeSlots & PythonQt::Type_LShift) {
173 if (typeSlots & PythonQt::Type_LShift) {
174 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
174 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
175 }
175 }
176 if (typeSlots & PythonQt::Type_RShift) {
176 if (typeSlots & PythonQt::Type_RShift) {
177 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
177 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
178 }
178 }
179
179
180 if (typeSlots & PythonQt::Type_InplaceAdd) {
180 if (typeSlots & PythonQt::Type_InplaceAdd) {
181 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
181 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
182 }
182 }
183 if (typeSlots & PythonQt::Type_InplaceSubtract) {
183 if (typeSlots & PythonQt::Type_InplaceSubtract) {
184 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
184 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
185 }
185 }
186 if (typeSlots & PythonQt::Type_InplaceMultiply) {
186 if (typeSlots & PythonQt::Type_InplaceMultiply) {
187 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
187 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
188 }
188 }
189 if (typeSlots & PythonQt::Type_InplaceDivide) {
189 if (typeSlots & PythonQt::Type_InplaceDivide) {
190 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
190 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
191 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
191 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
192 }
192 }
193 if (typeSlots & PythonQt::Type_InplaceAnd) {
193 if (typeSlots & PythonQt::Type_InplaceAnd) {
194 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
194 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
195 }
195 }
196 if (typeSlots & PythonQt::Type_InplaceOr) {
196 if (typeSlots & PythonQt::Type_InplaceOr) {
197 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
197 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
198 }
198 }
199 if (typeSlots & PythonQt::Type_InplaceXor) {
199 if (typeSlots & PythonQt::Type_InplaceXor) {
200 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
200 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
201 }
201 }
202 if (typeSlots & PythonQt::Type_InplaceMod) {
202 if (typeSlots & PythonQt::Type_InplaceMod) {
203 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
203 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
204 }
204 }
205 if (typeSlots & PythonQt::Type_InplaceLShift) {
205 if (typeSlots & PythonQt::Type_InplaceLShift) {
206 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
206 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
207 }
207 }
208 if (typeSlots & PythonQt::Type_InplaceRShift) {
208 if (typeSlots & PythonQt::Type_InplaceRShift) {
209 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
209 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
210 }
210 }
211 if (typeSlots & PythonQt::Type_Invert) {
211 if (typeSlots & PythonQt::Type_Invert) {
212 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
212 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
213 }
213 }
214 if (typeSlots & PythonQt::Type_NonZero) {
214 if (typeSlots & PythonQt::Type_NonZero) {
215 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
215 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
216 }
216 }
217 }
217 }
218 }
218 }
219
219
220 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
220 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
221 {
221 {
222 // call the default type alloc
222 // call the default type alloc
223 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
223 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
224
224
225 // take current class type, if we are called via newPythonQtClassWrapper()
225 // take current class type, if we are called via newPythonQtClassWrapper()
226 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
226 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
227 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
227 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
228 if (wrap->_classInfo) {
228 if (wrap->_classInfo) {
229 initializeSlots(wrap);
229 initializeSlots(wrap);
230 }
230 }
231
231
232 return obj;
232 return obj;
233 }
233 }
234
234
235
235
236 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
236 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
237 {
237 {
238 // call the default type init
238 // call the default type init
239 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
239 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
240 return -1;
240 return -1;
241 }
241 }
242
242
243 // if we have no CPP class information, try our base class
243 // if we have no CPP class information, try our base class
244 if (!self->classInfo()) {
244 if (!self->classInfo()) {
245 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
245 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
246
246
247 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
247 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
248 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
248 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
249 return -1;
249 return -1;
250 }
250 }
251
251
252 // take the class info from the superType
252 // take the class info from the superType
253 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
253 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
254 }
254 }
255
255
256 return 0;
256 return 0;
257 }
257 }
258
258
259 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
259 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
260 {
260 {
261 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
261 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
262 }
262 }
263
263
264 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
264 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
265 {
265 {
266 return PythonQt::self()->helpCalled(type->classInfo());
266 return PythonQt::self()->helpCalled(type->classInfo());
267 }
267 }
268
268
269 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
270 {
271 Q_UNUSED(type);
272
273 Py_ssize_t argc = PyTuple_Size(args);
274 if (argc>0) {
275 PyObject* self = PyTuple_GET_ITEM(args, 0);
276 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
277 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
278 }
279 }
280 return NULL;
281 }
282
283 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
284 {
285 Q_UNUSED(type);
286 PythonQtInstanceWrapper* wrapper = NULL;
287 char *name = NULL;
288 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
289 return NULL;
290 }
291 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
292 }
293
269 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
294 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
270 {
295 {
271 Py_ssize_t argc = PyTuple_Size(args);
296 Py_ssize_t argc = PyTuple_Size(args);
272 if (argc>0) {
297 if (argc>0) {
273 // we need to call __init__ of the instance
298 // we need to call __init__ of the instance
274 PyObject* self = PyTuple_GET_ITEM(args, 0);
299 PyObject* self = PyTuple_GET_ITEM(args, 0);
275 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
300 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
276 PyObject* newargs = PyTuple_New(argc-1);
301 PyObject* newargs = PyTuple_New(argc-1);
277 for (int i = 0;i<argc-1; i++) {
302 for (int i = 0;i<argc-1; i++) {
278 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
303 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
279 }
304 }
280 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
305 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
281 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
306 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
282 Py_DECREF(newargs);
307 Py_DECREF(newargs);
283 if (result==0) {
308 if (result==0) {
284 Py_INCREF(Py_None);
309 Py_INCREF(Py_None);
285 return Py_None;
310 return Py_None;
286 } else {
311 } else {
287 // init failed!
312 // init failed!
288 }
313 }
289 } else {
314 } else {
290 // self not of correct type!
315 // self not of correct type!
291 }
316 }
292 } else {
317 } else {
293 // wrong number of args
318 // wrong number of args
294 }
319 }
295 return NULL;
320 return NULL;
296 }
321 }
297
322
323
298 static PyMethodDef PythonQtClassWrapper_methods[] = {
324 static PyMethodDef PythonQtClassWrapper_methods[] = {
299 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
325 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
300 "Return the classname of the object"
326 "Init function"
301 },
327 },
302 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
328 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
303 "Return the classname of the object"
329 "Return the classname of the object"
304 },
330 },
331 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
332 "Returns if the class inherits or is of given type name"
333 },
305 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
334 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
306 "Shows the help of available methods for this class"
335 "Shows the help of available methods for this class"
307 },
336 },
337 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
338 "Deletes the given C++ object"
339 },
308 {NULL, NULL, 0 , NULL} /* Sentinel */
340 {NULL, NULL, 0 , NULL} /* Sentinel */
309 };
341 };
310
342
311
343
312 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
344 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
313 {
345 {
314 const char *attributeName;
346 const char *attributeName;
315 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
347 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
316
348
317 if ((attributeName = PyString_AsString(name)) == NULL) {
349 if ((attributeName = PyString_AsString(name)) == NULL) {
318 return NULL;
350 return NULL;
319 }
351 }
320 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
352 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
321 return NULL;
353 return NULL;
322 }
354 }
323
355
324 if (qstrcmp(attributeName, "__dict__")==0) {
356 if (qstrcmp(attributeName, "__dict__")==0) {
325 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
357 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
326 if (!wrapper->classInfo()) {
358 if (!wrapper->classInfo()) {
327 Py_INCREF(dict);
359 Py_INCREF(dict);
328 return dict;
360 return dict;
329 }
361 }
330 dict = PyDict_Copy(dict);
362 dict = PyDict_Copy(dict);
331
363
332 QStringList l = wrapper->classInfo()->memberList(false);
364 QStringList l = wrapper->classInfo()->memberList(false);
333 foreach (QString name, l) {
365 foreach (QString name, l) {
334 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
366 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
335 if (o) {
367 if (o) {
336 PyDict_SetItemString(dict, name.toLatin1().data(), o);
368 PyDict_SetItemString(dict, name.toLatin1().data(), o);
337 Py_DECREF(o);
369 Py_DECREF(o);
338 } else {
370 } else {
339 // it must have been a property or child, which we do not know as a class object...
371 // it must have been a property or child, which we do not know as a class object...
340 }
372 }
341 }
373 }
342 if (wrapper->classInfo()->constructors()) {
374 if (wrapper->classInfo()->constructors()) {
343 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
375 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
344 PyDict_SetItemString(dict, "__init__", func);
376 PyDict_SetItemString(dict, "__init__", func);
345 Py_DECREF(func);
377 Py_DECREF(func);
346 }
378 }
347 for (int i = 1;i<3;i++) {
379 for (int i = 1; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
348 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
380 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
349 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
381 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
350 Py_DECREF(func);
382 Py_DECREF(func);
351 }
383 }
352 return dict;
384 return dict;
353 }
385 }
354
386
355 if (wrapper->classInfo()) {
387 if (wrapper->classInfo()) {
356 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
388 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
357 if (member._type == PythonQtMemberInfo::EnumValue) {
389 if (member._type == PythonQtMemberInfo::EnumValue) {
358 PyObject* enumValue = member._enumValue;
390 PyObject* enumValue = member._enumValue;
359 Py_INCREF(enumValue);
391 Py_INCREF(enumValue);
360 return enumValue;
392 return enumValue;
361 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
393 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
362 PyObject* enumWrapper = member._enumWrapper;
394 PyObject* enumWrapper = member._enumWrapper;
363 Py_INCREF(enumWrapper);
395 Py_INCREF(enumWrapper);
364 return enumWrapper;
396 return enumWrapper;
365 } else if (member._type == PythonQtMemberInfo::Slot) {
397 } else if (member._type == PythonQtMemberInfo::Slot) {
366 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
398 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
367 return PythonQtSlotFunction_New(member._slot, obj, NULL);
399 return PythonQtSlotFunction_New(member._slot, obj, NULL);
368 }
400 }
369 }
401 }
370
402
371 // look for the interal methods (className(), help())
403 // look for the interal methods (className(), help())
372 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
404 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
373 if (internalMethod) {
405 if (internalMethod) {
374 return internalMethod;
406 return internalMethod;
375 }
407 }
376 PyErr_Clear();
408 PyErr_Clear();
377
409
378 // look in super
410 // look in super
379 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
411 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
380 if (superAttr) {
412 if (superAttr) {
381 return superAttr;
413 return superAttr;
382 }
414 }
383
415
384 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
416 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
385 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
417 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
386 return NULL;
418 return NULL;
387 }
419 }
388
420
389 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
421 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
390 {
422 {
391 return PyType_Type.tp_setattro(obj,name,value);
423 return PyType_Type.tp_setattro(obj,name,value);
392 }
424 }
393
425
394 /*
426 /*
395 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
427 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
396 {
428 {
397 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
429 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
398 if (wrapper->classInfo()->isCPPWrapper()) {
430 if (wrapper->classInfo()->isCPPWrapper()) {
399 const QMetaObject* meta = wrapper->classInfo()->metaObject();
431 const QMetaObject* meta = wrapper->classInfo()->metaObject();
400 if (!meta) {
432 if (!meta) {
401 QObject* decorator = wrapper->classInfo()->decorator();
433 QObject* decorator = wrapper->classInfo()->decorator();
402 if (decorator) {
434 if (decorator) {
403 meta = decorator->metaObject();
435 meta = decorator->metaObject();
404 }
436 }
405 }
437 }
406 if (meta) {
438 if (meta) {
407 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
439 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
408 } else {
440 } else {
409 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
441 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
410 }
442 }
411 } else {
443 } else {
412 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
444 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
413 }
445 }
414 }
446 }
415
447
416 */
448 */
417
449
418 PyTypeObject PythonQtClassWrapper_Type = {
450 PyTypeObject PythonQtClassWrapper_Type = {
419 PyObject_HEAD_INIT(NULL)
451 PyObject_HEAD_INIT(NULL)
420 0, /*ob_size*/
452 0, /*ob_size*/
421 "PythonQt.PythonQtClassWrapper", /*tp_name*/
453 "PythonQt.PythonQtClassWrapper", /*tp_name*/
422 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
454 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
423 0, /*tp_itemsize*/
455 0, /*tp_itemsize*/
424 0, /*tp_dealloc*/
456 0, /*tp_dealloc*/
425 0, /*tp_print*/
457 0, /*tp_print*/
426 0, /*tp_getattr*/
458 0, /*tp_getattr*/
427 0, /*tp_setattr*/
459 0, /*tp_setattr*/
428 0, /*tp_compare*/
460 0, /*tp_compare*/
429 0, //PythonQtClassWrapper_repr, /*tp_repr*/
461 0, //PythonQtClassWrapper_repr, /*tp_repr*/
430 0, /*tp_as_number*/
462 0, /*tp_as_number*/
431 0, /*tp_as_sequence*/
463 0, /*tp_as_sequence*/
432 0, /*tp_as_mapping*/
464 0, /*tp_as_mapping*/
433 0, /*tp_hash */
465 0, /*tp_hash */
434 0, /*tp_call*/
466 0, /*tp_call*/
435 0, /*tp_str*/
467 0, /*tp_str*/
436 PythonQtClassWrapper_getattro, /*tp_getattro*/
468 PythonQtClassWrapper_getattro, /*tp_getattro*/
437 PythonQtClassWrapper_setattro, /*tp_setattro*/
469 PythonQtClassWrapper_setattro, /*tp_setattro*/
438 0, /*tp_as_buffer*/
470 0, /*tp_as_buffer*/
439 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
471 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
440 0, /* tp_doc */
472 0, /* tp_doc */
441 0, /* tp_traverse */
473 0, /* tp_traverse */
442 0, /* tp_clear */
474 0, /* tp_clear */
443 0, /* tp_richcompare */
475 0, /* tp_richcompare */
444 0, /* tp_weaklistoffset */
476 0, /* tp_weaklistoffset */
445 0, /* tp_iter */
477 0, /* tp_iter */
446 0, /* tp_iternext */
478 0, /* tp_iternext */
447 0, /* tp_methods */
479 0, /* tp_methods */
448 0, /* tp_members */
480 0, /* tp_members */
449 0, /* tp_getset */
481 0, /* tp_getset */
450 0, /* tp_base */
482 0, /* tp_base */
451 0, /* tp_dict */
483 0, /* tp_dict */
452 0, /* tp_descr_get */
484 0, /* tp_descr_get */
453 0, /* tp_descr_set */
485 0, /* tp_descr_set */
454 0, /* tp_dictoffset */
486 0, /* tp_dictoffset */
455 (initproc)PythonQtClassWrapper_init, /* tp_init */
487 (initproc)PythonQtClassWrapper_init, /* tp_init */
456 PythonQtClassWrapper_alloc, /* tp_alloc */
488 PythonQtClassWrapper_alloc, /* tp_alloc */
457 0, /* tp_new */
489 0, /* tp_new */
458 0, /* tp_free */
490 0, /* tp_free */
459 };
491 };
460
492
461 //-------------------------------------------------------
493 //-------------------------------------------------------
462
494
@@ -1,1236 +1,1236
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 PythonQtConversion.cpp
35 // \file PythonQtConversion.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 "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (info.pointerCount==0) {
65 if (info.pointerCount==0) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 if (innerType.endsWith("*")) {
84 if (innerType.endsWith("*")) {
85 innerType.truncate(innerType.length()-1);
85 innerType.truncate(innerType.length()-1);
86 QList<void*>* listPtr = NULL;
86 QList<void*>* listPtr = NULL;
87 if (info.pointerCount == 1) {
87 if (info.pointerCount == 1) {
88 listPtr = *((QList<void*>**)data);
88 listPtr = *((QList<void*>**)data);
89 } else if (info.pointerCount == 0) {
89 } else if (info.pointerCount == 0) {
90 listPtr = (QList<void*>*)data;
90 listPtr = (QList<void*>*)data;
91 }
91 }
92 if (listPtr) {
92 if (listPtr) {
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
94 } else {
94 } else {
95 return NULL;
95 return NULL;
96 }
96 }
97 }
97 }
98 }
98 }
99
99
100 if (info.typeId >= QMetaType::User) {
100 if (info.typeId >= QMetaType::User) {
101 // if a converter is registered, we use is:
101 // if a converter is registered, we use is:
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
103 if (converter) {
103 if (converter) {
104 return (*converter)(data, info.typeId);
104 return (*converter)(data, info.typeId);
105 }
105 }
106 }
106 }
107
107
108 // special handling did not match, so we convert the usual way (either pointer or value version):
108 // special handling did not match, so we convert the usual way (either pointer or value version):
109 if (info.pointerCount == 1) {
109 if (info.pointerCount == 1) {
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
112 } else if (info.pointerCount == 0) {
112 } else if (info.pointerCount == 0) {
113 // handle values that are not yet handled and not pointers
113 // handle values that are not yet handled and not pointers
114 return ConvertQtValueToPythonInternal(info.typeId, data);
114 return ConvertQtValueToPythonInternal(info.typeId, data);
115 } else {
115 } else {
116 return NULL;
116 return NULL;
117 }
117 }
118 }
118 }
119
119
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
121 switch (type) {
121 switch (type) {
122 case QMetaType::Void:
122 case QMetaType::Void:
123 Py_INCREF(Py_None);
123 Py_INCREF(Py_None);
124 return Py_None;
124 return Py_None;
125 case QMetaType::Char:
125 case QMetaType::Char:
126 return PyInt_FromLong(*((char*)data));
126 return PyInt_FromLong(*((char*)data));
127 case QMetaType::UChar:
127 case QMetaType::UChar:
128 return PyInt_FromLong(*((unsigned char*)data));
128 return PyInt_FromLong(*((unsigned char*)data));
129 case QMetaType::Short:
129 case QMetaType::Short:
130 return PyInt_FromLong(*((short*)data));
130 return PyInt_FromLong(*((short*)data));
131 case QMetaType::UShort:
131 case QMetaType::UShort:
132 return PyInt_FromLong(*((unsigned short*)data));
132 return PyInt_FromLong(*((unsigned short*)data));
133 case QMetaType::Long:
133 case QMetaType::Long:
134 return PyInt_FromLong(*((long*)data));
134 return PyInt_FromLong(*((long*)data));
135 case QMetaType::ULong:
135 case QMetaType::ULong:
136 // does not fit into simple int of python
136 // does not fit into simple int of python
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
138 case QMetaType::Bool:
138 case QMetaType::Bool:
139 return PythonQtConv::GetPyBool(*((bool*)data));
139 return PythonQtConv::GetPyBool(*((bool*)data));
140 case QMetaType::Int:
140 case QMetaType::Int:
141 return PyInt_FromLong(*((int*)data));
141 return PyInt_FromLong(*((int*)data));
142 case QMetaType::UInt:
142 case QMetaType::UInt:
143 // does not fit into simple int of python
143 // does not fit into simple int of python
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
145 case QMetaType::QChar:
145 case QMetaType::QChar:
146 return PyInt_FromLong(*((short*)data));
146 return PyInt_FromLong(*((short*)data));
147 case QMetaType::Float:
147 case QMetaType::Float:
148 return PyFloat_FromDouble(*((float*)data));
148 return PyFloat_FromDouble(*((float*)data));
149 case QMetaType::Double:
149 case QMetaType::Double:
150 return PyFloat_FromDouble(*((double*)data));
150 return PyFloat_FromDouble(*((double*)data));
151 case QMetaType::LongLong:
151 case QMetaType::LongLong:
152 return PyLong_FromLongLong(*((qint64*)data));
152 return PyLong_FromLongLong(*((qint64*)data));
153 case QMetaType::ULongLong:
153 case QMetaType::ULongLong:
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
155 // implicit conversion from QByteArray to str has been removed:
155 // implicit conversion from QByteArray to str has been removed:
156 //case QMetaType::QByteArray: {
156 //case QMetaType::QByteArray: {
157 // QByteArray* v = (QByteArray*) data;
157 // QByteArray* v = (QByteArray*) data;
158 // return PyString_FromStringAndSize(*v, v->size());
158 // return PyString_FromStringAndSize(*v, v->size());
159 // }
159 // }
160 case QMetaType::QVariantMap:
160 case QMetaType::QVariantMap:
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
162 case QMetaType::QVariantList:
162 case QMetaType::QVariantList:
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
164 case QMetaType::QString:
164 case QMetaType::QString:
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
166 case QMetaType::QStringList:
166 case QMetaType::QStringList:
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
168
168
169 case PythonQtMethodInfo::Variant:
169 case PythonQtMethodInfo::Variant:
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
171 case QMetaType::QObjectStar:
171 case QMetaType::QObjectStar:
172 case QMetaType::QWidgetStar:
172 case QMetaType::QWidgetStar:
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
174
174
175 default:
175 default:
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
179 Py_INCREF(o);
179 Py_INCREF(o);
180 return o;
180 return o;
181 } else {
181 } else {
182 if (type > 0) {
182 if (type > 0) {
183 // if the type is known, we can construct it via QMetaType::construct
183 // if the type is known, we can construct it via QMetaType::construct
184 void* newCPPObject = QMetaType::construct(type, data);
184 void* newCPPObject = QMetaType::construct(type, data);
185 // XXX this could be optimized by using metatypeid directly
185 // XXX this could be optimized by using metatypeid directly
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
187 wrap->_ownedByPythonQt = true;
187 wrap->_ownedByPythonQt = true;
188 wrap->_useQMetaTypeDestroy = true;
188 wrap->_useQMetaTypeDestroy = true;
189 return (PyObject*)wrap;
189 return (PyObject*)wrap;
190 }
190 }
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
192 }
192 }
193 }
193 }
194 Py_INCREF(Py_None);
194 Py_INCREF(Py_None);
195 return Py_None;
195 return Py_None;
196 }
196 }
197
197
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
199 void* ptr = NULL;
199 void* ptr = NULL;
200 if (info.pointerCount>1) {
200 if (info.pointerCount>1) {
201 return NULL;
201 return NULL;
202 } else if (info.pointerCount==1) {
202 } else if (info.pointerCount==1) {
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
204 } else if (info.enumWrapper) {
204 } else if (info.enumWrapper) {
205 // create enum return value
205 // create enum return value
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
207 } else {
207 } else {
208 switch (info.typeId) {
208 switch (info.typeId) {
209 case QMetaType::Char:
209 case QMetaType::Char:
210 case QMetaType::UChar:
210 case QMetaType::UChar:
211 case QMetaType::Short:
211 case QMetaType::Short:
212 case QMetaType::UShort:
212 case QMetaType::UShort:
213 case QMetaType::Long:
213 case QMetaType::Long:
214 case QMetaType::ULong:
214 case QMetaType::ULong:
215 case QMetaType::Bool:
215 case QMetaType::Bool:
216 case QMetaType::Int:
216 case QMetaType::Int:
217 case QMetaType::UInt:
217 case QMetaType::UInt:
218 case QMetaType::QChar:
218 case QMetaType::QChar:
219 case QMetaType::Float:
219 case QMetaType::Float:
220 case QMetaType::Double:
220 case QMetaType::Double:
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
222 break;
222 break;
223 case PythonQtMethodInfo::Variant:
223 case PythonQtMethodInfo::Variant:
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
225 // return the ptr to the variant
225 // return the ptr to the variant
226 break;
226 break;
227 default:
227 default:
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
230 if (info.name.startsWith("QList<")) {
230 if (info.name.startsWith("QList<")) {
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
232 if (innerType.endsWith("*")) {
232 if (innerType.endsWith("*")) {
233 static int id = QMetaType::type("QList<void*>");
233 static int id = QMetaType::type("QList<void*>");
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
235 // return the constData pointer that will be filled with the result value later on
235 // return the constData pointer that will be filled with the result value later on
236 ptr = (void*)((QVariant*)ptr)->constData();
236 ptr = (void*)((QVariant*)ptr)->constData();
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
242 // everything else is stored in a QVariant, if we know the meta type...
242 // everything else is stored in a QVariant, if we know the meta type...
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
244 // return the constData pointer that will be filled with the result value later on
244 // return the constData pointer that will be filled with the result value later on
245 ptr = (void*)((QVariant*)ptr)->constData();
245 ptr = (void*)((QVariant*)ptr)->constData();
246 }
246 }
247 }
247 }
248 }
248 }
249 return ptr;
249 return ptr;
250 }
250 }
251
251
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
253 {
253 {
254 void* object;
254 void* object;
255 if (wrapper->classInfo()->isCPPWrapper()) {
255 if (wrapper->classInfo()->isCPPWrapper()) {
256 object = wrapper->_wrappedPtr;
256 object = wrapper->_wrappedPtr;
257 } else {
257 } else {
258 QObject* tmp = wrapper->_obj;
258 QObject* tmp = wrapper->_obj;
259 object = tmp;
259 object = tmp;
260 }
260 }
261 if (object) {
261 if (object) {
262 // if we can be upcasted to the given name, we pass the casted pointer in:
262 // if we can be upcasted to the given name, we pass the casted pointer in:
263 object = wrapper->classInfo()->castTo(object, className);
263 object = wrapper->classInfo()->castTo(object, className);
264 ok = object!=NULL;
264 ok = object!=NULL;
265 } else {
265 } else {
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
267 ok = wrapper->classInfo()->inherits(className);
267 ok = wrapper->classInfo()->inherits(className);
268 }
268 }
269 return object;
269 return object;
270 }
270 }
271
271
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
273 {
273 {
274 void* ptr = alreadyAllocatedCPPObject;
274 void* ptr = alreadyAllocatedCPPObject;
275
275
276 static int penId = QMetaType::type("QPen");
276 static int penId = QMetaType::type("QPen");
277 static int brushId = QMetaType::type("QBrush");
277 static int brushId = QMetaType::type("QBrush");
278 static int cursorId = QMetaType::type("QCursor");
278 static int cursorId = QMetaType::type("QCursor");
279 static int colorId = QMetaType::type("QColor");
279 static int colorId = QMetaType::type("QColor");
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
281 if (typeId == cursorId) {
281 if (typeId == cursorId) {
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
285 if (!ptr) {
285 if (!ptr) {
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
287 ptr = (void*)((QVariant*)ptr)->constData();
287 ptr = (void*)((QVariant*)ptr)->constData();
288 }
288 }
289 *((QCursor*)ptr) = QCursor(val);
289 *((QCursor*)ptr) = QCursor(val);
290 return ptr;
290 return ptr;
291 }
291 }
292 } else if (typeId == penId) {
292 } else if (typeId == penId) {
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
297 if (!ptr) {
297 if (!ptr) {
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
299 ptr = (void*)((QVariant*)ptr)->constData();
299 ptr = (void*)((QVariant*)ptr)->constData();
300 }
300 }
301 *((QPen*)ptr) = QPen(QColor(val));
301 *((QPen*)ptr) = QPen(QColor(val));
302 return ptr;
302 return ptr;
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
304 if (!ptr) {
304 if (!ptr) {
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
306 ptr = (void*)((QVariant*)ptr)->constData();
306 ptr = (void*)((QVariant*)ptr)->constData();
307 }
307 }
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
309 return ptr;
309 return ptr;
310 }
310 }
311 } else if (typeId == brushId) {
311 } else if (typeId == brushId) {
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
316 if (!ptr) {
316 if (!ptr) {
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
318 ptr = (void*)((QVariant*)ptr)->constData();
318 ptr = (void*)((QVariant*)ptr)->constData();
319 }
319 }
320 *((QBrush*)ptr) = QBrush(QColor(val));
320 *((QBrush*)ptr) = QBrush(QColor(val));
321 return ptr;
321 return ptr;
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
323 if (!ptr) {
323 if (!ptr) {
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
325 ptr = (void*)((QVariant*)ptr)->constData();
325 ptr = (void*)((QVariant*)ptr)->constData();
326 }
326 }
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
328 return ptr;
328 return ptr;
329 }
329 }
330 } else if (typeId == colorId) {
330 } else if (typeId == colorId) {
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
334 if (!ptr) {
334 if (!ptr) {
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
336 ptr = (void*)((QVariant*)ptr)->constData();
336 ptr = (void*)((QVariant*)ptr)->constData();
337 }
337 }
338 *((QColor*)ptr) = QColor(val);
338 *((QColor*)ptr) = QColor(val);
339 return ptr;
339 return ptr;
340 }
340 }
341 }
341 }
342 return NULL;
342 return NULL;
343 }
343 }
344
344
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
346 {
346 {
347 bool ok = false;
347 bool ok = false;
348 void* ptr = NULL;
348 void* ptr = NULL;
349
349
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
351 if (info.pointerCount==0 && !strict) {
351 if (info.pointerCount==0 && !strict) {
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
353 if (ptr) {
353 if (ptr) {
354 return ptr;
354 return ptr;
355 }
355 }
356 }
356 }
357
357
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
360 // (the Variant case is handled below in a switch)
360 // (the Variant case is handled below in a switch)
361
361
362 // a C++ wrapper (can be passed as pointer or reference)
362 // a C++ wrapper (can be passed as pointer or reference)
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
364 void* object = castWrapperTo(wrap, info.name, ok);
364 void* object = castWrapperTo(wrap, info.name, ok);
365 if (ok) {
365 if (ok) {
366 if (info.pointerCount==1) {
366 if (info.pointerCount==1) {
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
369 } else if (info.pointerCount==0) {
369 } else if (info.pointerCount==0) {
370 // store the wrapped pointer directly, since we are a reference
370 // store the wrapped pointer directly, since we are a reference
371 ptr = object;
371 ptr = object;
372 }
372 }
373 } else {
373 } else {
374 // not matching
374 // not matching
375 }
375 }
376 } else if (info.pointerCount == 1) {
376 } else if (info.pointerCount == 1) {
377 // a pointer
377 // a pointer
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
379 {
379 {
380 QString str = PyObjGetString(obj, strict, ok);
380 QString str = PyObjGetString(obj, strict, ok);
381 if (ok) {
381 if (ok) {
382 void* ptr2 = NULL;
382 void* ptr2 = NULL;
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
385 }
385 }
386 } else if (info.name == "PyObject") {
386 } else if (info.name == "PyObject") {
387 // handle low level PyObject directly
387 // handle low level PyObject directly
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
389 } else if (obj == Py_None) {
389 } else if (obj == Py_None) {
390 // None is treated as a NULL ptr
390 // None is treated as a NULL ptr
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
392 } else {
392 } else {
393 // if we are not strict, we try if we are passed a 0 integer
393 // if we are not strict, we try if we are passed a 0 integer
394 if (!strict) {
394 if (!strict) {
395 bool ok;
395 bool ok;
396 int value = PyObjGetInt(obj, true, ok);
396 int value = PyObjGetInt(obj, true, ok);
397 if (ok && value==0) {
397 if (ok && value==0) {
398 // TODOXXX is this wise? or should it be expected from the programmer to use None?
398 // TODOXXX is this wise? or should it be expected from the programmer to use None?
399 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
399 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
400 }
400 }
401 }
401 }
402 }
402 }
403 } else if (info.pointerCount == 0) {
403 } else if (info.pointerCount == 0) {
404 // not a pointer
404 // not a pointer
405 switch (info.typeId) {
405 switch (info.typeId) {
406 case QMetaType::Char:
406 case QMetaType::Char:
407 {
407 {
408 int val = PyObjGetInt(obj, strict, ok);
408 int val = PyObjGetInt(obj, strict, ok);
409 if (ok) {
409 if (ok) {
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
411 }
411 }
412 }
412 }
413 break;
413 break;
414 case QMetaType::UChar:
414 case QMetaType::UChar:
415 {
415 {
416 int val = PyObjGetInt(obj, strict, ok);
416 int val = PyObjGetInt(obj, strict, ok);
417 if (ok) {
417 if (ok) {
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
419 }
419 }
420 }
420 }
421 break;
421 break;
422 case QMetaType::Short:
422 case QMetaType::Short:
423 {
423 {
424 int val = PyObjGetInt(obj, strict, ok);
424 int val = PyObjGetInt(obj, strict, ok);
425 if (ok) {
425 if (ok) {
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
427 }
427 }
428 }
428 }
429 break;
429 break;
430 case QMetaType::UShort:
430 case QMetaType::UShort:
431 {
431 {
432 int val = PyObjGetInt(obj, strict, ok);
432 int val = PyObjGetInt(obj, strict, ok);
433 if (ok) {
433 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
435 }
435 }
436 }
436 }
437 break;
437 break;
438 case QMetaType::Long:
438 case QMetaType::Long:
439 {
439 {
440 long val = (long)PyObjGetLongLong(obj, strict, ok);
440 long val = (long)PyObjGetLongLong(obj, strict, ok);
441 if (ok) {
441 if (ok) {
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
443 }
443 }
444 }
444 }
445 break;
445 break;
446 case QMetaType::ULong:
446 case QMetaType::ULong:
447 {
447 {
448 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
448 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
449 if (ok) {
449 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
451 }
451 }
452 }
452 }
453 break;
453 break;
454 case QMetaType::Bool:
454 case QMetaType::Bool:
455 {
455 {
456 bool val = PyObjGetBool(obj, strict, ok);
456 bool val = PyObjGetBool(obj, strict, ok);
457 if (ok) {
457 if (ok) {
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
459 }
459 }
460 }
460 }
461 break;
461 break;
462 case QMetaType::Int:
462 case QMetaType::Int:
463 {
463 {
464 int val = PyObjGetInt(obj, strict, ok);
464 int val = PyObjGetInt(obj, strict, ok);
465 if (ok) {
465 if (ok) {
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
467 }
467 }
468 }
468 }
469 break;
469 break;
470 case QMetaType::UInt:
470 case QMetaType::UInt:
471 {
471 {
472 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
472 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
473 if (ok) {
473 if (ok) {
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
475 }
475 }
476 }
476 }
477 break;
477 break;
478 case QMetaType::QChar:
478 case QMetaType::QChar:
479 {
479 {
480 int val = PyObjGetInt(obj, strict, ok);
480 int val = PyObjGetInt(obj, strict, ok);
481 if (ok) {
481 if (ok) {
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
483 }
483 }
484 }
484 }
485 break;
485 break;
486 case QMetaType::Float:
486 case QMetaType::Float:
487 {
487 {
488 float val = (float)PyObjGetDouble(obj, strict, ok);
488 float val = (float)PyObjGetDouble(obj, strict, ok);
489 if (ok) {
489 if (ok) {
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
491 }
491 }
492 }
492 }
493 break;
493 break;
494 case QMetaType::Double:
494 case QMetaType::Double:
495 {
495 {
496 double val = (double)PyObjGetDouble(obj, strict, ok);
496 double val = (double)PyObjGetDouble(obj, strict, ok);
497 if (ok) {
497 if (ok) {
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
499 }
499 }
500 }
500 }
501 break;
501 break;
502 case QMetaType::LongLong:
502 case QMetaType::LongLong:
503 {
503 {
504 qint64 val = PyObjGetLongLong(obj, strict, ok);
504 qint64 val = PyObjGetLongLong(obj, strict, ok);
505 if (ok) {
505 if (ok) {
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
507 }
507 }
508 }
508 }
509 break;
509 break;
510 case QMetaType::ULongLong:
510 case QMetaType::ULongLong:
511 {
511 {
512 quint64 val = PyObjGetULongLong(obj, strict, ok);
512 quint64 val = PyObjGetULongLong(obj, strict, ok);
513 if (ok) {
513 if (ok) {
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
515 }
515 }
516 }
516 }
517 break;
517 break;
518 case QMetaType::QByteArray:
518 case QMetaType::QByteArray:
519 {
519 {
520 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
520 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
521 if (ok) {
521 if (ok) {
522 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
522 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
523 ptr = (void*)((QVariant*)ptr)->constData();
523 ptr = (void*)((QVariant*)ptr)->constData();
524 }
524 }
525 }
525 }
526 break;
526 break;
527 case QMetaType::QString:
527 case QMetaType::QString:
528 {
528 {
529 QString str = PyObjGetString(obj, strict, ok);
529 QString str = PyObjGetString(obj, strict, ok);
530 if (ok) {
530 if (ok) {
531 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
531 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
532 ptr = (void*)((QVariant*)ptr)->constData();
532 ptr = (void*)((QVariant*)ptr)->constData();
533 }
533 }
534 }
534 }
535 break;
535 break;
536 case QMetaType::QStringList:
536 case QMetaType::QStringList:
537 {
537 {
538 QStringList l = PyObjToStringList(obj, strict, ok);
538 QStringList l = PyObjToStringList(obj, strict, ok);
539 if (ok) {
539 if (ok) {
540 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
540 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
541 ptr = (void*)((QVariant*)ptr)->constData();
541 ptr = (void*)((QVariant*)ptr)->constData();
542 }
542 }
543 }
543 }
544 break;
544 break;
545
545
546 case PythonQtMethodInfo::Variant:
546 case PythonQtMethodInfo::Variant:
547 {
547 {
548 QVariant v = PyObjToQVariant(obj);
548 QVariant v = PyObjToQVariant(obj);
549 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
549 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
550 // so we do not check v.isValid() here
550 // so we do not check v.isValid() here
551 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
551 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
552 }
552 }
553 break;
553 break;
554 default:
554 default:
555 {
555 {
556 // check for enum case
556 // check for enum case
557 if (info.enumWrapper) {
557 if (info.enumWrapper) {
558 unsigned int val;
558 unsigned int val;
559 ok = false;
559 ok = false;
560 if ((PyObject*)obj->ob_type == info.enumWrapper) {
560 if ((PyObject*)obj->ob_type == info.enumWrapper) {
561 // we have a exact enum type match:
561 // we have a exact enum type match:
562 val = PyInt_AS_LONG(obj);
562 val = PyInt_AS_LONG(obj);
563 ok = true;
563 ok = true;
564 } else if (!strict) {
564 } else if (!strict) {
565 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
565 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
566 // we want an integer overload to be taken first!
566 // we want an integer overload to be taken first!
567 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
567 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
568 }
568 }
569 if (ok) {
569 if (ok) {
570 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
570 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
571 return ptr;
571 return ptr;
572 } else {
572 } else {
573 return NULL;
573 return NULL;
574 }
574 }
575 }
575 }
576
576
577 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
577 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
578 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
578 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
579 if (info.name.startsWith("QList<")) {
579 if (info.name.startsWith("QList<")) {
580 QByteArray innerType = info.name.mid(6,info.name.length()-7);
580 QByteArray innerType = info.name.mid(6,info.name.length()-7);
581 if (innerType.endsWith("*")) {
581 if (innerType.endsWith("*")) {
582 innerType.truncate(innerType.length()-1);
582 innerType.truncate(innerType.length()-1);
583 static int id = QMetaType::type("QList<void*>");
583 static int id = QMetaType::type("QList<void*>");
584 if (!alreadyAllocatedCPPObject) {
584 if (!alreadyAllocatedCPPObject) {
585 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
585 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
586 ptr = (void*)((QVariant*)ptr)->constData();
586 ptr = (void*)((QVariant*)ptr)->constData();
587 } else {
587 } else {
588 ptr = alreadyAllocatedCPPObject;
588 ptr = alreadyAllocatedCPPObject;
589 }
589 }
590 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
590 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
591 if (ok) {
591 if (ok) {
592 return ptr;
592 return ptr;
593 } else {
593 } else {
594 return NULL;
594 return NULL;
595 }
595 }
596 }
596 }
597 }
597 }
598 }
598 }
599
599
600 // We only do this for registered type > QMetaType::User for performance reasons.
600 // We only do this for registered type > QMetaType::User for performance reasons.
601 if (info.typeId >= QMetaType::User) {
601 if (info.typeId >= QMetaType::User) {
602 // Maybe we have a special converter that is registered for that type:
602 // Maybe we have a special converter that is registered for that type:
603 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
603 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
604 if (converter) {
604 if (converter) {
605 if (!alreadyAllocatedCPPObject) {
605 if (!alreadyAllocatedCPPObject) {
606 // create a new empty variant of concrete type:
606 // create a new empty variant of concrete type:
607 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
607 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
608 ptr = (void*)((QVariant*)ptr)->constData();
608 ptr = (void*)((QVariant*)ptr)->constData();
609 } else {
609 } else {
610 ptr = alreadyAllocatedCPPObject;
610 ptr = alreadyAllocatedCPPObject;
611 }
611 }
612 // now call the converter, passing the internal object of the variant
612 // now call the converter, passing the internal object of the variant
613 ok = (*converter)(obj, ptr, info.typeId, strict);
613 ok = (*converter)(obj, ptr, info.typeId, strict);
614 if (ok) {
614 if (ok) {
615 return ptr;
615 return ptr;
616 } else {
616 } else {
617 return NULL;
617 return NULL;
618 }
618 }
619 }
619 }
620 }
620 }
621 // if no type id is available, conversion to a QVariant makes no sense/is not possible
621 // if no type id is available, conversion to a QVariant makes no sense/is not possible
622 if (info.typeId != PythonQtMethodInfo::Unknown) {
622 if (info.typeId != PythonQtMethodInfo::Unknown) {
623 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
623 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
624 QVariant v = PyObjToQVariant(obj, info.typeId);
624 QVariant v = PyObjToQVariant(obj, info.typeId);
625 if (v.isValid()) {
625 if (v.isValid()) {
626 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
626 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
627 ptr = (void*)((QVariant*)ptr)->constData();
627 ptr = (void*)((QVariant*)ptr)->constData();
628 }
628 }
629 }
629 }
630 }
630 }
631 }
631 }
632 }
632 }
633 return ptr;
633 return ptr;
634 }
634 }
635
635
636
636
637 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
637 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
638 QStringList v;
638 QStringList v;
639 ok = false;
639 ok = false;
640 // if we are strict, we do not want to convert a string to a stringlist
640 // if we are strict, we do not want to convert a string to a stringlist
641 // (strings in python are detected to be sequences)
641 // (strings in python are detected to be sequences)
642 if (strict &&
642 if (strict &&
643 (val->ob_type == &PyString_Type ||
643 (val->ob_type == &PyString_Type ||
644 PyUnicode_Check(val))) {
644 PyUnicode_Check(val))) {
645 ok = false;
645 ok = false;
646 return v;
646 return v;
647 }
647 }
648 if (PySequence_Check(val)) {
648 if (PySequence_Check(val)) {
649 int count = PySequence_Size(val);
649 int count = PySequence_Size(val);
650 for (int i = 0;i<count;i++) {
650 for (int i = 0;i<count;i++) {
651 PyObject* value = PySequence_GetItem(val,i);
651 PyObject* value = PySequence_GetItem(val,i);
652 v.append(PyObjGetString(value,false,ok));
652 v.append(PyObjGetString(value,false,ok));
653 }
653 }
654 ok = true;
654 ok = true;
655 }
655 }
656 return v;
656 return v;
657 }
657 }
658
658
659 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
659 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
660 {
660 {
661 QString r;
661 QString r;
662 PyObject* str = PyObject_Repr(val);
662 PyObject* str = PyObject_Repr(val);
663 if (str) {
663 if (str) {
664 r = QString(PyString_AS_STRING(str));
664 r = QString(PyString_AS_STRING(str));
665 Py_DECREF(str);
665 Py_DECREF(str);
666 }
666 }
667 return r;
667 return r;
668 }
668 }
669
669
670 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
670 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
671 QString r;
671 QString r;
672 ok = true;
672 ok = true;
673 if (val->ob_type == &PyString_Type) {
673 if (val->ob_type == &PyString_Type) {
674 r = QString(PyString_AS_STRING(val));
674 r = QString(PyString_AS_STRING(val));
675 } else if (PyUnicode_Check(val)) {
675 } else if (PyUnicode_Check(val)) {
676 #ifdef WIN32
676 #ifdef WIN32
677 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
677 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
678 #else
678 #else
679 PyObject *ptmp = PyUnicode_AsUTF8String(val);
679 PyObject *ptmp = PyUnicode_AsUTF8String(val);
680 if(ptmp) {
680 if(ptmp) {
681 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
681 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
682 Py_DECREF(ptmp);
682 Py_DECREF(ptmp);
683 }
683 }
684 #endif
684 #endif
685 } else if (!strict) {
685 } else if (!strict) {
686 // EXTRA: could also use _Unicode, but why should we?
686 // EXTRA: could also use _Unicode, but why should we?
687 PyObject* str = PyObject_Str(val);
687 PyObject* str = PyObject_Str(val);
688 if (str) {
688 if (str) {
689 r = QString(PyString_AS_STRING(str));
689 r = QString(PyString_AS_STRING(str));
690 Py_DECREF(str);
690 Py_DECREF(str);
691 } else {
691 } else {
692 ok = false;
692 ok = false;
693 }
693 }
694 } else {
694 } else {
695 ok = false;
695 ok = false;
696 }
696 }
697 return r;
697 return r;
698 }
698 }
699
699
700 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
700 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
701 // TODO: support buffer objects in general
701 // TODO: support buffer objects in general
702 QByteArray r;
702 QByteArray r;
703 ok = true;
703 ok = true;
704 if (val->ob_type == &PyString_Type) {
704 if (val->ob_type == &PyString_Type) {
705 long size = PyString_GET_SIZE(val);
705 long size = PyString_GET_SIZE(val);
706 r = QByteArray(PyString_AS_STRING(val), size);
706 r = QByteArray(PyString_AS_STRING(val), size);
707 } else {
707 } else {
708 ok = false;
708 ok = false;
709 }
709 }
710 return r;
710 return r;
711 }
711 }
712
712
713 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
713 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
714 bool d = false;
714 bool d = false;
715 ok = false;
715 ok = false;
716 if (val == Py_False) {
716 if (val == Py_False) {
717 d = false;
717 d = false;
718 ok = true;
718 ok = true;
719 } else if (val == Py_True) {
719 } else if (val == Py_True) {
720 d = true;
720 d = true;
721 ok = true;
721 ok = true;
722 } else if (!strict) {
722 } else if (!strict) {
723 d = PyObjGetInt(val, false, ok)!=0;
723 d = PyObjGetInt(val, false, ok)!=0;
724 ok = true;
724 ok = true;
725 }
725 }
726 return d;
726 return d;
727 }
727 }
728
728
729 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
729 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
730 int d = 0;
730 int d = 0;
731 ok = true;
731 ok = true;
732 if (val->ob_type == &PyInt_Type) {
732 if (val->ob_type == &PyInt_Type) {
733 d = PyInt_AS_LONG(val);
733 d = PyInt_AS_LONG(val);
734 } else if (!strict) {
734 } else if (!strict) {
735 if (PyObject_TypeCheck(val, &PyInt_Type)) {
735 if (PyObject_TypeCheck(val, &PyInt_Type)) {
736 // support for derived int classes, e.g. for our enums
736 // support for derived int classes, e.g. for our enums
737 d = PyInt_AS_LONG(val);
737 d = PyInt_AS_LONG(val);
738 } else if (val->ob_type == &PyFloat_Type) {
738 } else if (val->ob_type == &PyFloat_Type) {
739 d = floor(PyFloat_AS_DOUBLE(val));
739 d = floor(PyFloat_AS_DOUBLE(val));
740 } else if (val->ob_type == &PyLong_Type) {
740 } else if (val->ob_type == &PyLong_Type) {
741 // handle error on overflow!
741 // handle error on overflow!
742 d = PyLong_AsLong(val);
742 d = PyLong_AsLong(val);
743 } else if (val == Py_False) {
743 } else if (val == Py_False) {
744 d = 0;
744 d = 0;
745 } else if (val == Py_True) {
745 } else if (val == Py_True) {
746 d = 1;
746 d = 1;
747 } else {
747 } else {
748 ok = false;
748 ok = false;
749 }
749 }
750 } else {
750 } else {
751 ok = false;
751 ok = false;
752 }
752 }
753 return d;
753 return d;
754 }
754 }
755
755
756 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
756 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
757 qint64 d = 0;
757 qint64 d = 0;
758 ok = true;
758 ok = true;
759 if (val->ob_type == &PyInt_Type) {
759 if (val->ob_type == &PyInt_Type) {
760 d = PyInt_AS_LONG(val);
760 d = PyInt_AS_LONG(val);
761 } else if (val->ob_type == &PyLong_Type) {
761 } else if (val->ob_type == &PyLong_Type) {
762 d = PyLong_AsLongLong(val);
762 d = PyLong_AsLongLong(val);
763 } else if (!strict) {
763 } else if (!strict) {
764 if (PyObject_TypeCheck(val, &PyInt_Type)) {
764 if (PyObject_TypeCheck(val, &PyInt_Type)) {
765 // support for derived int classes, e.g. for our enums
765 // support for derived int classes, e.g. for our enums
766 d = PyInt_AS_LONG(val);
766 d = PyInt_AS_LONG(val);
767 } else if (val->ob_type == &PyFloat_Type) {
767 } else if (val->ob_type == &PyFloat_Type) {
768 d = floor(PyFloat_AS_DOUBLE(val));
768 d = floor(PyFloat_AS_DOUBLE(val));
769 } else if (val == Py_False) {
769 } else if (val == Py_False) {
770 d = 0;
770 d = 0;
771 } else if (val == Py_True) {
771 } else if (val == Py_True) {
772 d = 1;
772 d = 1;
773 } else {
773 } else {
774 ok = false;
774 ok = false;
775 }
775 }
776 } else {
776 } else {
777 ok = false;
777 ok = false;
778 }
778 }
779 return d;
779 return d;
780 }
780 }
781
781
782 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
782 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
783 quint64 d = 0;
783 quint64 d = 0;
784 ok = true;
784 ok = true;
785 if (PyObject_TypeCheck(val, &PyInt_Type)) {
785 if (PyObject_TypeCheck(val, &PyInt_Type)) {
786 d = PyInt_AS_LONG(val);
786 d = PyInt_AS_LONG(val);
787 } else if (val->ob_type == &PyLong_Type) {
787 } else if (val->ob_type == &PyLong_Type) {
788 d = PyLong_AsLongLong(val);
788 d = PyLong_AsLongLong(val);
789 } else if (!strict) {
789 } else if (!strict) {
790 if (PyObject_TypeCheck(val, &PyInt_Type)) {
790 if (PyObject_TypeCheck(val, &PyInt_Type)) {
791 // support for derived int classes, e.g. for our enums
791 // support for derived int classes, e.g. for our enums
792 d = PyInt_AS_LONG(val);
792 d = PyInt_AS_LONG(val);
793 } else if (val->ob_type == &PyFloat_Type) {
793 } else if (val->ob_type == &PyFloat_Type) {
794 d = floor(PyFloat_AS_DOUBLE(val));
794 d = floor(PyFloat_AS_DOUBLE(val));
795 } else if (val == Py_False) {
795 } else if (val == Py_False) {
796 d = 0;
796 d = 0;
797 } else if (val == Py_True) {
797 } else if (val == Py_True) {
798 d = 1;
798 d = 1;
799 } else {
799 } else {
800 ok = false;
800 ok = false;
801 }
801 }
802 } else {
802 } else {
803 ok = false;
803 ok = false;
804 }
804 }
805 return d;
805 return d;
806 }
806 }
807
807
808 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
808 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
809 double d = 0;
809 double d = 0;
810 ok = true;
810 ok = true;
811 if (val->ob_type == &PyFloat_Type) {
811 if (val->ob_type == &PyFloat_Type) {
812 d = PyFloat_AS_DOUBLE(val);
812 d = PyFloat_AS_DOUBLE(val);
813 } else if (!strict) {
813 } else if (!strict) {
814 if (PyObject_TypeCheck(val, &PyInt_Type)) {
814 if (PyObject_TypeCheck(val, &PyInt_Type)) {
815 d = PyInt_AS_LONG(val);
815 d = PyInt_AS_LONG(val);
816 } else if (val->ob_type == &PyLong_Type) {
816 } else if (val->ob_type == &PyLong_Type) {
817 d = PyLong_AsLong(val);
817 d = PyLong_AsLong(val);
818 } else if (val == Py_False) {
818 } else if (val == Py_False) {
819 d = 0;
819 d = 0;
820 } else if (val == Py_True) {
820 } else if (val == Py_True) {
821 d = 1;
821 d = 1;
822 } else {
822 } else {
823 ok = false;
823 ok = false;
824 }
824 }
825 } else {
825 } else {
826 ok = false;
826 ok = false;
827 }
827 }
828 return d;
828 return d;
829 }
829 }
830
830
831 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
831 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
832 {
832 {
833 QVariant v;
833 QVariant v;
834 bool ok = true;
834 bool ok = true;
835
835
836 if (type==-1) {
836 if (type==-1) {
837 // no special type requested
837 // no special type requested
838 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
838 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
839 type = QVariant::String;
839 type = QVariant::String;
840 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
840 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
841 type = QVariant::Int;
841 type = QVariant::Int;
842 } else if (val->ob_type==&PyLong_Type) {
842 } else if (val->ob_type==&PyLong_Type) {
843 type = QVariant::LongLong;
843 type = QVariant::LongLong;
844 } else if (val->ob_type==&PyFloat_Type) {
844 } else if (val->ob_type==&PyFloat_Type) {
845 type = QVariant::Double;
845 type = QVariant::Double;
846 } else if (val == Py_False || val == Py_True) {
846 } else if (val == Py_False || val == Py_True) {
847 type = QVariant::Bool;
847 type = QVariant::Bool;
848 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
848 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
849 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
849 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
850 // c++ wrapper, check if the class names of the c++ objects match
850 // c++ wrapper, check if the class names of the c++ objects match
851 if (wrap->classInfo()->isCPPWrapper()) {
851 if (wrap->classInfo()->isCPPWrapper()) {
852 if (wrap->classInfo()->metaTypeId()>0) {
852 if (wrap->classInfo()->metaTypeId()>0) {
853 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
853 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
854 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
854 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
855 } else {
855 } else {
856 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
856 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
857 // the pointer here...
857 // the pointer here...
858 // is this worth anything? we loose the knowledge of the cpp object type
858 // is this worth anything? we loose the knowledge of the cpp object type
859 v = qVariantFromValue(wrap->_wrappedPtr);
859 v = qVariantFromValue(wrap->_wrappedPtr);
860 }
860 }
861 } else {
861 } else {
862 // this gives us a QObject pointer
862 // this gives us a QObject pointer
863 QObject* myObject = wrap->_obj;
863 QObject* myObject = wrap->_obj;
864 v = qVariantFromValue(myObject);
864 v = qVariantFromValue(myObject);
865 }
865 }
866 return v;
866 return v;
867 } else if (val->ob_type==&PyDict_Type) {
867 } else if (val->ob_type==&PyDict_Type) {
868 type = QVariant::Map;
868 type = QVariant::Map;
869 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
869 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
870 type = QVariant::List;
870 type = QVariant::List;
871 } else if (val == Py_None) {
871 } else if (val == Py_None) {
872 // none is invalid
872 // none is invalid
873 type = QVariant::Invalid;
873 type = QVariant::Invalid;
874 } else {
874 } else {
875 // this used to be:
875 // this used to be:
876 // type = QVariant::String;
876 // type = QVariant::String;
877 // but now we want to transport the Python Objects directly:
877 // but now we want to transport the Python Objects directly:
878 PythonQtObjectPtr o(val);
878 PythonQtObjectPtr o(val);
879 v = qVariantFromValue(o);
879 v = qVariantFromValue(o);
880 return v;
880 return v;
881 }
881 }
882 }
882 }
883 // special type request:
883 // special type request:
884 switch (type) {
884 switch (type) {
885 case QVariant::Invalid:
885 case QVariant::Invalid:
886 return v;
886 return v;
887 break;
887 break;
888 case QVariant::Int:
888 case QVariant::Int:
889 {
889 {
890 int d = PyObjGetInt(val, false, ok);
890 int d = PyObjGetInt(val, false, ok);
891 if (ok) return QVariant(d);
891 if (ok) return QVariant(d);
892 }
892 }
893 break;
893 break;
894 case QVariant::UInt:
894 case QVariant::UInt:
895 {
895 {
896 int d = PyObjGetInt(val, false,ok);
896 int d = PyObjGetInt(val, false,ok);
897 if (ok) v = QVariant((unsigned int)d);
897 if (ok) v = QVariant((unsigned int)d);
898 }
898 }
899 break;
899 break;
900 case QVariant::Bool:
900 case QVariant::Bool:
901 {
901 {
902 int d = PyObjGetBool(val,false,ok);
902 int d = PyObjGetBool(val,false,ok);
903 if (ok) v = QVariant((bool)(d!=0));
903 if (ok) v = QVariant((bool)(d!=0));
904 }
904 }
905 break;
905 break;
906 case QVariant::Double:
906 case QVariant::Double:
907 {
907 {
908 double d = PyObjGetDouble(val,false,ok);
908 double d = PyObjGetDouble(val,false,ok);
909 if (ok) v = QVariant(d);
909 if (ok) v = QVariant(d);
910 break;
910 break;
911 }
911 }
912 case QMetaType::Float:
912 case QMetaType::Float:
913 {
913 {
914 float d = (float) PyObjGetDouble(val,false,ok);
914 float d = (float) PyObjGetDouble(val,false,ok);
915 if (ok) v = qVariantFromValue(d);
915 if (ok) v = qVariantFromValue(d);
916 break;
916 break;
917 }
917 }
918 case QMetaType::Long:
918 case QMetaType::Long:
919 {
919 {
920 long d = (long) PyObjGetLongLong(val,false,ok);
920 long d = (long) PyObjGetLongLong(val,false,ok);
921 if (ok) v = qVariantFromValue(d);
921 if (ok) v = qVariantFromValue(d);
922 break;
922 break;
923 }
923 }
924 case QMetaType::ULong:
924 case QMetaType::ULong:
925 {
925 {
926 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
926 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
927 if (ok) v = qVariantFromValue(d);
927 if (ok) v = qVariantFromValue(d);
928 break;
928 break;
929 }
929 }
930 case QMetaType::LongLong:
930 case QMetaType::LongLong:
931 {
931 {
932 qint64 d = PyObjGetLongLong(val, false, ok);
932 qint64 d = PyObjGetLongLong(val, false, ok);
933 if (ok) v = qVariantFromValue(d);
933 if (ok) v = qVariantFromValue(d);
934 }
934 }
935 break;
935 break;
936 case QMetaType::ULongLong:
936 case QMetaType::ULongLong:
937 {
937 {
938 quint64 d = PyObjGetULongLong(val, false, ok);
938 quint64 d = PyObjGetULongLong(val, false, ok);
939 if (ok) v = qVariantFromValue(d);
939 if (ok) v = qVariantFromValue(d);
940 }
940 }
941 break;
941 break;
942 case QMetaType::Short:
942 case QMetaType::Short:
943 {
943 {
944 short d = (short) PyObjGetInt(val,false,ok);
944 short d = (short) PyObjGetInt(val,false,ok);
945 if (ok) v = qVariantFromValue(d);
945 if (ok) v = qVariantFromValue(d);
946 break;
946 break;
947 }
947 }
948 case QMetaType::UShort:
948 case QMetaType::UShort:
949 {
949 {
950 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
950 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
951 if (ok) v = qVariantFromValue(d);
951 if (ok) v = qVariantFromValue(d);
952 break;
952 break;
953 }
953 }
954 case QMetaType::Char:
954 case QMetaType::Char:
955 {
955 {
956 char d = (char) PyObjGetInt(val,false,ok);
956 char d = (char) PyObjGetInt(val,false,ok);
957 if (ok) v = qVariantFromValue(d);
957 if (ok) v = qVariantFromValue(d);
958 break;
958 break;
959 }
959 }
960 case QMetaType::UChar:
960 case QMetaType::UChar:
961 {
961 {
962 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
962 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
963 if (ok) v = qVariantFromValue(d);
963 if (ok) v = qVariantFromValue(d);
964 break;
964 break;
965 }
965 }
966
966
967 case QVariant::ByteArray:
967 case QVariant::ByteArray:
968 case QVariant::String:
968 case QVariant::String:
969 {
969 {
970 bool ok;
970 bool ok;
971 v = QVariant(PyObjGetString(val, false, ok));
971 v = QVariant(PyObjGetString(val, false, ok));
972 }
972 }
973 break;
973 break;
974
974
975 // these are important for MeVisLab
975 // these are important for MeVisLab
976 case QVariant::Map:
976 case QVariant::Map:
977 {
977 {
978 if (PyMapping_Check(val)) {
978 if (PyMapping_Check(val)) {
979 QMap<QString,QVariant> map;
979 QMap<QString,QVariant> map;
980 PyObject* items = PyMapping_Items(val);
980 PyObject* items = PyMapping_Items(val);
981 if (items) {
981 if (items) {
982 int count = PyList_Size(items);
982 int count = PyList_Size(items);
983 PyObject* value;
983 PyObject* value;
984 PyObject* key;
984 PyObject* key;
985 PyObject* tuple;
985 PyObject* tuple;
986 for (int i = 0;i<count;i++) {
986 for (int i = 0;i<count;i++) {
987 tuple = PyList_GetItem(items,i);
987 tuple = PyList_GetItem(items,i);
988 key = PyTuple_GetItem(tuple, 0);
988 key = PyTuple_GetItem(tuple, 0);
989 value = PyTuple_GetItem(tuple, 1);
989 value = PyTuple_GetItem(tuple, 1);
990 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
990 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
991 }
991 }
992 Py_DECREF(items);
992 Py_DECREF(items);
993 v = map;
993 v = map;
994 }
994 }
995 }
995 }
996 }
996 }
997 break;
997 break;
998 case QVariant::List:
998 case QVariant::List:
999 if (PySequence_Check(val)) {
999 if (PySequence_Check(val)) {
1000 QVariantList list;
1000 QVariantList list;
1001 int count = PySequence_Size(val);
1001 int count = PySequence_Size(val);
1002 PyObject* value;
1002 PyObject* value;
1003 for (int i = 0;i<count;i++) {
1003 for (int i = 0;i<count;i++) {
1004 value = PySequence_GetItem(val,i);
1004 value = PySequence_GetItem(val,i);
1005 list.append(PyObjToQVariant(value, -1));
1005 list.append(PyObjToQVariant(value, -1));
1006 }
1006 }
1007 v = list;
1007 v = list;
1008 }
1008 }
1009 break;
1009 break;
1010 case QVariant::StringList:
1010 case QVariant::StringList:
1011 {
1011 {
1012 bool ok;
1012 bool ok;
1013 QStringList l = PyObjToStringList(val, false, ok);
1013 QStringList l = PyObjToStringList(val, false, ok);
1014 if (ok) {
1014 if (ok) {
1015 v = l;
1015 v = l;
1016 }
1016 }
1017 }
1017 }
1018 break;
1018 break;
1019
1019
1020 default:
1020 default:
1021 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1021 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1022 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1022 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1023 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1023 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1024 // construct a new variant from the C++ object if it has the same meta type
1024 // construct a new variant from the C++ object if it has the same meta type
1025 v = QVariant(type, wrap->_wrappedPtr);
1025 v = QVariant(type, wrap->_wrappedPtr);
1026 } else {
1026 } else {
1027 v = QVariant();
1027 v = QVariant();
1028 }
1028 }
1029 } else {
1029 } else {
1030 v = QVariant();
1030 v = QVariant();
1031 }
1031 }
1032 }
1032 }
1033 return v;
1033 return v;
1034 }
1034 }
1035
1035
1036 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1036 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1037 {
1037 {
1038 if (str.isNull()) {
1038 if (str.isNull()) {
1039 return PyString_FromString("");
1039 return PyString_FromString("");
1040 } else {
1040 } else {
1041 #ifdef WIN32
1041 #ifdef WIN32
1042 // return PyString_FromString(str.toLatin1().data());
1042 // return PyString_FromString(str.toLatin1().data());
1043 return PyUnicode_FromUnicode(str.utf16(), str.length());
1043 return PyUnicode_FromUnicode(str.utf16(), str.length());
1044 #else
1044 #else
1045 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1045 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1046 #endif
1046 #endif
1047 }
1047 }
1048 }
1048 }
1049
1049
1050 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1050 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1051 {
1051 {
1052 PyObject* result = PyTuple_New(list.count());
1052 PyObject* result = PyTuple_New(list.count());
1053 int i = 0;
1053 int i = 0;
1054 QString str;
1054 QString str;
1055 foreach (str, list) {
1055 foreach (str, list) {
1056 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1056 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1057 i++;
1057 i++;
1058 }
1058 }
1059 // why is the error state bad after this?
1059 // why is the error state bad after this?
1060 PyErr_Clear();
1060 PyErr_Clear();
1061 return result;
1061 return result;
1062 }
1062 }
1063
1063
1064 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1064 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1065 {
1065 {
1066 PyObject* result = PyList_New(list.count());
1066 PyObject* result = PyList_New(list.count());
1067 int i = 0;
1067 int i = 0;
1068 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1068 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1069 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1069 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1070 i++;
1070 i++;
1071 }
1071 }
1072 return result;
1072 return result;
1073 }
1073 }
1074
1074
1075 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1075 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1076 {
1076 {
1077 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1077 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1078 }
1078 }
1079
1079
1080 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1080 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1081 PyObject* result = PyDict_New();
1081 PyObject* result = PyDict_New();
1082 QVariantMap::const_iterator t = m.constBegin();
1082 QVariantMap::const_iterator t = m.constBegin();
1083 PyObject* key;
1083 PyObject* key;
1084 PyObject* val;
1084 PyObject* val;
1085 for (;t!=m.end();t++) {
1085 for (;t!=m.end();t++) {
1086 key = QStringToPyObject(t.key());
1086 key = QStringToPyObject(t.key());
1087 val = QVariantToPyObject(t.value());
1087 val = QVariantToPyObject(t.value());
1088 PyDict_SetItem(result, key, val);
1088 PyDict_SetItem(result, key, val);
1089 Py_DECREF(key);
1089 Py_DECREF(key);
1090 Py_DECREF(val);
1090 Py_DECREF(val);
1091 }
1091 }
1092 return result;
1092 return result;
1093 }
1093 }
1094
1094
1095 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1095 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1096 PyObject* result = PyTuple_New(l.count());
1096 PyObject* result = PyTuple_New(l.count());
1097 int i = 0;
1097 int i = 0;
1098 QVariant v;
1098 QVariant v;
1099 foreach (v, l) {
1099 foreach (v, l) {
1100 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1100 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1101 i++;
1101 i++;
1102 }
1102 }
1103 // why is the error state bad after this?
1103 // why is the error state bad after this?
1104 PyErr_Clear();
1104 PyErr_Clear();
1105 return result;
1105 return result;
1106 }
1106 }
1107
1107
1108 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1108 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1109 {
1109 {
1110 PyObject* result = PyTuple_New(list->count());
1110 PyObject* result = PyTuple_New(list->count());
1111 int i = 0;
1111 int i = 0;
1112 foreach (void* value, *list) {
1112 foreach (void* value, *list) {
1113 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1113 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1114 i++;
1114 i++;
1115 }
1115 }
1116 return result;
1116 return result;
1117 }
1117 }
1118
1118
1119 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1119 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1120 {
1120 {
1121 bool result = false;
1121 bool result = false;
1122 if (PySequence_Check(obj)) {
1122 if (PySequence_Check(obj)) {
1123 result = true;
1123 result = true;
1124 int count = PySequence_Size(obj);
1124 int count = PySequence_Size(obj);
1125 PyObject* value;
1125 PyObject* value;
1126 for (int i = 0;i<count;i++) {
1126 for (int i = 0;i<count;i++) {
1127 value = PySequence_GetItem(obj,i);
1127 value = PySequence_GetItem(obj,i);
1128 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1128 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1129 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1129 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1130 bool ok;
1130 bool ok;
1131 void* object = castWrapperTo(wrap, type, ok);
1131 void* object = castWrapperTo(wrap, type, ok);
1132 if (ok) {
1132 if (ok) {
1133 list->append(object);
1133 list->append(object);
1134 } else {
1134 } else {
1135 result = false;
1135 result = false;
1136 break;
1136 break;
1137 }
1137 }
1138 }
1138 }
1139 }
1139 }
1140 }
1140 }
1141 return result;
1141 return result;
1142 }
1142 }
1143
1143
1144 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1144 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1145 {
1145 {
1146 int idx = typeName.indexOf("<");
1146 int idx = typeName.indexOf("<");
1147 if (idx>0) {
1147 if (idx>0) {
1148 int idx2 = typeName.indexOf(">");
1148 int idx2 = typeName.indexOf(">");
1149 if (idx2>0) {
1149 if (idx2>0) {
1150 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1150 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1151 return QMetaType::type(innerType.constData());
1151 return QMetaType::type(innerType.constData());
1152 }
1152 }
1153 }
1153 }
1154 return QMetaType::Void;
1154 return QMetaType::Void;
1155 }
1155 }
1156
1156
1157
1157
1158 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1158 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1159 QString r;
1159 QString r;
1160 switch (type) {
1160 switch (type) {
1161 case QVariant::Size: {
1161 case QVariant::Size: {
1162 const QSize* s = static_cast<const QSize*>(data);
1162 const QSize* s = static_cast<const QSize*>(data);
1163 r = QString::number(s->width()) + ", " + QString::number(s->height());
1163 r = QString::number(s->width()) + ", " + QString::number(s->height());
1164 }
1164 }
1165 break;
1165 break;
1166 case QVariant::SizeF: {
1166 case QVariant::SizeF: {
1167 const QSizeF* s = static_cast<const QSizeF*>(data);
1167 const QSizeF* s = static_cast<const QSizeF*>(data);
1168 r = QString::number(s->width()) + ", " + QString::number(s->height());
1168 r = QString::number(s->width()) + ", " + QString::number(s->height());
1169 }
1169 }
1170 break;
1170 break;
1171 case QVariant::Point: {
1171 case QVariant::Point: {
1172 const QPoint* s = static_cast<const QPoint*>(data);
1172 const QPoint* s = static_cast<const QPoint*>(data);
1173 r = QString::number(s->x()) + ", " + QString::number(s->y());
1173 r = QString::number(s->x()) + ", " + QString::number(s->y());
1174 }
1174 }
1175 break;
1175 break;
1176 case QVariant::PointF: {
1176 case QVariant::PointF: {
1177 const QPointF* s = static_cast<const QPointF*>(data);
1177 const QPointF* s = static_cast<const QPointF*>(data);
1178 r = QString::number(s->x()) + ", " + QString::number(s->y());
1178 r = QString::number(s->x()) + ", " + QString::number(s->y());
1179 }
1179 }
1180 break;
1180 break;
1181 case QVariant::Rect: {
1181 case QVariant::Rect: {
1182 const QRect* s = static_cast<const QRect*>(data);
1182 const QRect* s = static_cast<const QRect*>(data);
1183 r = QString::number(s->x()) + ", " + QString::number(s->y());
1183 r = QString::number(s->x()) + ", " + QString::number(s->y());
1184 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1184 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1185 }
1185 }
1186 break;
1186 break;
1187 case QVariant::RectF: {
1187 case QVariant::RectF: {
1188 const QRectF* s = static_cast<const QRectF*>(data);
1188 const QRectF* s = static_cast<const QRectF*>(data);
1189 r = QString::number(s->x()) + ", " + QString::number(s->y());
1189 r = QString::number(s->x()) + ", " + QString::number(s->y());
1190 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1190 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1191 }
1191 }
1192 break;
1192 break;
1193 case QVariant::Date: {
1193 case QVariant::Date: {
1194 const QDate* s = static_cast<const QDate*>(data);
1194 const QDate* s = static_cast<const QDate*>(data);
1195 r = s->toString(Qt::ISODate);
1195 r = s->toString(Qt::ISODate);
1196 }
1196 }
1197 break;
1197 break;
1198 case QVariant::DateTime: {
1198 case QVariant::DateTime: {
1199 const QDateTime* s = static_cast<const QDateTime*>(data);
1199 const QDateTime* s = static_cast<const QDateTime*>(data);
1200 r = s->toString(Qt::ISODate);
1200 r = s->toString(Qt::ISODate);
1201 }
1201 }
1202 break;
1202 break;
1203 case QVariant::Time: {
1203 case QVariant::Time: {
1204 const QTime* s = static_cast<const QTime*>(data);
1204 const QTime* s = static_cast<const QTime*>(data);
1205 r = s->toString(Qt::ISODate);
1205 r = s->toString(Qt::ISODate);
1206 }
1206 }
1207 break;
1207 break;
1208 case QVariant::Pixmap:
1208 case QVariant::Pixmap:
1209 {
1209 {
1210 const QPixmap* s = static_cast<const QPixmap*>(data);
1210 const QPixmap* s = static_cast<const QPixmap*>(data);
1211 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1211 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1212 }
1212 }
1213 break;
1213 break;
1214 case QVariant::Image:
1214 case QVariant::Image:
1215 {
1215 {
1216 const QImage* s = static_cast<const QImage*>(data);
1216 const QImage* s = static_cast<const QImage*>(data);
1217 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1217 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1218 }
1218 }
1219 break;
1219 break;
1220 case QVariant::Url:
1220 case QVariant::Url:
1221 {
1221 {
1222 const QUrl* s = static_cast<const QUrl*>(data);
1222 const QUrl* s = static_cast<const QUrl*>(data);
1223 r = s->toString();
1223 r = s->toString();
1224 }
1224 }
1225 break;
1225 break;
1226 //TODO: add more printing for other variant types
1226 //TODO: add more printing for other variant types
1227 default:
1227 default:
1228 // this creates a copy, but that should not be expensive for typical simple variants
1228 // this creates a copy, but that should not be expensive for typical simple variants
1229 // (but we do not want to do this for our won user types!
1229 // (but we do not want to do this for our won user types!
1230 if (type>0 && type < (int)QVariant::UserType) {
1230 if (type>0 && type < (int)QVariant::UserType) {
1231 QVariant v(type, data);
1231 QVariant v(type, data);
1232 r = v.toString();
1232 r = v.toString();
1233 }
1233 }
1234 }
1234 }
1235 return r;
1235 return r;
1236 }
1236 }
@@ -1,210 +1,210
1 #ifndef _PYTHONQTCONVERSION_H
1 #ifndef _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_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 PythonQtConversion.h
38 // \file PythonQtConversion.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 "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtMethodInfo.h"
48 #include "PythonQtMethodInfo.h"
49
49
50 #include <QWidget>
50 #include <QWidget>
51 #include <QList>
51 #include <QList>
52 #include <vector>
52 #include <vector>
53
53
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
56
56
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
61 }
61 }
62
62
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
67 // TODO: add QHash etc. here!
67 // TODO: add QHash etc. here!
68
68
69 //! a static class that offers methods for type conversion
69 //! a static class that offers methods for type conversion
70 class PYTHONQT_EXPORT PythonQtConv {
70 class PYTHONQT_EXPORT PythonQtConv {
71
71
72 public:
72 public:
73
73
74 //! get a ref counted True or False Python object
74 //! get a ref counted True or False Python object
75 static PyObject* GetPyBool(bool val);
75 static PyObject* GetPyBool(bool val);
76
76
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
79
79
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
82
82
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
85
85
86 //! converts QString to Python string (unicode!)
86 //! converts QString to Python string (unicode!)
87 static PyObject* QStringToPyObject(const QString& str);
87 static PyObject* QStringToPyObject(const QString& str);
88
88
89 //! converts QStringList to Python tuple
89 //! converts QStringList to Python tuple
90 static PyObject* QStringListToPyObject(const QStringList& list);
90 static PyObject* QStringListToPyObject(const QStringList& list);
91
91
92 //! converts QStringList to Python list
92 //! converts QStringList to Python list
93 static PyObject* QStringListToPyList(const QStringList& list);
93 static PyObject* QStringListToPyList(const QStringList& list);
94
94
95 //! get string representation of py object
95 //! get string representation of py object
96 static QString PyObjGetRepresentation(PyObject* val);
96 static QString PyObjGetRepresentation(PyObject* val);
97
97
98 //! get string value from py object
98 //! get string value from py object
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
100 //! get string value from py object
100 //! get string value from py object
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
102 //! get bytes from py object
102 //! get bytes from py object
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
104 //! get int from py object
104 //! get int from py object
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
106 //! get int64 from py object
106 //! get int64 from py object
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
108 //! get int64 from py object
108 //! get int64 from py object
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
110 //! get double from py object
110 //! get double from py object
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
112 //! get bool from py object
112 //! get bool from py object
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
114
114
115 //! create a string list from python sequence
115 //! create a string list from python sequence
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
117
117
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
119 //! it will guess from the python type
119 //! it will guess from the python type
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
121
121
122 //! convert QVariant from PyObject
122 //! convert QVariant from PyObject
123 static PyObject* QVariantToPyObject(const QVariant& v);
123 static PyObject* QVariantToPyObject(const QVariant& v);
124
124
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
127
127
128 //! get human readable string from CPP object (when the metatype is known)
128 //! get human readable string from CPP object (when the metatype is known)
129 static QString CPPObjectToString(int type, const void* data);
129 static QString CPPObjectToString(int type, const void* data);
130
130
131 //! register a converter callback from python to cpp for given metatype
131 //! register a converter callback from python to cpp for given metatype
132 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
132 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
133
133
134 //! register a converter callback from cpp to python for given metatype
134 //! register a converter callback from cpp to python for given metatype
135 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
135 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
136
136
137 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
137 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
138 static int getInnerTemplateMetaType(const QByteArray& typeName);
138 static int getInnerTemplateMetaType(const QByteArray& typeName);
139
139
140 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
140 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
141 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
141 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
142
142
143 public:
143 public:
144
144
145 static PythonQtValueStorage<qint64, 128> global_valueStorage;
145 static PythonQtValueStorage<qint64, 128> global_valueStorage;
146 static PythonQtValueStorage<void*, 128> global_ptrStorage;
146 static PythonQtValueStorage<void*, 128> global_ptrStorage;
147 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
147 static PythonQtValueStorageWithCleanup<QVariant, 128> global_variantStorage;
148
148
149 protected:
149 protected:
150 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
150 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
151 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
151 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
152
152
153 //! handle automatic conversion of some special types (QColor, QBrush, ...)
153 //! handle automatic conversion of some special types (QColor, QBrush, ...)
154 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
154 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
155
155
156 //! converts the list of pointers of given type to Python
156 //! converts the list of pointers of given type to Python
157 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
157 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
158 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
158 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
159 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
159 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
160
160
161 //! cast wrapper to given className if possible
161 //! cast wrapper to given className if possible
162 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
162 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
163 };
163 };
164
164
165 template<class ListType, class T>
165 template<class ListType, class T>
166 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
166 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
167 {
167 {
168 ListType* list = (ListType*)inList;
168 ListType* list = (ListType*)inList;
169 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
169 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
170 if (innerType == QVariant::Invalid) {
170 if (innerType == QVariant::Invalid) {
171 std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
171 std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
172 }
172 }
173 PyObject* result = PyTuple_New(list->size());
173 PyObject* result = PyTuple_New(list->size());
174 int i = 0;
174 int i = 0;
175 foreach (const T& value, *list) {
175 foreach (const T& value, *list) {
176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
177 i++;
177 i++;
178 }
178 }
179 return result;
179 return result;
180 }
180 }
181
181
182 template<class ListType, class T>
182 template<class ListType, class T>
183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
184 {
184 {
185 ListType* list = (ListType*)outList;
185 ListType* list = (ListType*)outList;
186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
187 if (innerType == QVariant::Invalid) {
187 if (innerType == QVariant::Invalid) {
188 std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
188 std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
189 }
189 }
190 bool result = false;
190 bool result = false;
191 if (PySequence_Check(obj)) {
191 if (PySequence_Check(obj)) {
192 result = true;
192 result = true;
193 int count = PySequence_Size(obj);
193 int count = PySequence_Size(obj);
194 PyObject* value;
194 PyObject* value;
195 for (int i = 0;i<count;i++) {
195 for (int i = 0;i<count;i++) {
196 value = PySequence_GetItem(obj,i);
196 value = PySequence_GetItem(obj,i);
197 // this is quite some overhead, but it avoids having another large switch...
197 // this is quite some overhead, but it avoids having another large switch...
198 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
198 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
199 if (v.isValid()) {
199 if (v.isValid()) {
200 list->push_back(qVariantValue<T>(v));
200 list->push_back(qVariantValue<T>(v));
201 } else {
201 } else {
202 result = false;
202 result = false;
203 break;
203 break;
204 }
204 }
205 }
205 }
206 }
206 }
207 return result;
207 return result;
208 }
208 }
209
209
210 #endif
210 #endif
@@ -1,61 +1,61
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_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 PythonQtCppWrapperFactory.h
38 // \file PythonQtCppWrapperFactory.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-06
41 // \date 2006-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
47 the create() method.
47 the create() method.
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
49 */
49 */
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
51 {
51 {
52 public:
52 public:
53 PythonQtCppWrapperFactory() {};
53 PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
55
55
56 //! create a wrapper for the given object
56 //! create a wrapper for the given object
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
58
58
59 };
59 };
60
60
61 #endif No newline at end of file
61 #endif
@@ -1,72 +1,75
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
71 //! are ignored
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
70 };
73 };
71
74
72 #endif No newline at end of file
75 #endif
@@ -1,793 +1,822
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 }
118 }
118 }
119 }
119 return info;
120 return info;
120 }
121 }
121
122
122
123
123 /* PythonQtImporter.__init__
124 /* PythonQtImporter.__init__
124 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
125 */
126 */
126 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 {
128 {
128 self->_path = NULL;
129 self->_path = NULL;
129
130
130 const char* cpath;
131 const char* cpath;
131 if (!PyArg_ParseTuple(args, "s",
132 if (!PyArg_ParseTuple(args, "s",
132 &cpath))
133 &cpath))
133 return -1;
134 return -1;
134
135
135 QString path(cpath);
136 QString path(cpath);
136 if (PythonQt::importInterface()->exists(path)) {
137 if (PythonQt::importInterface()->exists(path)) {
137 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 foreach(QString ignorePath, ignorePaths) {
139 foreach(QString ignorePath, ignorePaths) {
139 if (path.startsWith(ignorePath)) {
140 if (path.startsWith(ignorePath)) {
140 PyErr_SetString(PythonQtImportError,
141 PyErr_SetString(PythonQtImportError,
141 "path ignored");
142 "path ignored");
142 return -1;
143 return -1;
143 }
144 }
144 }
145 }
145
146
146 self->_path = new QString(path);
147 self->_path = new QString(path);
147 return 0;
148 return 0;
148 } else {
149 } else {
149 PyErr_SetString(PythonQtImportError,
150 PyErr_SetString(PythonQtImportError,
150 "path does not exist error");
151 "path does not exist error");
151 return -1;
152 return -1;
152 }
153 }
153 }
154 }
154
155
155 void
156 void
156 PythonQtImporter_dealloc(PythonQtImporter *self)
157 PythonQtImporter_dealloc(PythonQtImporter *self)
157 {
158 {
158 // free the stored path
159 // free the stored path
159 if (self->_path) delete self->_path;
160 if (self->_path) delete self->_path;
160 // free ourself
161 // free ourself
161 self->ob_type->tp_free((PyObject *)self);
162 self->ob_type->tp_free((PyObject *)self);
162 }
163 }
163
164
164
165
165 /* 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
166 'fullname'. Return self if we can, None if we can't. */
167 'fullname'. Return self if we can, None if we can't. */
167 PyObject *
168 PyObject *
168 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 {
170 {
170 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PyObject *path = NULL;
172 PyObject *path = NULL;
172 char *fullname;
173 char *fullname;
173
174
174 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 &fullname, &path))
176 &fullname, &path))
176 return NULL;
177 return NULL;
177
178
178 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179
180
180 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 Py_INCREF(self);
183 Py_INCREF(self);
183 return (PyObject *)self;
184 return (PyObject *)self;
184 } else {
185 } else {
185 Py_INCREF(Py_None);
186 Py_INCREF(Py_None);
186 return Py_None;
187 return Py_None;
187 }
188 }
188 }
189 }
189
190
190 /* Load and return the module named by 'fullname'. */
191 /* Load and return the module named by 'fullname'. */
191 PyObject *
192 PyObject *
192 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 {
194 {
194 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 char *fullname;
197 char *fullname;
197
198
198 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 &fullname))
200 &fullname))
200 return NULL;
201 return NULL;
201
202
202 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 return NULL;
205 return NULL;
205 }
206 }
206
207
207 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 QString fullPath;
209 QString fullPath;
209 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 if (code == NULL) {
211 if (code == NULL) {
211 return NULL;
212 return NULL;
212 }
213 }
213
214
214 mod = PyImport_AddModule(fullname);
215 mod = PyImport_AddModule(fullname);
215 if (mod == NULL) {
216 if (mod == NULL) {
216 Py_DECREF(code);
217 Py_DECREF(code);
217 return NULL;
218 return NULL;
218 }
219 }
219 dict = PyModule_GetDict(mod);
220 dict = PyModule_GetDict(mod);
220
221
221 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 Py_DECREF(code);
223 Py_DECREF(code);
223 Py_DECREF(mod);
224 Py_DECREF(mod);
224 return NULL;
225 return NULL;
225 }
226 }
226
227
227 if (info.type == PythonQtImport::MI_PACKAGE) {
228 if (info.type == PythonQtImport::MI_PACKAGE) {
228 PyObject *pkgpath, *fullpath;
229 PyObject *pkgpath, *fullpath;
229 QString subname = info.moduleName;
230 QString subname = info.moduleName;
230 int err;
231 int err;
231
232
232 fullpath = PyString_FromFormat("%s%c%s",
233 fullpath = PyString_FromFormat("%s%c%s",
233 self->_path->toLatin1().constData(),
234 self->_path->toLatin1().constData(),
234 SEP,
235 SEP,
235 subname.toLatin1().constData());
236 subname.toLatin1().constData());
236 if (fullpath == NULL) {
237 if (fullpath == NULL) {
237 Py_DECREF(code);
238 Py_DECREF(code);
238 Py_DECREF(mod);
239 Py_DECREF(mod);
239 return NULL;
240 return NULL;
240 }
241 }
241
242
242 pkgpath = Py_BuildValue("[O]", fullpath);
243 pkgpath = Py_BuildValue("[O]", fullpath);
243 Py_DECREF(fullpath);
244 Py_DECREF(fullpath);
244 if (pkgpath == NULL) {
245 if (pkgpath == NULL) {
245 Py_DECREF(code);
246 Py_DECREF(code);
246 Py_DECREF(mod);
247 Py_DECREF(mod);
247 return NULL;
248 return NULL;
248 }
249 }
249 err = PyDict_SetItemString(dict, "__path__", pkgpath);
250 err = PyDict_SetItemString(dict, "__path__", pkgpath);
250 Py_DECREF(pkgpath);
251 Py_DECREF(pkgpath);
251 if (err != 0) {
252 if (err != 0) {
252 Py_DECREF(code);
253 Py_DECREF(code);
253 Py_DECREF(mod);
254 Py_DECREF(mod);
254 return NULL;
255 return NULL;
255 }
256 }
256 }
257 }
257 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
258 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
258 Py_DECREF(code);
259 Py_DECREF(code);
259 if (Py_VerboseFlag) {
260 if (Py_VerboseFlag) {
260 PySys_WriteStderr("import %s # loaded from %s\n",
261 PySys_WriteStderr("import %s # loaded from %s\n",
261 fullname, fullPath.toLatin1().constData());
262 fullname, fullPath.toLatin1().constData());
262 }
263 }
263 } else {
264 } else {
264 PythonQtObjectPtr imp;
265 PythonQtObjectPtr imp;
265 imp.setNewRef(PyImport_ImportModule("imp"));
266 imp.setNewRef(PyImport_ImportModule("imp"));
266
267
267 // Create a PyList with the current path as its single element,
268 // Create a PyList with the current path as its single element,
268 // which is required for find_module (it won't accept a tuple...)
269 // which is required for find_module (it won't accept a tuple...)
269 PythonQtObjectPtr pathList;
270 PythonQtObjectPtr pathList;
270 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
271 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
271
272
272 QVariantList args;
273 QVariantList args;
273 // Pass the module name without the package prefix
274 // Pass the module name without the package prefix
274 args.append(info.moduleName);
275 args.append(info.moduleName);
275 // And the path where we know that the shared library is
276 // And the path where we know that the shared library is
276 args.append(QVariant::fromValue(pathList));
277 args.append(QVariant::fromValue(pathList));
277 QVariant result = imp.call("find_module", args);
278 QVariant result = imp.call("find_module", args);
278 if (result.isValid()) {
279 if (result.isValid()) {
279 // This will return a tuple with (file, pathname, description)
280 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
280 QVariantList list = result.toList();
281 QVariantList list = result.toList();
281 if (list.count()==3) {
282 if (list.count()==3) {
282 // We prepend the full module name (including package prefix)
283 // We prepend the full module name (including package prefix)
283 list.prepend(fullname);
284 list.prepend(fullname);
284 // And call "load_module" with (fullname, file, pathname, description)
285 #ifdef __linux
286 #ifdef _DEBUG
287 // 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
289 // find_module opened a file to the release library, but that file handle is
290 // ignored on Linux and Windows, maybe on MacOS also.
291 list[2] = info.fullPath;
292 #endif
293 #endif
294 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
285 PythonQtObjectPtr module = imp.call("load_module", list);
295 PythonQtObjectPtr module = imp.call("load_module", list);
286 mod = module.object();
296 mod = module.object();
287 if (mod) {
297 if (mod) {
288 Py_INCREF(mod);
298 Py_INCREF(mod);
289 }
299 }
290
300
291 // Finally, we need to close the file again, which find_module opened for us
301 // Finally, we need to close the file again, which find_module opened for us
292 PythonQtObjectPtr file = list.at(1);
302 PythonQtObjectPtr file = list.at(1);
293 file.call("close");
303 file.call("close");
294 }
304 }
295 }
305 }
296 }
306 }
297 return mod;
307 return mod;
298 }
308 }
299
309
300
310
301 PyObject *
311 PyObject *
302 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
312 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
303 {
313 {
304 // EXTRA, NOT YET IMPLEMENTED
314 // EXTRA, NOT YET IMPLEMENTED
305 return NULL;
315 return NULL;
306 }
316 }
307
317
308 PyObject *
318 PyObject *
309 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
319 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
310 {
320 {
311 PythonQtImporter *self = (PythonQtImporter *)obj;
321 PythonQtImporter *self = (PythonQtImporter *)obj;
312 char *fullname;
322 char *fullname;
313
323
314 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
324 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
315 return NULL;
325 return NULL;
316
326
317 QString notused;
327 QString notused;
318 return PythonQtImport::getModuleCode(self, fullname, notused);
328 return PythonQtImport::getModuleCode(self, fullname, notused);
319 }
329 }
320
330
321 PyObject *
331 PyObject *
322 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
332 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
323 {
333 {
324 // EXTRA, NOT YET IMPLEMENTED
334 // EXTRA, NOT YET IMPLEMENTED
325 return NULL;
335 return NULL;
326 }
336 }
327
337
328 PyDoc_STRVAR(doc_find_module,
338 PyDoc_STRVAR(doc_find_module,
329 "find_module(fullname, path=None) -> self or None.\n\
339 "find_module(fullname, path=None) -> self or None.\n\
330 \n\
340 \n\
331 Search for a module specified by 'fullname'. 'fullname' must be the\n\
341 Search for a module specified by 'fullname'. 'fullname' must be the\n\
332 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
342 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
333 instance itself if the module was found, or None if it wasn't.\n\
343 instance itself if the module was found, or None if it wasn't.\n\
334 The optional 'path' argument is ignored -- it's there for compatibility\n\
344 The optional 'path' argument is ignored -- it's there for compatibility\n\
335 with the importer protocol.");
345 with the importer protocol.");
336
346
337 PyDoc_STRVAR(doc_load_module,
347 PyDoc_STRVAR(doc_load_module,
338 "load_module(fullname) -> module.\n\
348 "load_module(fullname) -> module.\n\
339 \n\
349 \n\
340 Load the module specified by 'fullname'. 'fullname' must be the\n\
350 Load the module specified by 'fullname'. 'fullname' must be the\n\
341 fully qualified (dotted) module name. It returns the imported\n\
351 fully qualified (dotted) module name. It returns the imported\n\
342 module, or raises PythonQtImportError if it wasn't found.");
352 module, or raises PythonQtImportError if it wasn't found.");
343
353
344 PyDoc_STRVAR(doc_get_data,
354 PyDoc_STRVAR(doc_get_data,
345 "get_data(pathname) -> string with file data.\n\
355 "get_data(pathname) -> string with file data.\n\
346 \n\
356 \n\
347 Return the data associated with 'pathname'. Raise IOError if\n\
357 Return the data associated with 'pathname'. Raise IOError if\n\
348 the file wasn't found.");
358 the file wasn't found.");
349
359
350 PyDoc_STRVAR(doc_get_code,
360 PyDoc_STRVAR(doc_get_code,
351 "get_code(fullname) -> code object.\n\
361 "get_code(fullname) -> code object.\n\
352 \n\
362 \n\
353 Return the code object for the specified module. Raise PythonQtImportError\n\
363 Return the code object for the specified module. Raise PythonQtImportError\n\
354 is the module couldn't be found.");
364 is the module couldn't be found.");
355
365
356 PyDoc_STRVAR(doc_get_source,
366 PyDoc_STRVAR(doc_get_source,
357 "get_source(fullname) -> source string.\n\
367 "get_source(fullname) -> source string.\n\
358 \n\
368 \n\
359 Return the source code for the specified module. Raise PythonQtImportError\n\
369 Return the source code for the specified module. Raise PythonQtImportError\n\
360 is the module couldn't be found, return None if the archive does\n\
370 is the module couldn't be found, return None if the archive does\n\
361 contain the module, but has no source for it.");
371 contain the module, but has no source for it.");
362
372
363 PyMethodDef PythonQtImporter_methods[] = {
373 PyMethodDef PythonQtImporter_methods[] = {
364 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
374 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
365 doc_find_module},
375 doc_find_module},
366 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
376 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
367 doc_load_module},
377 doc_load_module},
368 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
378 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
369 doc_get_data},
379 doc_get_data},
370 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
380 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
371 doc_get_code},
381 doc_get_code},
372 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
382 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
373 doc_get_source},
383 doc_get_source},
374 {NULL, NULL, 0 , NULL} /* sentinel */
384 {NULL, NULL, 0 , NULL} /* sentinel */
375 };
385 };
376
386
377
387
378 PyDoc_STRVAR(PythonQtImporter_doc,
388 PyDoc_STRVAR(PythonQtImporter_doc,
379 "PythonQtImporter(path) -> PythonQtImporter object\n\
389 "PythonQtImporter(path) -> PythonQtImporter object\n\
380 \n\
390 \n\
381 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\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\
382 . Every path is accepted.");
392 . Every path is accepted.");
383
393
384 #define DEFERRED_ADDRESS(ADDR) 0
394 #define DEFERRED_ADDRESS(ADDR) 0
385
395
386 PyTypeObject PythonQtImporter_Type = {
396 PyTypeObject PythonQtImporter_Type = {
387 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
397 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
388 0,
398 0,
389 "PythonQtImport.PythonQtImporter",
399 "PythonQtImport.PythonQtImporter",
390 sizeof(PythonQtImporter),
400 sizeof(PythonQtImporter),
391 0, /* tp_itemsize */
401 0, /* tp_itemsize */
392 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
402 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
393 0, /* tp_print */
403 0, /* tp_print */
394 0, /* tp_getattr */
404 0, /* tp_getattr */
395 0, /* tp_setattr */
405 0, /* tp_setattr */
396 0, /* tp_compare */
406 0, /* tp_compare */
397 0, /* tp_repr */
407 0, /* tp_repr */
398 0, /* tp_as_number */
408 0, /* tp_as_number */
399 0, /* tp_as_sequence */
409 0, /* tp_as_sequence */
400 0, /* tp_as_mapping */
410 0, /* tp_as_mapping */
401 0, /* tp_hash */
411 0, /* tp_hash */
402 0, /* tp_call */
412 0, /* tp_call */
403 0, /* tp_str */
413 0, /* tp_str */
404 PyObject_GenericGetAttr, /* tp_getattro */
414 PyObject_GenericGetAttr, /* tp_getattro */
405 0, /* tp_setattro */
415 0, /* tp_setattro */
406 0, /* tp_as_buffer */
416 0, /* tp_as_buffer */
407 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
417 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
408 PythonQtImporter_doc, /* tp_doc */
418 PythonQtImporter_doc, /* tp_doc */
409 0, /* tp_traverse */
419 0, /* tp_traverse */
410 0, /* tp_clear */
420 0, /* tp_clear */
411 0, /* tp_richcompare */
421 0, /* tp_richcompare */
412 0, /* tp_weaklistoffset */
422 0, /* tp_weaklistoffset */
413 0, /* tp_iter */
423 0, /* tp_iter */
414 0, /* tp_iternext */
424 0, /* tp_iternext */
415 PythonQtImporter_methods, /* tp_methods */
425 PythonQtImporter_methods, /* tp_methods */
416 0, /* tp_members */
426 0, /* tp_members */
417 0, /* tp_getset */
427 0, /* tp_getset */
418 0, /* tp_base */
428 0, /* tp_base */
419 0, /* tp_dict */
429 0, /* tp_dict */
420 0, /* tp_descr_get */
430 0, /* tp_descr_get */
421 0, /* tp_descr_set */
431 0, /* tp_descr_set */
422 0, /* tp_dictoffset */
432 0, /* tp_dictoffset */
423 (initproc)PythonQtImporter_init, /* tp_init */
433 (initproc)PythonQtImporter_init, /* tp_init */
424 PyType_GenericAlloc, /* tp_alloc */
434 PyType_GenericAlloc, /* tp_alloc */
425 PyType_GenericNew, /* tp_new */
435 PyType_GenericNew, /* tp_new */
426 PyObject_Del, /* tp_free */
436 PyObject_Del, /* tp_free */
427 };
437 };
428
438
429
439
430 /* Given a buffer, return the long that is represented by the first
440 /* Given a buffer, return the long that is represented by the first
431 4 bytes, encoded as little endian. This partially reimplements
441 4 bytes, encoded as little endian. This partially reimplements
432 marshal.c:r_long() */
442 marshal.c:r_long() */
433 long
443 long
434 PythonQtImport::getLong(unsigned char *buf)
444 PythonQtImport::getLong(unsigned char *buf)
435 {
445 {
436 long x;
446 long x;
437 x = buf[0];
447 x = buf[0];
438 x |= (long)buf[1] << 8;
448 x |= (long)buf[1] << 8;
439 x |= (long)buf[2] << 16;
449 x |= (long)buf[2] << 16;
440 x |= (long)buf[3] << 24;
450 x |= (long)buf[3] << 24;
441 #if SIZEOF_LONG > 4
451 #if SIZEOF_LONG > 4
442 /* Sign extension for 64-bit machines */
452 /* Sign extension for 64-bit machines */
443 x |= -(x & 0x80000000L);
453 x |= -(x & 0x80000000L);
444 #endif
454 #endif
445 return x;
455 return x;
446 }
456 }
447
457
448 FILE *
458 FILE *
449 open_exclusive(const QString& filename)
459 open_exclusive(const QString& filename)
450 {
460 {
451 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
461 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
452 /* Use O_EXCL to avoid a race condition when another process tries to
462 /* Use O_EXCL to avoid a race condition when another process tries to
453 write the same file. When that happens, our open() call fails,
463 write the same file. When that happens, our open() call fails,
454 which is just fine (since it's only a cache).
464 which is just fine (since it's only a cache).
455 XXX If the file exists and is writable but the directory is not
465 XXX If the file exists and is writable but the directory is not
456 writable, the file will never be written. Oh well.
466 writable, the file will never be written. Oh well.
457 */
467 */
458 QFile::remove(filename);
468 QFile::remove(filename);
459
469
460 int fd;
470 int fd;
461 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
471 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
462 #ifdef O_BINARY
472 #ifdef O_BINARY
463 flags |= O_BINARY; /* necessary for Windows */
473 flags |= O_BINARY; /* necessary for Windows */
464 #endif
474 #endif
465 #ifdef WIN32
475 #ifdef WIN32
466 fd = _wopen(filename.ucs2(), flags, 0666);
476 fd = _wopen(filename.ucs2(), flags, 0666);
467 #else
477 #else
468 fd = open(filename.local8Bit(), flags, 0666);
478 fd = open(filename.local8Bit(), flags, 0666);
469 #endif
479 #endif
470 if (fd < 0)
480 if (fd < 0)
471 return NULL;
481 return NULL;
472 return fdopen(fd, "wb");
482 return fdopen(fd, "wb");
473 #else
483 #else
474 /* Best we can do -- on Windows this can't happen anyway */
484 /* Best we can do -- on Windows this can't happen anyway */
475 return fopen(filename.toLocal8Bit().constData(), "wb");
485 return fopen(filename.toLocal8Bit().constData(), "wb");
476 #endif
486 #endif
477 }
487 }
478
488
479
489
480 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
490 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
481 {
491 {
482 FILE *fp;
492 FILE *fp;
483 // we do not want to write Qt resources to disk, do we?
493 // we do not want to write Qt resources to disk, do we?
484 if (filename.startsWith(":")) {
494 if (filename.startsWith(":")) {
485 return;
495 return;
486 }
496 }
487 fp = open_exclusive(filename);
497 fp = open_exclusive(filename);
488 if (fp == NULL) {
498 if (fp == NULL) {
489 if (Py_VerboseFlag)
499 if (Py_VerboseFlag)
490 PySys_WriteStderr(
500 PySys_WriteStderr(
491 "# can't create %s\n", filename.toLatin1().constData());
501 "# can't create %s\n", filename.toLatin1().constData());
492 return;
502 return;
493 }
503 }
494 #if PY_VERSION_HEX < 0x02040000
504 #if PY_VERSION_HEX < 0x02040000
495 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
505 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
496 #else
506 #else
497 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
507 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
498 #endif
508 #endif
499 /* First write a 0 for mtime */
509 /* First write a 0 for mtime */
500 #if PY_VERSION_HEX < 0x02040000
510 #if PY_VERSION_HEX < 0x02040000
501 PyMarshal_WriteLongToFile(0L, fp);
511 PyMarshal_WriteLongToFile(0L, fp);
502 #else
512 #else
503 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
513 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
504 #endif
514 #endif
505 #if PY_VERSION_HEX < 0x02040000
515 #if PY_VERSION_HEX < 0x02040000
506 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
516 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
507 #else
517 #else
508 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
518 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
509 #endif
519 #endif
510 if (ferror(fp)) {
520 if (ferror(fp)) {
511 if (Py_VerboseFlag)
521 if (Py_VerboseFlag)
512 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
522 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
513 /* Don't keep partial file */
523 /* Don't keep partial file */
514 fclose(fp);
524 fclose(fp);
515 QFile::remove(filename);
525 QFile::remove(filename);
516 return;
526 return;
517 }
527 }
518 /* Now write the true mtime */
528 /* Now write the true mtime */
519 fseek(fp, 4L, 0);
529 fseek(fp, 4L, 0);
520 #if PY_VERSION_HEX < 0x02040000
530 #if PY_VERSION_HEX < 0x02040000
521 PyMarshal_WriteLongToFile(mtime, fp);
531 PyMarshal_WriteLongToFile(mtime, fp);
522 #else
532 #else
523 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
533 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
524 #endif
534 #endif
525 fflush(fp);
535 fflush(fp);
526 fclose(fp);
536 fclose(fp);
527 if (Py_VerboseFlag)
537 if (Py_VerboseFlag)
528 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
538 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
529 //#ifdef macintosh
539 //#ifdef macintosh
530 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
540 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
531 //#endif
541 //#endif
532 }
542 }
533
543
534 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
544 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
535 and return the code object. Return None if it the magic word doesn't
545 and return the code object. Return None if it the magic word doesn't
536 match (we do this instead of raising an exception as we fall back
546 match (we do this instead of raising an exception as we fall back
537 to .py if available and we don't want to mask other errors).
547 to .py if available and we don't want to mask other errors).
538 Returns a new reference. */
548 Returns a new reference. */
539 PyObject *
549 PyObject *
540 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
550 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
541 {
551 {
542 PyObject *code;
552 PyObject *code;
543 // ugly cast, but Python API is not const safe
553 // ugly cast, but Python API is not const safe
544 char *buf = (char*) data.constData();
554 char *buf = (char*) data.constData();
545 int size = data.size();
555 int size = data.size();
546
556
547 if (size <= 9) {
557 if (size <= 9) {
548 PySys_WriteStderr("# %s has bad pyc data\n",
558 PySys_WriteStderr("# %s has bad pyc data\n",
549 path.toLatin1().constData());
559 path.toLatin1().constData());
550 Py_INCREF(Py_None);
560 Py_INCREF(Py_None);
551 return Py_None;
561 return Py_None;
552 }
562 }
553
563
554 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
564 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
555 if (Py_VerboseFlag)
565 if (Py_VerboseFlag)
556 PySys_WriteStderr("# %s has bad magic\n",
566 PySys_WriteStderr("# %s has bad magic\n",
557 path.toLatin1().constData());
567 path.toLatin1().constData());
558 Py_INCREF(Py_None);
568 Py_INCREF(Py_None);
559 return Py_None;
569 return Py_None;
560 }
570 }
561
571
562 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
572 if (mtime != 0) {
563 if (Py_VerboseFlag)
573 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
564 PySys_WriteStderr("# %s has bad mtime\n",
574 if (timeDiff<0) { timeDiff = -timeDiff; }
565 path.toLatin1().constData());
575 if (timeDiff > 1) {
566 Py_INCREF(Py_None);
576 if (Py_VerboseFlag)
567 return Py_None;
577 PySys_WriteStderr("# %s has bad mtime\n",
578 path.toLatin1().constData());
579 Py_INCREF(Py_None);
580 return Py_None;
581 }
568 }
582 }
569
583
570 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
584 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
571 if (code == NULL)
585 if (code == NULL)
572 return NULL;
586 return NULL;
573 if (!PyCode_Check(code)) {
587 if (!PyCode_Check(code)) {
574 Py_DECREF(code);
588 Py_DECREF(code);
575 PyErr_Format(PyExc_TypeError,
589 PyErr_Format(PyExc_TypeError,
576 "compiled module %.200s is not a code object",
590 "compiled module %.200s is not a code object",
577 path.toLatin1().constData());
591 path.toLatin1().constData());
578 return NULL;
592 return NULL;
579 }
593 }
580 return code;
594 return code;
581 }
595 }
582
596
583
597
584 /* Given a string buffer containing Python source code, compile it
598 /* Given a string buffer containing Python source code, compile it
585 return and return a code object as a new reference. */
599 return and return a code object as a new reference. */
586 PyObject *
600 PyObject *
587 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
601 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
588 {
602 {
589 PyObject *code;
603 PyObject *code;
590 QByteArray data1 = data;
604 QByteArray data1 = data;
591 // in qt4, data is null terminated
605 // in qt4, data is null terminated
592 // data1.resize(data.size()+1);
606 // data1.resize(data.size()+1);
593 // data1.data()[data.size()-1] = 0;
607 // data1.data()[data.size()-1] = 0;
594 code = Py_CompileString(data.data(), path.toLatin1().constData(),
608 code = Py_CompileString(data.data(), path.toLatin1().constData(),
595 Py_file_input);
609 Py_file_input);
596 return code;
610 return code;
597 }
611 }
598
612
599
613
600 /* Return the code object for the module named by 'fullname' from the
614 /* Return the code object for the module named by 'fullname' from the
601 Zip archive as a new reference. */
615 Zip archive as a new reference. */
602 PyObject *
616 PyObject *
603 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
617 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
604 {
618 {
605 PyObject *code;
619 PyObject *code;
606
620
607 QByteArray qdata;
621 QByteArray qdata;
608 if (!isbytecode) {
622 if (!isbytecode) {
609 // mlabDebugConst("MLABPython", "reading source " << path);
623 // mlabDebugConst("MLABPython", "reading source " << path);
610 bool ok;
624 bool ok;
611 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
625 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
612 if (!ok) {
626 if (!ok) {
613 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
627 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
614 return NULL;
628 return NULL;
615 }
629 }
616 if (qdata == " ") {
630 if (qdata == " ") {
617 qdata.clear();
631 qdata.clear();
618 }
632 }
619 } else {
633 } else {
620 qdata = PythonQt::importInterface()->readFileAsBytes(path);
634 qdata = PythonQt::importInterface()->readFileAsBytes(path);
621 }
635 }
622
636
623 if (isbytecode) {
637 if (isbytecode) {
624 // mlabDebugConst("MLABPython", "reading bytecode " << path);
638 // mlabDebugConst("MLABPython", "reading bytecode " << path);
625 code = unmarshalCode(path, qdata, mtime);
639 code = unmarshalCode(path, qdata, mtime);
626 }
640 }
627 else {
641 else {
628 // mlabDebugConst("MLABPython", "compiling source " << path);
642 // mlabDebugConst("MLABPython", "compiling source " << path);
629 code = compileSource(path, qdata);
643 code = compileSource(path, qdata);
630 if (code) {
644 if (code) {
631 // save a pyc file if possible
645 // save a pyc file if possible
632 QDateTime time;
646 QDateTime time;
633 time = PythonQt::importInterface()->lastModifiedDate(path);
647 time = PythonQt::importInterface()->lastModifiedDate(path);
634 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
648 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
635 }
649 }
636 }
650 }
637 return code;
651 return code;
638 }
652 }
639
653
640 time_t
654 time_t
641 PythonQtImport::getMTimeOfSource(const QString& path)
655 PythonQtImport::getMTimeOfSource(const QString& path)
642 {
656 {
643 time_t mtime = 0;
657 time_t mtime = 0;
644 QString path2 = path;
658 QString path2 = path;
645 path2.truncate(path.length()-1);
659 path2.truncate(path.length()-1);
646
660
647 if (PythonQt::importInterface()->exists(path2)) {
661 if (PythonQt::importInterface()->exists(path2)) {
648 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
662 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
663 if (t.isValid()) {
664 mtime = t.toTime_t();
665 }
649 }
666 }
650
667
651 return mtime;
668 return mtime;
652 }
669 }
653
670
654 /* Get the code object associated with the module specified by
671 /* Get the code object associated with the module specified by
655 'fullname'. */
672 'fullname'. */
656 PyObject *
673 PyObject *
657 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
674 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
658 {
675 {
659 QString subname;
676 QString subname;
660 struct st_mlab_searchorder *zso;
677 struct st_mlab_searchorder *zso;
661
678
662 subname = getSubName(fullname);
679 subname = getSubName(fullname);
663 QString path = *self->_path + "/" + subname;
680 QString path = *self->_path + "/" + subname;
664
681
665 QString test;
682 QString test;
666 for (zso = mlab_searchorder; *zso->suffix; zso++) {
683 for (zso = mlab_searchorder; *zso->suffix; zso++) {
667 PyObject *code = NULL;
684 PyObject *code = NULL;
668 test = path + zso->suffix;
685 test = path + zso->suffix;
669
686
670 if (Py_VerboseFlag > 1)
687 if (Py_VerboseFlag > 1)
671 PySys_WriteStderr("# trying %s\n",
688 PySys_WriteStderr("# trying %s\n",
672 test.toLatin1().constData());
689 test.toLatin1().constData());
673 if (PythonQt::importInterface()->exists(test)) {
690 if (PythonQt::importInterface()->exists(test)) {
674 time_t mtime = 0;
691 time_t mtime = 0;
675 int ispackage = zso->type & IS_PACKAGE;
692 int ispackage = zso->type & IS_PACKAGE;
676 int isbytecode = zso->type & IS_BYTECODE;
693 int isbytecode = zso->type & IS_BYTECODE;
677
694
678 if (isbytecode) {
695 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
696 // 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
698 // typically only *.pyc files are delivered without *.py files and reading file
699 // modification time is slow.
700 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
679 mtime = getMTimeOfSource(test);
701 mtime = getMTimeOfSource(test);
680 }
702 }
681 code = getCodeFromData(test, isbytecode, ispackage, mtime);
703 code = getCodeFromData(test, isbytecode, ispackage, mtime);
682 if (code == Py_None) {
704 if (code == Py_None) {
683 Py_DECREF(code);
705 Py_DECREF(code);
684 continue;
706 continue;
685 }
707 }
686 if (code != NULL) {
708 if (code != NULL) {
687 modpath = test;
709 modpath = test;
688 }
710 }
689 return code;
711 return code;
690 }
712 }
691 }
713 }
692 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
714 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
693
715
694 return NULL;
716 return NULL;
695 }
717 }
696
718
697 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
719 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
698 {
720 {
699 QString r;
721 QString r;
700 int i = str.lastIndexOf('.');
722 int i = str.lastIndexOf('.');
701 if (i!=-1) {
723 if (i!=-1) {
702 r = str.mid(0,i) + "." + ext;
724 r = str.mid(0,i) + "." + ext;
703 } else {
725 } else {
704 r = str + "." + ext;
726 r = str + "." + ext;
705 }
727 }
706 return r;
728 return r;
707 }
729 }
708
730
709 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
731 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
710 {
732 {
711 PyObject* code;
733 PyObject* code;
712 const static QString pycStr("pyc");
734 const static QString pycStr("pyc");
713 QString pyc = replaceExtension(file, pycStr);
735 QString pyc = replaceExtension(file, pycStr);
714 if (PythonQt::importInterface()->exists(pyc)) {
736 if (PythonQt::importInterface()->exists(pyc)) {
715 time_t mtime = 0;
737 time_t mtime = 0;
716 mtime = getMTimeOfSource(pyc);
738 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
739 // 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
741 // typically only *.pyc files are delivered without *.py files and reading file
742 // modification time is slow.
743 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
744 mtime = getMTimeOfSource(pyc);
745 }
717 code = getCodeFromData(pyc, true, false, mtime);
746 code = getCodeFromData(pyc, true, false, mtime);
718 if (code != Py_None && code != NULL) {
747 if (code != Py_None && code != NULL) {
719 return code;
748 return code;
720 }
749 }
721 if (code) {
750 if (code) {
722 Py_DECREF(code);
751 Py_DECREF(code);
723 }
752 }
724 }
753 }
725 code = getCodeFromData(file,false,false,0);
754 code = getCodeFromData(file,false,false,0);
726 return code;
755 return code;
727 }
756 }
728
757
729 /* Module init */
758 /* Module init */
730
759
731 PyDoc_STRVAR(mlabimport_doc,
760 PyDoc_STRVAR(mlabimport_doc,
732 "Imports python files into PythonQt, completely replaces internal python import");
761 "Imports python files into PythonQt, completely replaces internal python import");
733
762
734 void PythonQtImport::init()
763 void PythonQtImport::init()
735 {
764 {
736 static bool first = true;
765 static bool first = true;
737 if (!first) {
766 if (!first) {
738 return;
767 return;
739 }
768 }
740 first = false;
769 first = false;
741
770
742 PyObject *mod;
771 PyObject *mod;
743
772
744 if (PyType_Ready(&PythonQtImporter_Type) < 0)
773 if (PyType_Ready(&PythonQtImporter_Type) < 0)
745 return;
774 return;
746
775
747 /* Correct directory separator */
776 /* Correct directory separator */
748 mlab_searchorder[0].suffix[0] = SEP;
777 mlab_searchorder[0].suffix[0] = SEP;
749 mlab_searchorder[1].suffix[0] = SEP;
778 mlab_searchorder[1].suffix[0] = SEP;
750 mlab_searchorder[2].suffix[0] = SEP;
779 mlab_searchorder[2].suffix[0] = SEP;
751 if (Py_OptimizeFlag) {
780 if (Py_OptimizeFlag) {
752 /* Reverse *.pyc and *.pyo */
781 /* Reverse *.pyc and *.pyo */
753 struct st_mlab_searchorder tmp;
782 struct st_mlab_searchorder tmp;
754 tmp = mlab_searchorder[0];
783 tmp = mlab_searchorder[0];
755 mlab_searchorder[0] = mlab_searchorder[1];
784 mlab_searchorder[0] = mlab_searchorder[1];
756 mlab_searchorder[1] = tmp;
785 mlab_searchorder[1] = tmp;
757 tmp = mlab_searchorder[3];
786 tmp = mlab_searchorder[3];
758 mlab_searchorder[3] = mlab_searchorder[4];
787 mlab_searchorder[3] = mlab_searchorder[4];
759 mlab_searchorder[4] = tmp;
788 mlab_searchorder[4] = tmp;
760 }
789 }
761
790
762 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
791 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
763 NULL, PYTHON_API_VERSION);
792 NULL, PYTHON_API_VERSION);
764
793
765 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
794 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
766 PyExc_ImportError, NULL);
795 PyExc_ImportError, NULL);
767 if (PythonQtImportError == NULL)
796 if (PythonQtImportError == NULL)
768 return;
797 return;
769
798
770 Py_INCREF(PythonQtImportError);
799 Py_INCREF(PythonQtImportError);
771 if (PyModule_AddObject(mod, "PythonQtImportError",
800 if (PyModule_AddObject(mod, "PythonQtImportError",
772 PythonQtImportError) < 0)
801 PythonQtImportError) < 0)
773 return;
802 return;
774
803
775 Py_INCREF(&PythonQtImporter_Type);
804 Py_INCREF(&PythonQtImporter_Type);
776 if (PyModule_AddObject(mod, "PythonQtImporter",
805 if (PyModule_AddObject(mod, "PythonQtImporter",
777 (PyObject *)&PythonQtImporter_Type) < 0)
806 (PyObject *)&PythonQtImporter_Type) < 0)
778 return;
807 return;
779
808
780 // set our importer into the path_hooks to handle all path on sys.path
809 // set our importer into the path_hooks to handle all path on sys.path
781 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
810 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
782 PyObject* path_hooks = PySys_GetObject("path_hooks");
811 PyObject* path_hooks = PySys_GetObject("path_hooks");
783 PyList_Append(path_hooks, classobj);
812 PyList_Append(path_hooks, classobj);
784
813
785 #ifndef WIN32
814 #ifndef WIN32
786 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
815 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
787 PyObject* modules = PyImport_GetModuleDict();
816 PyObject* modules = PyImport_GetModuleDict();
788 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
817 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
789 if (encodingsModule != NULL) {
818 if (encodingsModule != NULL) {
790 PyImport_ReloadModule(encodingsModule);
819 PyImport_ReloadModule(encodingsModule);
791 }
820 }
792 #endif
821 #endif
793 }
822 }
@@ -1,726 +1,766
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 "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
48 #include "PythonQtClassWrapper.h"
49
49
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 {
51 {
52 // take the class info from our type object
52 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
54 }
55
55
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
57
58 // is this a C++ wrapper?
58 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
61
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
64 delete self->_obj;
64 delete self->_obj;
65 self->_obj = NULL;
65 self->_obj = NULL;
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 int type = self->classInfo()->metaTypeId();
67 int type = self->classInfo()->metaTypeId();
68 if (self->_useQMetaTypeDestroy && type>=0) {
68 if (self->_useQMetaTypeDestroy && type>=0) {
69 // use QMetaType to destroy the object
69 // use QMetaType to destroy the object
70 QMetaType::destroy(type, self->_wrappedPtr);
70 QMetaType::destroy(type, self->_wrappedPtr);
71 } else {
71 } else {
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 if (slot) {
73 if (slot) {
74 void* args[2];
74 void* args[2];
75 args[0] = NULL;
75 args[0] = NULL;
76 args[1] = &self->_wrappedPtr;
76 args[1] = &self->_wrappedPtr;
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 self->_wrappedPtr = NULL;
78 self->_wrappedPtr = NULL;
79 } else {
79 } else {
80 if (type>=0) {
80 if (type>=0) {
81 // use QMetaType to destroy the object
81 // use QMetaType to destroy the object
82 QMetaType::destroy(type, self->_wrappedPtr);
82 QMetaType::destroy(type, self->_wrappedPtr);
83 } else {
83 } else {
84 // TODO: warn about not being able to destroy the object?
84 // TODO: warn about not being able to destroy the object?
85 }
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 } else {
89 } else {
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 if (self->_objPointerCopy) {
91 if (self->_objPointerCopy) {
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 }
93 }
94 if (self->_obj) {
94 if (self->_obj) {
95 if (force || self->_ownedByPythonQt) {
95 if (force || self->_ownedByPythonQt) {
96 if (force || !self->_obj->parent()) {
96 if (force || !self->_obj->parent()) {
97 delete self->_obj;
97 delete self->_obj;
98 }
98 }
99 } else {
99 } else {
100 if (self->_obj->parent()==NULL) {
100 if (self->_obj->parent()==NULL) {
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 }
103 }
104 }
104 }
105 }
105 }
106 }
106 }
107 self->_obj = NULL;
107 self->_obj = NULL;
108 }
108 }
109
109
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 {
111 {
112 PythonQtInstanceWrapper_deleteObject(self);
112 PythonQtInstanceWrapper_deleteObject(self);
113 self->_obj.~QPointer<QObject>();
113 self->_obj.~QPointer<QObject>();
114 self->ob_type->tp_free((PyObject*)self);
114 self->ob_type->tp_free((PyObject*)self);
115 }
115 }
116
116
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 {
118 {
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
121 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
122 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
123 emptyTuple = PyTuple_New(0);
124 }
124 }
125
125
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127
127
128 if (self != NULL) {
128 if (self != NULL) {
129 new (&self->_obj) QPointer<QObject>();
129 new (&self->_obj) QPointer<QObject>();
130 self->_wrappedPtr = NULL;
130 self->_wrappedPtr = NULL;
131 self->_ownedByPythonQt = false;
131 self->_ownedByPythonQt = false;
132 self->_useQMetaTypeDestroy = false;
132 self->_useQMetaTypeDestroy = false;
133 self->_isShellInstance = false;
133 self->_isShellInstance = false;
134 }
134 }
135 return (PyObject *)self;
135 return (PyObject *)self;
136 }
136 }
137
137
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 {
139 {
140 if (args == PythonQtPrivate::dummyTuple()) {
140 if (args == PythonQtPrivate::dummyTuple()) {
141 // we are called from the internal PythonQt API, so our data will be filled later on...
141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 return 0;
142 return 0;
143 }
143 }
144
144
145 // we are called from python, try to construct our object
145 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
146 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
147 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
149 if (PyErr_Occurred()) {
150 return -1;
150 return -1;
151 }
151 }
152 if (directCPPPointer) {
152 if (directCPPPointer) {
153 // change ownershipflag to be owned by PythonQt
153 // change ownershipflag to be owned by PythonQt
154 self->_ownedByPythonQt = true;
154 self->_ownedByPythonQt = true;
155 self->_useQMetaTypeDestroy = false;
155 self->_useQMetaTypeDestroy = false;
156 if (self->classInfo()->isCPPWrapper()) {
156 if (self->classInfo()->isCPPWrapper()) {
157 self->_wrappedPtr = directCPPPointer;
157 self->_wrappedPtr = directCPPPointer;
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 } else {
159 } else {
160 self->setQObject((QObject*)directCPPPointer);
160 self->setQObject((QObject*)directCPPPointer);
161 }
161 }
162 // register with PythonQt
162 // register with PythonQt
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164
164
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 if (cb) {
166 if (cb) {
167 // if we are a derived python class, we set the wrapper
167 // 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...
168 // 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,
169 // 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
170 // which is the case for all non-python derived types
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 // set the wrapper and remember that we have a shell instance!
172 // set the wrapper and remember that we have a shell instance!
173 (*cb)(directCPPPointer, self);
173 (*cb)(directCPPPointer, self);
174 self->_isShellInstance = true;
174 self->_isShellInstance = true;
175 }
175 }
176 }
176 }
177 }
177 }
178 } else {
178 } else {
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 return -1;
181 return -1;
182 }
182 }
183 return 0;
183 return 0;
184 }
184 }
185
185
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 {
187 {
188 bool validPtrs = false;
188 bool validPtrs = false;
189 bool areSamePtrs = false;
189 bool areSamePtrs = false;
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 validPtrs = true;
192 validPtrs = true;
193 PythonQtInstanceWrapper* w1 = wrapper;
193 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 // check pointers directly
195 // check pointers directly
196 if (w1->_wrappedPtr != NULL) {
196 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 areSamePtrs = true;
198 areSamePtrs = true;
199 }
199 }
200 } else if (w1->_obj == w2->_obj) {
200 } else if (w1->_obj == w2->_obj) {
201 areSamePtrs = true;
201 areSamePtrs = true;
202 }
202 }
203 } else if (other == Py_None) {
203 } else if (other == Py_None) {
204 validPtrs = true;
204 validPtrs = true;
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 areSamePtrs = false;
206 areSamePtrs = false;
207 } else {
207 } else {
208 areSamePtrs = true;
208 areSamePtrs = true;
209 }
209 }
210 }
210 }
211 }
211 }
212
212
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 // shortcut if richcompare is not supported:
214 // shortcut if richcompare is not supported:
215 if (validPtrs && code == Py_EQ) {
215 if (validPtrs && code == Py_EQ) {
216 return PythonQtConv::GetPyBool(areSamePtrs);
216 return PythonQtConv::GetPyBool(areSamePtrs);
217 } else if (validPtrs && code == Py_NE) {
217 } else if (validPtrs && code == Py_NE) {
218 return PythonQtConv::GetPyBool(!areSamePtrs);
218 return PythonQtConv::GetPyBool(!areSamePtrs);
219 }
219 }
220 Py_INCREF(Py_NotImplemented);
220 Py_INCREF(Py_NotImplemented);
221 return Py_NotImplemented;
221 return Py_NotImplemented;
222 }
222 }
223
223
224 QByteArray memberName;
224 QByteArray memberName;
225 switch (code) {
225 switch (code) {
226 case Py_LT:
226 case Py_LT:
227 {
227 {
228 static QByteArray name = "__lt__";
228 static QByteArray name = "__lt__";
229 memberName = name;
229 memberName = name;
230 }
230 }
231 break;
231 break;
232
232
233 case Py_LE:
233 case Py_LE:
234 {
234 {
235 static QByteArray name = "__le__";
235 static QByteArray name = "__le__";
236 memberName = name;
236 memberName = name;
237 }
237 }
238 break;
238 break;
239
239
240 case Py_EQ:
240 case Py_EQ:
241 {
241 {
242 static QByteArray name = "__eq__";
242 static QByteArray name = "__eq__";
243 memberName = name;
243 memberName = name;
244 }
244 }
245 break;
245 break;
246
246
247 case Py_NE:
247 case Py_NE:
248 {
248 {
249 static QByteArray name = "__ne__";
249 static QByteArray name = "__ne__";
250 memberName = name;
250 memberName = name;
251 }
251 }
252 break;
252 break;
253
253
254 case Py_GT:
254 case Py_GT:
255 {
255 {
256 static QByteArray name = "__gt__";
256 static QByteArray name = "__gt__";
257 memberName = name;
257 memberName = name;
258 }
258 }
259 break;
259 break;
260
260
261 case Py_GE:
261 case Py_GE:
262 {
262 {
263 static QByteArray name = "__ge__";
263 static QByteArray name = "__ge__";
264 memberName = name;
264 memberName = name;
265 }
265 }
266 break;
266 break;
267 }
267 }
268
268
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 // TODO get rid of tuple
271 // TODO get rid of tuple
272 PyObject* args = PyTuple_New(1);
272 PyObject* args = PyTuple_New(1);
273 Py_INCREF(other);
273 Py_INCREF(other);
274 PyTuple_SET_ITEM(args, 0, other);
274 PyTuple_SET_ITEM(args, 0, other);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 Py_DECREF(args);
276 Py_DECREF(args);
277 return result;
277 return result;
278 } else {
278 } else {
279 // not implemented, let python try something else!
279 // not implemented, let python try something else!
280 Py_INCREF(Py_NotImplemented);
280 Py_INCREF(Py_NotImplemented);
281 return Py_NotImplemented;
281 return Py_NotImplemented;
282 }
282 }
283 }
283 }
284
284
285
285
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 {
287 {
288 return PyString_FromString(obj->ob_type->tp_name);
288 return PyString_FromString(obj->ob_type->tp_name);
289 }
289 }
290
290
291 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
292 {
293 char *name = NULL;
294 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
295 return NULL;
296 }
297 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
298 }
299
291 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
300 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
292 {
301 {
293 return PythonQt::self()->helpCalled(obj->classInfo());
302 return PythonQt::self()->helpCalled(obj->classInfo());
294 }
303 }
295
304
296 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
305 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
297 {
306 {
298 PythonQtInstanceWrapper_deleteObject(self, true);
307 PythonQtInstanceWrapper_deleteObject(self, true);
299 Py_INCREF(Py_None);
308 Py_INCREF(Py_None);
300 return Py_None;
309 return Py_None;
301 }
310 }
302
311
303
312
304 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
313 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
305 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
314 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
306 "Return the classname of the object"
315 "Return the classname of the object"
307 },
316 },
317 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
318 "Returns if the class inherits or is of given type name"
319 },
308 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
320 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
309 "Shows the help of available methods for this class"
321 "Shows the help of available methods for this class"
310 },
322 },
311 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
323 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
312 "Deletes the C++ object (at your own risk, my friend!)"
324 "Deletes the C++ object (at your own risk, my friend!)"
313 },
325 },
314 {NULL, NULL, 0, NULL} /* Sentinel */
326 {NULL, NULL, 0, NULL} /* Sentinel */
315 };
327 };
316
328
317
329
318 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
330 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
319 {
331 {
320 const char *attributeName;
332 const char *attributeName;
321 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
333 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
322
334
323 if ((attributeName = PyString_AsString(name)) == NULL) {
335 if ((attributeName = PyString_AsString(name)) == NULL) {
324 return NULL;
336 return NULL;
325 }
337 }
326
338
327 if (qstrcmp(attributeName, "__dict__")==0) {
339 if (qstrcmp(attributeName, "__dict__")==0) {
328 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
340 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
329 dict = PyDict_Copy(dict);
341 dict = PyDict_Copy(dict);
330
342
331 if (wrapper->_obj) {
343 if (wrapper->_obj) {
332 // only the properties are missing, the rest is already available from
344 // only the properties are missing, the rest is already available from
333 // PythonQtClassWrapper...
345 // PythonQtClassWrapper...
334 QStringList l = wrapper->classInfo()->propertyList();
346 QStringList l = wrapper->classInfo()->propertyList();
335 foreach (QString name, l) {
347 foreach (QString name, l) {
336 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
348 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
337 if (o) {
349 if (o) {
338 PyDict_SetItemString(dict, name.toLatin1().data(), o);
350 PyDict_SetItemString(dict, name.toLatin1().data(), o);
339 Py_DECREF(o);
351 Py_DECREF(o);
340 } else {
352 } else {
341 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
353 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
342 }
354 }
343 }
355 }
344
356
345 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
357 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
346 foreach (QByteArray name, dynamicProps) {
358 foreach (QByteArray name, dynamicProps) {
347 PyObject* o = PyObject_GetAttrString(obj, name.data());
359 PyObject* o = PyObject_GetAttrString(obj, name.data());
348 if (o) {
360 if (o) {
349 PyDict_SetItemString(dict, name.data(), o);
361 PyDict_SetItemString(dict, name.data(), o);
350 Py_DECREF(o);
362 Py_DECREF(o);
351 } else {
363 } else {
352 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
364 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
353 }
365 }
354 }
366 }
355 }
367 }
356 // Note: we do not put children into the dict, is would look confusing?!
368 // Note: we do not put children into the dict, is would look confusing?!
357 return dict;
369 return dict;
358 }
370 }
359
371
360 // first look in super, to return derived methods from base object first
372 // first look in super, to return derived methods from base object first
361 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
373 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
362 if (superAttr) {
374 if (superAttr) {
363 return superAttr;
375 return superAttr;
364 }
376 }
365 PyErr_Clear();
377 PyErr_Clear();
366
378
367 // mlabDebugConst("Python","get " << attributeName);
379 // mlabDebugConst("Python","get " << attributeName);
368
380
369 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
381 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
370 switch (member._type) {
382 switch (member._type) {
371 case PythonQtMemberInfo::Property:
383 case PythonQtMemberInfo::Property:
372 if (wrapper->_obj) {
384 if (wrapper->_obj) {
373 if (member._property.userType() != QVariant::Invalid) {
385 if (member._property.userType() != QVariant::Invalid) {
374 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
386
387 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
388 if (profilingCB) {
389 QString methodName = "getProperty(";
390 methodName += attributeName;
391 methodName += ")";
392 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
393 }
394
395 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
396
397 if (profilingCB) {
398 profilingCB(PythonQt::Leave, NULL, NULL);
399 }
400
401 return value;
402
375 } else {
403 } else {
376 Py_INCREF(Py_None);
404 Py_INCREF(Py_None);
377 return Py_None;
405 return Py_None;
378 }
406 }
379 } else {
407 } else {
380 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
408 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
381 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
409 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
382 return NULL;
410 return NULL;
383 }
411 }
384 break;
412 break;
385 case PythonQtMemberInfo::Slot:
413 case PythonQtMemberInfo::Slot:
386 return PythonQtSlotFunction_New(member._slot, obj, NULL);
414 return PythonQtSlotFunction_New(member._slot, obj, NULL);
387 break;
415 break;
388 case PythonQtMemberInfo::EnumValue:
416 case PythonQtMemberInfo::EnumValue:
389 {
417 {
390 PyObject* enumValue = member._enumValue;
418 PyObject* enumValue = member._enumValue;
391 Py_INCREF(enumValue);
419 Py_INCREF(enumValue);
392 return enumValue;
420 return enumValue;
393 }
421 }
394 break;
422 break;
395 case PythonQtMemberInfo::EnumWrapper:
423 case PythonQtMemberInfo::EnumWrapper:
396 {
424 {
397 PyObject* enumWrapper = member._enumWrapper;
425 PyObject* enumWrapper = member._enumWrapper;
398 Py_INCREF(enumWrapper);
426 Py_INCREF(enumWrapper);
399 return enumWrapper;
427 return enumWrapper;
400 }
428 }
401 break;
429 break;
402 case PythonQtMemberInfo::NotFound:
430 case PythonQtMemberInfo::NotFound:
403 {
431 {
404 static const QByteArray getterString("py_get_");
432 static const QByteArray getterString("py_get_");
405 // check for a getter slot
433 // check for a getter slot
406 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
434 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
407 if (member._type == PythonQtMemberInfo::Slot) {
435 if (member._type == PythonQtMemberInfo::Slot) {
408 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
436 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
409 }
437 }
410
438
411 // handle dynamic properties
439 // handle dynamic properties
412 if (wrapper->_obj) {
440 if (wrapper->_obj) {
413 QVariant v = wrapper->_obj->property(attributeName);
441 QVariant v = wrapper->_obj->property(attributeName);
414 if (v.isValid()) {
442 if (v.isValid()) {
415 return PythonQtConv::QVariantToPyObject(v);
443 return PythonQtConv::QVariantToPyObject(v);
416 }
444 }
417 }
445 }
418 }
446 }
419 break;
447 break;
420 default:
448 default:
421 // is an invalid type, go on
449 // is an invalid type, go on
422 break;
450 break;
423 }
451 }
424
452
425 // look for the internal methods (className(), help())
453 // look for the internal methods (className(), help())
426 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
454 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
427 if (internalMethod) {
455 if (internalMethod) {
428 return internalMethod;
456 return internalMethod;
429 }
457 }
430 PyErr_Clear();
458 PyErr_Clear();
431
459
432 if (wrapper->_obj) {
460 if (wrapper->_obj) {
433 // look for a child
461 // look for a child
434 QObjectList children = wrapper->_obj->children();
462 QObjectList children = wrapper->_obj->children();
435 for (int i = 0; i < children.count(); i++) {
463 for (int i = 0; i < children.count(); i++) {
436 QObject *child = children.at(i);
464 QObject *child = children.at(i);
437 if (child->objectName() == attributeName) {
465 if (child->objectName() == attributeName) {
438 return PythonQt::priv()->wrapQObject(child);
466 return PythonQt::priv()->wrapQObject(child);
439 }
467 }
440 }
468 }
441 }
469 }
442
470
443 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
471 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
444 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
472 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
445 return NULL;
473 return NULL;
446 }
474 }
447
475
448 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
476 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
449 {
477 {
450 QString error;
478 QString error;
451 const char *attributeName;
479 const char *attributeName;
452 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
480 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
453
481
454 if ((attributeName = PyString_AsString(name)) == NULL)
482 if ((attributeName = PyString_AsString(name)) == NULL)
455 return -1;
483 return -1;
456
484
457 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
485 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
458 if (member._type == PythonQtMemberInfo::Property) {
486 if (member._type == PythonQtMemberInfo::Property) {
459
487
460 if (!wrapper->_obj) {
488 if (!wrapper->_obj) {
461 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
489 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
462 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
490 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
463 return -1;
491 return -1;
464 }
492 }
465
493
466 QMetaProperty prop = member._property;
494 QMetaProperty prop = member._property;
467 if (prop.isWritable()) {
495 if (prop.isWritable()) {
468 QVariant v;
496 QVariant v;
469 if (prop.isEnumType()) {
497 if (prop.isEnumType()) {
470 // this will give us either a string or an int, everything else will probably be an error
498 // this will give us either a string or an int, everything else will probably be an error
471 v = PythonQtConv::PyObjToQVariant(value);
499 v = PythonQtConv::PyObjToQVariant(value);
472 } else {
500 } else {
473 int t = prop.userType();
501 int t = prop.userType();
474 v = PythonQtConv::PyObjToQVariant(value, t);
502 v = PythonQtConv::PyObjToQVariant(value, t);
475 }
503 }
476 bool success = false;
504 bool success = false;
477 if (v.isValid()) {
505 if (v.isValid()) {
506 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
507 if (profilingCB) {
508 QString methodName = "setProperty(";
509 methodName += attributeName;
510 methodName += ")";
511 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
512 }
513
478 success = prop.write(wrapper->_obj, v);
514 success = prop.write(wrapper->_obj, v);
515
516 if (profilingCB) {
517 profilingCB(PythonQt::Leave, NULL, NULL);
518 }
479 }
519 }
480 if (success) {
520 if (success) {
481 return 0;
521 return 0;
482 } else {
522 } else {
483 error = QString("Property '") + attributeName + "' of type '" +
523 error = QString("Property '") + attributeName + "' of type '" +
484 prop.typeName() + "' does not accept an object of type "
524 prop.typeName() + "' does not accept an object of type "
485 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
525 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
486 }
526 }
487 } else {
527 } else {
488 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
528 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
489 }
529 }
490 } else if (member._type == PythonQtMemberInfo::Slot) {
530 } else if (member._type == PythonQtMemberInfo::Slot) {
491 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
531 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
492 } else if (member._type == PythonQtMemberInfo::EnumValue) {
532 } else if (member._type == PythonQtMemberInfo::EnumValue) {
493 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
533 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
494 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
534 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
495 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
535 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
496 } else if (member._type == PythonQtMemberInfo::NotFound) {
536 } else if (member._type == PythonQtMemberInfo::NotFound) {
497 // check for a setter slot
537 // check for a setter slot
498 static const QByteArray setterString("py_set_");
538 static const QByteArray setterString("py_set_");
499 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
539 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
500 if (setter._type == PythonQtMemberInfo::Slot) {
540 if (setter._type == PythonQtMemberInfo::Slot) {
501 // call the setter and ignore the result value
541 // call the setter and ignore the result value
502 void* result;
542 void* result;
503 PyObject* args = PyTuple_New(1);
543 PyObject* args = PyTuple_New(1);
504 Py_INCREF(value);
544 Py_INCREF(value);
505 PyTuple_SET_ITEM(args, 0, value);
545 PyTuple_SET_ITEM(args, 0, value);
506 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
546 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
507 Py_DECREF(args);
547 Py_DECREF(args);
508 return 0;
548 return 0;
509 }
549 }
510
550
511 // handle dynamic properties
551 // handle dynamic properties
512 if (wrapper->_obj) {
552 if (wrapper->_obj) {
513 QVariant prop = wrapper->_obj->property(attributeName);
553 QVariant prop = wrapper->_obj->property(attributeName);
514 if (prop.isValid()) {
554 if (prop.isValid()) {
515 QVariant v = PythonQtConv::PyObjToQVariant(value);
555 QVariant v = PythonQtConv::PyObjToQVariant(value);
516 if (v.isValid()) {
556 if (v.isValid()) {
517 wrapper->_obj->setProperty(attributeName, v);
557 wrapper->_obj->setProperty(attributeName, v);
518 return 0;
558 return 0;
519 } else {
559 } else {
520 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
560 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
521 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
561 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
522 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
562 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
523 return -1;
563 return -1;
524 }
564 }
525 }
565 }
526 }
566 }
527
567
528 // if we are a derived python class, we allow setting attributes.
568 // if we are a derived python class, we allow setting attributes.
529 // if we are a direct CPP wrapper, we do NOT allow it, since
569 // if we are a direct CPP wrapper, we do NOT allow it, since
530 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
570 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
531 // and when it is recreated from a CPP pointer the attributes are gone...
571 // and when it is recreated from a CPP pointer the attributes are gone...
532 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
572 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
533 return PyBaseObject_Type.tp_setattro(obj,name,value);
573 return PyBaseObject_Type.tp_setattro(obj,name,value);
534 } else {
574 } else {
535 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
575 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
536 }
576 }
537 }
577 }
538
578
539 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
579 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
540 return -1;
580 return -1;
541 }
581 }
542
582
543 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
583 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
544 QString result;
584 QString result;
545 if (wrapper->_wrappedPtr) {
585 if (wrapper->_wrappedPtr) {
546 // first try some manually string conversions for some variants
586 // first try some manually string conversions for some variants
547 int metaid = wrapper->classInfo()->metaTypeId();
587 int metaid = wrapper->classInfo()->metaTypeId();
548 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
588 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
549 if (!result.isEmpty()) {
589 if (!result.isEmpty()) {
550 return result;
590 return result;
551 }
591 }
552 }
592 }
553 // next, try to call py_toString
593 // next, try to call py_toString
554 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
594 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
555 if (info._type == PythonQtMemberInfo::Slot) {
595 if (info._type == PythonQtMemberInfo::Slot) {
556 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
596 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
557 if (resultObj) {
597 if (resultObj) {
558 // TODO this is one conversion too much, would be nicer to call the slot directly...
598 // TODO this is one conversion too much, would be nicer to call the slot directly...
559 result = PythonQtConv::PyObjGetString(resultObj);
599 result = PythonQtConv::PyObjGetString(resultObj);
560 Py_DECREF(resultObj);
600 Py_DECREF(resultObj);
561 }
601 }
562 }
602 }
563 return result;
603 return result;
564 }
604 }
565
605
566 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
606 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
567 {
607 {
568 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
608 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
569
609
570 // QByteArray should be directly returned as a str
610 // QByteArray should be directly returned as a str
571 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
611 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
572 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
612 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
573 if (b->data()) {
613 if (b->data()) {
574 return PyString_FromStringAndSize(b->data(), b->size());
614 return PyString_FromStringAndSize(b->data(), b->size());
575 } else {
615 } else {
576 return PyString_FromString("");
616 return PyString_FromString("");
577 }
617 }
578 }
618 }
579
619
580 const char* typeName = obj->ob_type->tp_name;
620 const char* typeName = obj->ob_type->tp_name;
581 QObject *qobj = wrapper->_obj;
621 QObject *qobj = wrapper->_obj;
582 QString str = getStringFromObject(wrapper);
622 QString str = getStringFromObject(wrapper);
583 if (!str.isEmpty()) {
623 if (!str.isEmpty()) {
584 return PyString_FromFormat("%s", str.toLatin1().constData());
624 return PyString_FromFormat("%s", str.toLatin1().constData());
585 }
625 }
586 if (wrapper->_wrappedPtr) {
626 if (wrapper->_wrappedPtr) {
587 if (wrapper->_obj) {
627 if (wrapper->_obj) {
588 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
628 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
589 } else {
629 } else {
590 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
630 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
591 }
631 }
592 } else {
632 } else {
593 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
633 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
594 }
634 }
595 }
635 }
596
636
597 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
637 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
598 {
638 {
599 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
639 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
600 const char* typeName = obj->ob_type->tp_name;
640 const char* typeName = obj->ob_type->tp_name;
601
641
602 QObject *qobj = wrapper->_obj;
642 QObject *qobj = wrapper->_obj;
603 QString str = getStringFromObject(wrapper);
643 QString str = getStringFromObject(wrapper);
604 if (!str.isEmpty()) {
644 if (!str.isEmpty()) {
605 if (str.startsWith(typeName)) {
645 if (str.startsWith(typeName)) {
606 return PyString_FromFormat("%s", str.toLatin1().constData());
646 return PyString_FromFormat("%s", str.toLatin1().constData());
607 } else {
647 } else {
608 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
648 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
609 }
649 }
610 }
650 }
611 if (wrapper->_wrappedPtr) {
651 if (wrapper->_wrappedPtr) {
612 if (wrapper->_obj) {
652 if (wrapper->_obj) {
613 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
653 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
614 } else {
654 } else {
615 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
655 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
616 }
656 }
617 } else {
657 } else {
618 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
658 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
619 }
659 }
620 }
660 }
621
661
622 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
662 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
623 {
663 {
624 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
664 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
625 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
665 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
626 }
666 }
627
667
628
668
629 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
669 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
630 {
670 {
631 if (obj->_wrappedPtr != NULL) {
671 if (obj->_wrappedPtr != NULL) {
632 return reinterpret_cast<long>(obj->_wrappedPtr);
672 return reinterpret_cast<long>(obj->_wrappedPtr);
633 } else {
673 } else {
634 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
674 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
635 return reinterpret_cast<long>(qobj);
675 return reinterpret_cast<long>(qobj);
636 }
676 }
637 }
677 }
638
678
639
679
640
680
641 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
681 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
642 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
682 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
643 0, /* nb_add */
683 0, /* nb_add */
644 0, /* nb_subtract */
684 0, /* nb_subtract */
645 0, /* nb_multiply */
685 0, /* nb_multiply */
646 0, /* nb_divide */
686 0, /* nb_divide */
647 0, /* nb_remainder */
687 0, /* nb_remainder */
648 0, /* nb_divmod */
688 0, /* nb_divmod */
649 0, /* nb_power */
689 0, /* nb_power */
650 0, /* nb_negative */
690 0, /* nb_negative */
651 0, /* nb_positive */
691 0, /* nb_positive */
652 0, /* nb_absolute */
692 0, /* nb_absolute */
653 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
693 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
654 0, /* nb_invert */
694 0, /* nb_invert */
655 0, /* nb_lshift */
695 0, /* nb_lshift */
656 0, /* nb_rshift */
696 0, /* nb_rshift */
657 0, /* nb_and */
697 0, /* nb_and */
658 0, /* nb_xor */
698 0, /* nb_xor */
659 0, /* nb_or */
699 0, /* nb_or */
660 0, /* nb_coerce */
700 0, /* nb_coerce */
661 0, /* nb_int */
701 0, /* nb_int */
662 0, /* nb_long */
702 0, /* nb_long */
663 0, /* nb_float */
703 0, /* nb_float */
664 0, /* nb_oct */
704 0, /* nb_oct */
665 0, /* nb_hex */
705 0, /* nb_hex */
666 0, /* nb_inplace_add */
706 0, /* nb_inplace_add */
667 0, /* nb_inplace_subtract */
707 0, /* nb_inplace_subtract */
668 0, /* nb_inplace_multiply */
708 0, /* nb_inplace_multiply */
669 0, /* nb_inplace_divide */
709 0, /* nb_inplace_divide */
670 0, /* nb_inplace_remainder */
710 0, /* nb_inplace_remainder */
671 0, /* nb_inplace_power */
711 0, /* nb_inplace_power */
672 0, /* nb_inplace_lshift */
712 0, /* nb_inplace_lshift */
673 0, /* nb_inplace_rshift */
713 0, /* nb_inplace_rshift */
674 0, /* nb_inplace_and */
714 0, /* nb_inplace_and */
675 0, /* nb_inplace_xor */
715 0, /* nb_inplace_xor */
676 0, /* nb_inplace_or */
716 0, /* nb_inplace_or */
677 0, /* nb_floor_divide */
717 0, /* nb_floor_divide */
678 0, /* nb_true_divide */
718 0, /* nb_true_divide */
679 0, /* nb_inplace_floor_divide */
719 0, /* nb_inplace_floor_divide */
680 0, /* nb_inplace_true_divide */
720 0, /* nb_inplace_true_divide */
681 };
721 };
682
722
683 PyTypeObject PythonQtInstanceWrapper_Type = {
723 PyTypeObject PythonQtInstanceWrapper_Type = {
684 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
724 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
685 0, /*ob_size*/
725 0, /*ob_size*/
686 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
726 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
687 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
727 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
688 0, /*tp_itemsize*/
728 0, /*tp_itemsize*/
689 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
729 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
690 0, /*tp_print*/
730 0, /*tp_print*/
691 0, /*tp_getattr*/
731 0, /*tp_getattr*/
692 0, /*tp_setattr*/
732 0, /*tp_setattr*/
693 0, /*tp_compare*/
733 0, /*tp_compare*/
694 PythonQtInstanceWrapper_repr, /*tp_repr*/
734 PythonQtInstanceWrapper_repr, /*tp_repr*/
695 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
735 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
696 0, /*tp_as_sequence*/
736 0, /*tp_as_sequence*/
697 0, /*tp_as_mapping*/
737 0, /*tp_as_mapping*/
698 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
738 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
699 0, /*tp_call*/
739 0, /*tp_call*/
700 PythonQtInstanceWrapper_str, /*tp_str*/
740 PythonQtInstanceWrapper_str, /*tp_str*/
701 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
741 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
702 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
742 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
703 0, /*tp_as_buffer*/
743 0, /*tp_as_buffer*/
704 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
744 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
705 "PythonQtInstanceWrapper object", /* tp_doc */
745 "PythonQtInstanceWrapper object", /* tp_doc */
706 0, /* tp_traverse */
746 0, /* tp_traverse */
707 0, /* tp_clear */
747 0, /* tp_clear */
708 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
748 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
709 0, /* tp_weaklistoffset */
749 0, /* tp_weaklistoffset */
710 0, /* tp_iter */
750 0, /* tp_iter */
711 0, /* tp_iternext */
751 0, /* tp_iternext */
712 0, /* tp_methods */
752 0, /* tp_methods */
713 0, /* tp_members */
753 0, /* tp_members */
714 0, /* tp_getset */
754 0, /* tp_getset */
715 0, /* tp_base */
755 0, /* tp_base */
716 0, /* tp_dict */
756 0, /* tp_dict */
717 0, /* tp_descr_get */
757 0, /* tp_descr_get */
718 0, /* tp_descr_set */
758 0, /* tp_descr_set */
719 0, /* tp_dictoffset */
759 0, /* tp_dictoffset */
720 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
760 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
721 0, /* tp_alloc */
761 0, /* tp_alloc */
722 PythonQtInstanceWrapper_new, /* tp_new */
762 PythonQtInstanceWrapper_new, /* tp_new */
723 };
763 };
724
764
725 //-------------------------------------------------------
765 //-------------------------------------------------------
726
766
@@ -1,98 +1,100
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_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 PythonQtInstanceWrapper.h
38 // \file PythonQtInstanceWrapper.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 <Python.h>
45 #include <Python.h>
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include <QPointer>
48 #include <QPointer>
49
49
50 #include "structmember.h"
50 #include "structmember.h"
51 #include "methodobject.h"
51 #include "methodobject.h"
52 #include "compile.h"
52 #include "compile.h"
53 #include "eval.h"
53 #include "eval.h"
54
54
55 class PythonQtClassInfo;
55 class PythonQtClassInfo;
56 class QObject;
56 class QObject;
57
57
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
59
59
60 //---------------------------------------------------------------
60 //---------------------------------------------------------------
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
62 typedef struct PythonQtInstanceWrapperStruct {
62 typedef struct PythonQtInstanceWrapperStruct {
63 PyObject_HEAD
63 PyObject_HEAD
64
64
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
66 PythonQtClassInfo* classInfo();
66 PythonQtClassInfo* classInfo();
67
67
68 //! set the QObject pointer
68 //! set the QObject pointer
69 void setQObject(QObject* object) {
69 void setQObject(QObject* object) {
70 _obj = object;
70 _obj = object;
71 _objPointerCopy = object;
71 _objPointerCopy = object;
72 }
72 }
73
73
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
75 QPointer<QObject> _obj;
75 QPointer<QObject> _obj;
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
78 void* _objPointerCopy;
78 void* _objPointerCopy;
79
79
80 //! optional C++ object Ptr that is wrapped by the above _obj
80 //! optional C++ object Ptr that is wrapped by the above _obj
81 void* _wrappedPtr;
81 void* _wrappedPtr;
82
82
83 // TODO xxx: put booleans into int that holds flags
83 // TODO xxx: put booleans into int that holds flags
84
84
85 //! flag that stores if the object is owned by pythonQt
85 //! flag that stores if the object is owned by pythonQt
86 bool _ownedByPythonQt;
86 bool _ownedByPythonQt;
87
87
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
89 bool _useQMetaTypeDestroy;
89 bool _useQMetaTypeDestroy;
90
90
91 //! stores if the object is a shell instance
91 //! stores if the object is a shell instance
92 bool _isShellInstance;
92 bool _isShellInstance;
93
93
94 } PythonQtInstanceWrapper;
94 } PythonQtInstanceWrapper;
95
95
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
97
97
98 #endif No newline at end of file
98 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self);
99
100 #endif
@@ -1,353 +1,350
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 arguments << QByteArray(args[i]);
103 }
103 }
104 fullSig += ")";
104 fullSig += ")";
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
106 if (!result) {
106 if (!result) {
107 result = new PythonQtMethodInfo(typeName, arguments);
107 result = new PythonQtMethodInfo(typeName, arguments);
108 _cachedSignatures.insert(fullSig, result);
108 _cachedSignatures.insert(fullSig, result);
109 }
109 }
110 return result;
110 return result;
111 }
111 }
112
112
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
114 {
114 {
115 QByteArray name = orgName;
115 QByteArray name = orgName;
116
116
117 type.enumWrapper = NULL;
117 type.enumWrapper = NULL;
118
118
119 int len = name.length();
119 int len = name.length();
120 if (len>0) {
120 if (len>0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
122 name = name.mid(6);
122 name = name.mid(6);
123 len -= 6;
123 len -= 6;
124 type.isConst = true;
124 type.isConst = true;
125 } else {
125 } else {
126 type.isConst = false;
126 type.isConst = false;
127 }
127 }
128 char pointerCount = 0;
128 char pointerCount = 0;
129 bool hadReference = false;
129 bool hadReference = false;
130 // remove * and & from the end of the string, handle & and * the same way
130 // remove * and & from the end of the string, handle & and * the same way
131 while (name.at(len-1) == '*') {
131 while (name.at(len-1) == '*') {
132 len--;
132 len--;
133 pointerCount++;
133 pointerCount++;
134 }
134 }
135 while (name.at(len-1) == '&') {
135 while (name.at(len-1) == '&') {
136 len--;
136 len--;
137 hadReference = true;
137 hadReference = true;
138 }
138 }
139 if (len!=name.length()) {
139 if (len!=name.length()) {
140 name = name.left(len);
140 name = name.left(len);
141 }
141 }
142 type.pointerCount = pointerCount;
142 type.pointerCount = pointerCount;
143
143
144 QByteArray alias = _parameterNameAliases.value(name);
144 QByteArray alias = _parameterNameAliases.value(name);
145 if (!alias.isEmpty()) {
145 if (!alias.isEmpty()) {
146 name = alias;
146 name = alias;
147 }
147 }
148
148
149 type.typeId = nameToType(name);
149 type.typeId = nameToType(name);
150 if ((type.pointerCount == 0) && type.typeId == Unknown) {
150 if ((type.pointerCount == 0) && type.typeId == Unknown) {
151 type.typeId = QMetaType::type(name.constData());
151 type.typeId = QMetaType::type(name.constData());
152 if (type.typeId == QMetaType::Void) {
152 if (type.typeId == QMetaType::Void) {
153 type.typeId = Unknown;
153 type.typeId = Unknown;
154 }
154 }
155 }
155 }
156 type.name = name;
156 type.name = name;
157
157
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
159 bool isLocalEnum;
159 bool isLocalEnum;
160 // TODOXXX: make use of this flag!
160 // TODOXXX: make use of this flag!
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
162 }
162 }
163 } else {
163 } else {
164 type.typeId = QMetaType::Void;
164 type.typeId = QMetaType::Void;
165 type.pointerCount = 0;
165 type.pointerCount = 0;
166 type.isConst = false;
166 type.isConst = false;
167 }
167 }
168 }
168 }
169
169
170 int PythonQtMethodInfo::nameToType(const char* name)
170 int PythonQtMethodInfo::nameToType(const char* name)
171 {
171 {
172 if (_parameterTypeDict.isEmpty()) {
172 if (_parameterTypeDict.isEmpty()) {
173 // we could also use QMetaType::nameToType, but that does a string compare search
173 // we could also use QMetaType::nameToType, but that does a string compare search
174 // and does not support QVariant
174 // and does not support QVariant
175
175
176 // QMetaType names
176 // QMetaType names
177 _parameterTypeDict.insert("long", QMetaType::Long);
177 _parameterTypeDict.insert("long", QMetaType::Long);
178 _parameterTypeDict.insert("int", QMetaType::Int);
178 _parameterTypeDict.insert("int", QMetaType::Int);
179 _parameterTypeDict.insert("short", QMetaType::Short);
179 _parameterTypeDict.insert("short", QMetaType::Short);
180 _parameterTypeDict.insert("char", QMetaType::Char);
180 _parameterTypeDict.insert("char", QMetaType::Char);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
190 _parameterTypeDict.insert("float", QMetaType::Float);
190 _parameterTypeDict.insert("float", QMetaType::Float);
191 _parameterTypeDict.insert("double", QMetaType::Double);
191 _parameterTypeDict.insert("double", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
195 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
196 _parameterTypeDict.insert("QString", QMetaType::QString);
195 _parameterTypeDict.insert("QString", QMetaType::QString);
197 _parameterTypeDict.insert("", QMetaType::Void);
196 _parameterTypeDict.insert("", QMetaType::Void);
198 _parameterTypeDict.insert("void", QMetaType::Void);
197 _parameterTypeDict.insert("void", QMetaType::Void);
199 // QVariant names
198 // QVariant names
200 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
199 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
201 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
200 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
202 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
201 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
203 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
202 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
204 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
203 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
205 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
204 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
205 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
206 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
207 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
208 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
209 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
210 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
211 _parameterTypeDict.insert("QDate", QMetaType::QDate);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
212 _parameterTypeDict.insert("QTime", QMetaType::QTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
213 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
214 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
215 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
216 _parameterTypeDict.insert("QRect", QMetaType::QRect);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
217 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
218 _parameterTypeDict.insert("QSize", QMetaType::QSize);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
219 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
220 _parameterTypeDict.insert("QLine", QMetaType::QLine);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
221 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
222 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
223 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
224 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
228 _parameterTypeDict.insert("QFont", QMetaType::QFont);
225 _parameterTypeDict.insert("QFont", QMetaType::QFont);
229 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
226 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
230 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
227 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
231 _parameterTypeDict.insert("QColor", QMetaType::QColor);
228 _parameterTypeDict.insert("QColor", QMetaType::QColor);
232 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
229 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
233 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
230 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
234 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
231 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
232 _parameterTypeDict.insert("QImage", QMetaType::QImage);
236 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
233 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
237 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
234 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
238 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
235 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
239 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
236 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
240 _parameterTypeDict.insert("QPen", QMetaType::QPen);
237 _parameterTypeDict.insert("QPen", QMetaType::QPen);
241 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
238 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
242 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
239 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
243 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
240 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
244 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
241 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
245 // own special types... (none so far, could be e.g. ObjectList
242 // own special types... (none so far, could be e.g. ObjectList
246 }
243 }
247 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
244 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
248 if (it!=_parameterTypeDict.end()) {
245 if (it!=_parameterTypeDict.end()) {
249 return it.value();
246 return it.value();
250 } else {
247 } else {
251 return PythonQtMethodInfo::Unknown;
248 return PythonQtMethodInfo::Unknown;
252 }
249 }
253 }
250 }
254
251
255 void PythonQtMethodInfo::cleanupCachedMethodInfos()
252 void PythonQtMethodInfo::cleanupCachedMethodInfos()
256 {
253 {
257 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
254 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
258 while (i.hasNext()) {
255 while (i.hasNext()) {
259 delete i.next().value();
256 delete i.next().value();
260 }
257 }
261 }
258 }
262
259
263 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
260 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
264 {
261 {
265 _parameterNameAliases.insert(alias, name);
262 _parameterNameAliases.insert(alias, name);
266 }
263 }
267
264
268 //-------------------------------------------------------------------------------------------------
265 //-------------------------------------------------------------------------------------------------
269
266
270 void PythonQtSlotInfo::deleteOverloadsAndThis()
267 void PythonQtSlotInfo::deleteOverloadsAndThis()
271 {
268 {
272 PythonQtSlotInfo* cur = this;
269 PythonQtSlotInfo* cur = this;
273 while(cur->nextInfo()) {
270 while(cur->nextInfo()) {
274 PythonQtSlotInfo* next = cur->nextInfo();
271 PythonQtSlotInfo* next = cur->nextInfo();
275 delete cur;
272 delete cur;
276 cur = next;
273 cur = next;
277 }
274 }
278 }
275 }
279
276
280
277
281 QString PythonQtSlotInfo::fullSignature()
278 QString PythonQtSlotInfo::fullSignature()
282 {
279 {
283 bool skipFirstArg = isInstanceDecorator();
280 bool skipFirstArg = isInstanceDecorator();
284 QString result = _meta.typeName();
281 QString result = _meta.typeName();
285 QByteArray sig = slotName();
282 QByteArray sig = slotName();
286 QList<QByteArray> names = _meta.parameterNames();
283 QList<QByteArray> names = _meta.parameterNames();
287
284
288 bool isStatic = false;
285 bool isStatic = false;
289 bool isConstructor = false;
286 bool isConstructor = false;
290 bool isDestructor = false;
287 bool isDestructor = false;
291
288
292 if (_type == ClassDecorator) {
289 if (_type == ClassDecorator) {
293 if (sig.startsWith("new_")) {
290 if (sig.startsWith("new_")) {
294 sig = sig.mid(strlen("new_"));
291 sig = sig.mid(strlen("new_"));
295 isConstructor = true;
292 isConstructor = true;
296 } else if (sig.startsWith("delete_")) {
293 } else if (sig.startsWith("delete_")) {
297 sig = sig.mid(strlen("delete_"));
294 sig = sig.mid(strlen("delete_"));
298 isDestructor = true;
295 isDestructor = true;
299 } else if(sig.startsWith("static_")) {
296 } else if(sig.startsWith("static_")) {
300 isStatic = true;
297 isStatic = true;
301 sig = sig.mid(strlen("static_"));
298 sig = sig.mid(strlen("static_"));
302 int idx = sig.indexOf("_");
299 int idx = sig.indexOf("_");
303 if (idx>=0) {
300 if (idx>=0) {
304 sig = sig.mid(idx+1);
301 sig = sig.mid(idx+1);
305 }
302 }
306 }
303 }
307 }
304 }
308
305
309 result += QByteArray(" ") + sig;
306 result += QByteArray(" ") + sig;
310 result += "(";
307 result += "(";
311
308
312 int lastEntry = _parameters.count()-1;
309 int lastEntry = _parameters.count()-1;
313 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
310 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
314 if (_parameters.at(i).isConst) {
311 if (_parameters.at(i).isConst) {
315 result += "const ";
312 result += "const ";
316 }
313 }
317 result += _parameters.at(i).name;
314 result += _parameters.at(i).name;
318 if (_parameters.at(i).pointerCount) {
315 if (_parameters.at(i).pointerCount) {
319 QByteArray stars;
316 QByteArray stars;
320 stars.fill('*', _parameters.at(i).pointerCount);
317 stars.fill('*', _parameters.at(i).pointerCount);
321 result += stars;
318 result += stars;
322 }
319 }
323 if (!names.at(i-1).isEmpty()) {
320 if (!names.at(i-1).isEmpty()) {
324 result += " ";
321 result += " ";
325 result += names.at(i-1);
322 result += names.at(i-1);
326 }
323 }
327 if (i!=lastEntry) {
324 if (i!=lastEntry) {
328 result += ", ";
325 result += ", ";
329 }
326 }
330 }
327 }
331 result += ")";
328 result += ")";
332
329
333 if (isStatic) {
330 if (isStatic) {
334 result = QString("static ") + result;
331 result = QString("static ") + result;
335 }
332 }
336 if (isConstructor) {
333 if (isConstructor) {
337 // result = QString("constructor ") + result;
334 // result = QString("constructor ") + result;
338 }
335 }
339 if (isDestructor) {
336 if (isDestructor) {
340 result = QString("~") + result;
337 result = QString("~") + result;
341 }
338 }
342 return result;
339 return result;
343 }
340 }
344
341
345
342
346 QByteArray PythonQtSlotInfo::slotName()
343 QByteArray PythonQtSlotInfo::slotName()
347 {
344 {
348 QByteArray sig(_meta.signature());
345 QByteArray sig(_meta.signature());
349 int idx = sig.indexOf('(');
346 int idx = sig.indexOf('(');
350 sig = sig.left(idx);
347 sig = sig.left(idx);
351 return sig;
348 return sig;
352 }
349 }
353
350
@@ -1,142 +1,175
1 #ifndef _PYTHONQTMISC_H
1 #ifndef _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_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 PythonQtMisc.h
38 // \file PythonQtMisc.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
45
46 #include <QList>
46 #include <QList>
47
47
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
49 { type* item = (type*)store.nextValuePtr(); \
49 { type* item = (type*)store.nextValuePtr(); \
50 *item = value; \
50 *item = value; \
51 ptr = (void*)item; \
51 ptr = (void*)item; \
52 }
52 }
53
53
54 #define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \
54 #define PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedPtr,store, type, value, ptr) \
55 { \
55 { \
56 type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \
56 type* item = (type*)(alreadyAllocatedPtr?alreadyAllocatedPtr:store.nextValuePtr()); \
57 *item = value; \
57 *item = value; \
58 ptr = (void*)item; \
58 ptr = (void*)item; \
59 }
59 }
60
60
61 //! stores a position in the PythonQtValueStorage
61 //! stores a position in the PythonQtValueStorage
62 class PythonQtValueStoragePosition {
62 class PythonQtValueStoragePosition {
63
63
64 public:
64 public:
65 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
65 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
66
66
67 int chunkIdx;
67 int chunkIdx;
68 int chunkOffset;
68 int chunkOffset;
69
69
70 };
70 };
71
71
72 //! a helper class that stores basic C++ value types in chunks
72 //! a helper class that stores basic C++ value types in chunks
73 template <typename T, int chunkEntries> class PythonQtValueStorage
73 template <typename T, int chunkEntries> class PythonQtValueStorage
74 {
74 {
75 public:
75 public:
76 PythonQtValueStorage() {
76 PythonQtValueStorage() {
77 _chunkIdx = 0;
77 _chunkIdx = 0;
78 _chunkOffset = 0;
78 _chunkOffset = 0;
79 _currentChunk = new T[chunkEntries];
79 _currentChunk = new T[chunkEntries];
80 _chunks.append(_currentChunk);
80 _chunks.append(_currentChunk);
81 };
81 };
82
82
83 //! clear all memory
83 //! clear all memory
84 void clear() {
84 void clear() {
85 T* chunk;
85 T* chunk;
86 foreach(chunk, _chunks) {
86 foreach(chunk, _chunks) {
87 delete[]chunk;
87 delete[]chunk;
88 }
88 }
89 _chunks.clear();
89 _chunks.clear();
90 }
90 }
91
91
92 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
93 void reset() {
94 _chunkIdx = 0;
95 _chunkOffset = 0;
96 _currentChunk = _chunks.at(0);
97 }
98
99 //! get the current position to be restored with setPos
92 //! get the current position to be restored with setPos
100 void getPos(PythonQtValueStoragePosition & pos) {
93 void getPos(PythonQtValueStoragePosition & pos) {
101 pos.chunkIdx = _chunkIdx;
94 pos.chunkIdx = _chunkIdx;
102 pos.chunkOffset = _chunkOffset;
95 pos.chunkOffset = _chunkOffset;
103 }
96 }
104
97
105 //! set the current position (without freeing memory, thus caching old entries for reuse)
98 //! set the current position (without freeing memory, thus caching old entries for reuse)
106 void setPos(const PythonQtValueStoragePosition& pos) {
99 void setPos(const PythonQtValueStoragePosition& pos) {
107 _chunkOffset = pos.chunkOffset;
100 _chunkOffset = pos.chunkOffset;
108 if (_chunkIdx != pos.chunkIdx) {
101 if (_chunkIdx != pos.chunkIdx) {
109 _chunkIdx = pos.chunkIdx;
102 _chunkIdx = pos.chunkIdx;
110 _currentChunk = _chunks.at(_chunkIdx);
103 _currentChunk = _chunks.at(_chunkIdx);
111 }
104 }
112 }
105 }
113
106
114 //! add one default constructed value and return the pointer to it
107 //! add one default constructed value and return the pointer to it
115 T* nextValuePtr() {
108 T* nextValuePtr() {
116 if (_chunkOffset>=chunkEntries) {
109 if (_chunkOffset>=chunkEntries) {
117 _chunkIdx++;
110 _chunkIdx++;
118 if (_chunkIdx >= _chunks.size()) {
111 if (_chunkIdx >= _chunks.size()) {
119 T* newChunk = new T[chunkEntries];
112 T* newChunk = new T[chunkEntries];
120 _chunks.append(newChunk);
113 _chunks.append(newChunk);
121 _currentChunk = newChunk;
114 _currentChunk = newChunk;
122 } else {
115 } else {
123 _currentChunk = _chunks.at(_chunkIdx);
116 _currentChunk = _chunks.at(_chunkIdx);
124 }
117 }
125 _chunkOffset = 0;
118 _chunkOffset = 0;
126 }
119 }
127 T* newEntry = _currentChunk + _chunkOffset;
120 T* newEntry = _currentChunk + _chunkOffset;
128 _chunkOffset++;
121 _chunkOffset++;
129 return newEntry;
122 return newEntry;
130 };
123 };
131
124
132 private:
125 protected:
133 QList<T*> _chunks;
126 QList<T*> _chunks;
134
127
135 int _chunkIdx;
128 int _chunkIdx;
136 int _chunkOffset;
129 int _chunkOffset;
137 T* _currentChunk;
130 T* _currentChunk;
138
131
139 };
132 };
140
133
134 //! a helper class that stores basic C++ value types in chunks and clears the unused values on setPos() usage.
135 template <typename T, int chunkEntries> class PythonQtValueStorageWithCleanup : public PythonQtValueStorage<T, chunkEntries>
136 {
137 public:
138 void setPos(const PythonQtValueStoragePosition& pos) {
139 if (_chunkIdx > pos.chunkIdx) {
140 T* firstChunk = _chunks.at(pos.chunkIdx);
141 // clear region in first chunk
142 for (int i = pos.chunkOffset; i < chunkEntries; i++) {
143 firstChunk[i] = T();
144 }
145 for (int chunk = pos.chunkIdx + 1; chunk < _chunkIdx; chunk++) {
146 // clear the full chunks between the first and last chunk
147 T* fullChunk = _chunks.at(chunk);
148 for (int i = 0; i < chunkEntries; i++) {
149 fullChunk[i] = T();
150 }
151 }
152 // clear region in last chunk
153 T* lastChunk = _chunks.at(_chunkIdx);
154 for (int i = 0; i < _chunkOffset; i++) {
155 lastChunk[i] = T();
156 }
157 } else if (_chunkIdx == pos.chunkIdx) {
158 // clear the region in the last chunk only
159 T* lastChunk = _chunks.at(_chunkIdx);
160 for (int i = pos.chunkOffset; i<_chunkOffset; i++) {
161 lastChunk[i] = T();
162 }
163 }
164
165 PythonQtValueStorage<T, chunkEntries>::setPos(pos);
166 }
167
168 private:
169 using PythonQtValueStorage<T, chunkEntries>::_chunks;
170 using PythonQtValueStorage<T, chunkEntries>::_chunkIdx;
171 using PythonQtValueStorage<T, chunkEntries>::_chunkOffset;
172 using PythonQtValueStorage<T, chunkEntries>::_currentChunk;
173 };
141
174
142 #endif
175 #endif
@@ -1,174 +1,174
1 #ifndef _PYTHONQTOBJECTPTR_H
1 #ifndef _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_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 PythonQtObjectPtr.h
38 // \file PythonQtObjectPtr.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 <Python.h>
45 #include <Python.h>
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include <QVariant>
47 #include <QVariant>
48 #include <QVariantList>
48 #include <QVariantList>
49
49
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
51 class PYTHONQT_EXPORT PythonQtObjectPtr
51 class PYTHONQT_EXPORT PythonQtObjectPtr
52 {
52 {
53 public:
53 public:
54 PythonQtObjectPtr():_object(NULL) {}
54 PythonQtObjectPtr():_object(NULL) {}
55
55
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
57 setObject(p.object());
57 setObject(p.object());
58 }
58 }
59
59
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
62 fromVariant(variant);
62 fromVariant(variant);
63 }
63 }
64
64
65 PythonQtObjectPtr(PyObject* o) {
65 PythonQtObjectPtr(PyObject* o) {
66 _object = o;
66 _object = o;
67 if (o) Py_INCREF(_object);
67 if (o) Py_INCREF(_object);
68 }
68 }
69
69
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
70 ~PythonQtObjectPtr() { if (_object) { Py_DECREF(_object); } }
71
71
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
73 bool fromVariant(const QVariant& variant);
73 bool fromVariant(const QVariant& variant);
74
74
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
76 setObject(p.object());
76 setObject(p.object());
77 return *this;
77 return *this;
78 }
78 }
79
79
80 PythonQtObjectPtr &operator=(PyObject* o) {
80 PythonQtObjectPtr &operator=(PyObject* o) {
81 setObject(o);
81 setObject(o);
82 return *this;
82 return *this;
83 }
83 }
84
84
85
85
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
87 fromVariant(variant);
87 fromVariant(variant);
88 return *this;
88 return *this;
89 }
89 }
90
90
91
91
92 bool operator==( const PythonQtObjectPtr &p ) const {
92 bool operator==( const PythonQtObjectPtr &p ) const {
93 return object() == p.object();
93 return object() == p.object();
94 }
94 }
95
95
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
97 return !( *this == p );
97 return !( *this == p );
98 }
98 }
99
99
100 bool operator==( PyObject* p ) const {
100 bool operator==( PyObject* p ) const {
101 return object() == p;
101 return object() == p;
102 }
102 }
103
103
104 bool operator!= ( PyObject* p ) const {
104 bool operator!= ( PyObject* p ) const {
105 return object() != p;
105 return object() != p;
106 }
106 }
107
107
108 bool isNull() const { return !object(); }
108 bool isNull() const { return !object(); }
109
109
110 PyObject* operator->() const { return object(); }
110 PyObject* operator->() const { return object(); }
111
111
112 PyObject& operator*() const { return *( object() ); }
112 PyObject& operator*() const { return *( object() ); }
113
113
114 operator PyObject*() const { return object(); }
114 operator PyObject*() const { return object(); }
115
115
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
117 void setNewRef(PyObject* o) {
117 void setNewRef(PyObject* o) {
118 if (o != _object) {
118 if (o != _object) {
119 if (_object) Py_DECREF(_object);
119 if (_object) { Py_DECREF(_object); }
120 _object = o;
120 _object = o;
121 }
121 }
122 }
122 }
123
123
124 PyObject* object() const {
124 PyObject* object() const {
125 return _object;
125 return _object;
126 }
126 }
127
127
128 //! evaluates the given script code in the context of this object and returns the result value
128 //! evaluates the given script code in the context of this object and returns the result value
129 QVariant evalScript(const QString& script, int start = Py_file_input);
129 QVariant evalScript(const QString& script, int start = Py_file_input);
130
130
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
132 //! If pycode is NULL, a python error is printed.
132 //! If pycode is NULL, a python error is printed.
133 QVariant evalCode(PyObject* pycode);
133 QVariant evalCode(PyObject* pycode);
134
134
135 //! evaluates the given code in the context
135 //! evaluates the given code in the context
136 void evalFile(const QString& filename);
136 void evalFile(const QString& filename);
137
137
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
139 void addObject(const QString& name, QObject* object);
139 void addObject(const QString& name, QObject* object);
140
140
141 //! add the given variable to the module
141 //! add the given variable to the module
142 void addVariable(const QString& name, const QVariant& v);
142 void addVariable(const QString& name, const QVariant& v);
143
143
144 //! remove the given variable
144 //! remove the given variable
145 void removeVariable(const QString& name);
145 void removeVariable(const QString& name);
146
146
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
148 QVariant getVariable(const QString& name);
148 QVariant getVariable(const QString& name);
149
149
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
152
152
153 //! call the contained python object directly, returns the result converted to a QVariant
153 //! call the contained python object directly, returns the result converted to a QVariant
154 QVariant call(const QVariantList& args = QVariantList());
154 QVariant call(const QVariantList& args = QVariantList());
155
155
156 protected:
156 protected:
157
157
158 void setObject(PyObject* o) {
158 void setObject(PyObject* o) {
159 if (o != _object) {
159 if (o != _object) {
160 if (_object) Py_DECREF(_object);
160 if (_object) { Py_DECREF(_object); }
161 _object = o;
161 _object = o;
162 if (_object) Py_INCREF(_object);
162 if (_object) { Py_INCREF(_object); }
163 }
163 }
164 }
164 }
165
165
166 private:
166 private:
167 PyObject* _object;
167 PyObject* _object;
168 };
168 };
169
169
170
170
171 // register it to the meta type system
171 // register it to the meta type system
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
173
173
174 #endif No newline at end of file
174 #endif
@@ -1,226 +1,228
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)
60
59 // 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
60 // 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
61
63
62 int numPythonArgs = -1;
64 int numPythonArgs = -1;
63 if (PyFunction_Check(callable)) {
65 if (PyFunction_Check(callable)) {
64 PyObject* o = callable;
66 PyObject* o = callable;
65 PyFunctionObject* func = (PyFunctionObject*)o;
67 PyFunctionObject* func = (PyFunctionObject*)o;
66 PyCodeObject* code = (PyCodeObject*)func->func_code;
68 PyCodeObject* code = (PyCodeObject*)func->func_code;
67 if (!(code->co_flags & 0x04)) {
69 if (!(code->co_flags & 0x04)) {
68 numPythonArgs = code->co_argcount;
70 numPythonArgs = code->co_argcount;
69 } else {
71 } else {
70 // variable numbers of arguments allowed
72 // variable numbers of arguments allowed
71 }
73 }
72 } else if (PyMethod_Check(callable)) {
74 } else if (PyMethod_Check(callable)) {
73 PyObject* o = callable;
75 PyObject* o = callable;
74 PyMethodObject* method = (PyMethodObject*)o;
76 PyMethodObject* method = (PyMethodObject*)o;
75 if (PyFunction_Check(method->im_func)) {
77 if (PyFunction_Check(method->im_func)) {
76 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
78 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
77 PyCodeObject* code = (PyCodeObject*)func->func_code;
79 PyCodeObject* code = (PyCodeObject*)func->func_code;
78 if (!(code->co_flags & 0x04)) {
80 if (!(code->co_flags & 0x04)) {
79 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"
80 } else {
82 } else {
81 // variable numbers of arguments allowed
83 // variable numbers of arguments allowed
82 }
84 }
83 }
85 }
84 }
86 }
85
87
86 const PythonQtMethodInfo* m = methodInfos;
88 const PythonQtMethodInfo* m = methodInfos;
87 // parameterCount includes return value:
89 // parameterCount includes return value:
88 int count = m->parameterCount();
90 int count = m->parameterCount();
89 if (numPythonArgs!=-1) {
91 if (numPythonArgs!=-1) {
90 if (count>numPythonArgs+1) {
92 if (count>numPythonArgs+1) {
91 // take less arguments
93 // take less arguments
92 count = numPythonArgs+1;
94 count = numPythonArgs+1;
93 }
95 }
94 }
96 }
95
97
96 PyObject* pargs = NULL;
98 PyObject* pargs = NULL;
97 if (count>1) {
99 if (count>1) {
98 pargs = PyTuple_New(count-1);
100 pargs = PyTuple_New(count-1);
99 }
101 }
100 bool err = false;
102 bool err = false;
101 // transform Qt values to Python
103 // transform Qt values to Python
102 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
104 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
103 for (int i = 1; i < count; i++) {
105 for (int i = 1; i < count; i++) {
104 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
106 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
105 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
107 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
106 if (arg) {
108 if (arg) {
107 // steals reference, no unref
109 // steals reference, no unref
108 PyTuple_SetItem(pargs, i-1,arg);
110 PyTuple_SetItem(pargs, i-1,arg);
109 } else {
111 } else {
110 err = true;
112 err = true;
111 break;
113 break;
112 }
114 }
113 }
115 }
114
116
115 PyObject* result = NULL;
117 PyObject* result = NULL;
116 if (!err) {
118 if (!err) {
117 PyErr_Clear();
119 PyErr_Clear();
118 result = PyObject_CallObject(callable, pargs);
120 result = PyObject_CallObject(callable, pargs);
119 if (result) {
121 if (result) {
120 // ok
122 // ok
121 } else {
123 } else {
122 PythonQt::self()->handleError();
124 PythonQt::self()->handleError();
123 }
125 }
124 }
126 }
125 if (pargs) {
127 if (pargs) {
126 // free the arguments again
128 // free the arguments again
127 Py_DECREF(pargs);
129 Py_DECREF(pargs);
128 }
130 }
129
131
130 return result;
132 return result;
131 }
133 }
132
134
133 //------------------------------------------------------------------------------
135 //------------------------------------------------------------------------------
134
136
135 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
137 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
136 {
138 {
137 _obj = obj;
139 _obj = obj;
138
140
139 // fetch the class info for object, since we will need to for correct enum resolution in
141 // fetch the class info for object, since we will need to for correct enum resolution in
140 // signals
142 // signals
141 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
143 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
142 if (!_objClassInfo || !_objClassInfo->isQObject()) {
144 if (!_objClassInfo || !_objClassInfo->isQObject()) {
143 PythonQt::self()->registerClass(obj->metaObject());
145 PythonQt::self()->registerClass(obj->metaObject());
144 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
146 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
145 }
147 }
146 // force decorator/enum creation
148 // force decorator/enum creation
147 _objClassInfo->decorator();
149 _objClassInfo->decorator();
148
150
149 _slotCount = staticMetaObject.methodOffset();
151 _slotCount = staticMetaObject.methodOffset();
150 }
152 }
151
153
152 PythonQtSignalReceiver::~PythonQtSignalReceiver()
154 PythonQtSignalReceiver::~PythonQtSignalReceiver()
153 {
155 {
154 PythonQt::priv()->removeSignalEmitter(_obj);
156 PythonQt::priv()->removeSignalEmitter(_obj);
155 }
157 }
156
158
157
159
158 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
160 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
159 {
161 {
160 bool flag = false;
162 bool flag = false;
161 int sigId = getSignalIndex(signal);
163 int sigId = getSignalIndex(signal);
162 if (sigId>=0) {
164 if (sigId>=0) {
163 // create PythonQtMethodInfo from signal
165 // create PythonQtMethodInfo from signal
164 QMetaMethod meta = _obj->metaObject()->method(sigId);
166 QMetaMethod meta = _obj->metaObject()->method(sigId);
165 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
167 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
166 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
168 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
167 _targets.append(t);
169 _targets.append(t);
168 // now connect to ourselves with the new slot id
170 // now connect to ourselves with the new slot id
169 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
171 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
170
172
171 _slotCount++;
173 _slotCount++;
172 flag = true;
174 flag = true;
173 }
175 }
174 return flag;
176 return flag;
175 }
177 }
176
178
177 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
179 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
178 {
180 {
179 bool found = false;
181 bool found = false;
180 int sigId = getSignalIndex(signal);
182 int sigId = getSignalIndex(signal);
181 if (sigId>=0) {
183 if (sigId>=0) {
182 QMutableListIterator<PythonQtSignalTarget> i(_targets);
184 QMutableListIterator<PythonQtSignalTarget> i(_targets);
183 while (i.hasNext()) {
185 while (i.hasNext()) {
184 if (i.next().isSame(sigId, callable)) {
186 if (i.next().isSame(sigId, callable)) {
185 i.remove();
187 i.remove();
186 found = true;
188 found = true;
187 break;
189 break;
188 }
190 }
189 }
191 }
190 }
192 }
191 return found;
193 return found;
192 }
194 }
193
195
194 void PythonQtSignalReceiver::removeSignalHandlers()
196 void PythonQtSignalReceiver::removeSignalHandlers()
195 {
197 {
196 _targets.clear();
198 _targets.clear();
197 }
199 }
198
200
199 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
201 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
200 {
202 {
201 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
203 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
202 if (sigId<0) {
204 if (sigId<0) {
203 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
205 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
204 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
206 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
205 }
207 }
206 return sigId;
208 return sigId;
207 }
209 }
208
210
209 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
211 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
210 {
212 {
211 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
213 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
212 if (c != QMetaObject::InvokeMetaMethod) {
214 if (c != QMetaObject::InvokeMetaMethod) {
213 QObject::qt_metacall(c, id, arguments);
215 QObject::qt_metacall(c, id, arguments);
214 }
216 }
215
217
216 bool found = false;
218 bool found = false;
217 foreach(const PythonQtSignalTarget& t, _targets) {
219 foreach(const PythonQtSignalTarget& t, _targets) {
218 if (t.slotId() == id) {
220 if (t.slotId() == id) {
219 found = true;
221 found = true;
220 t.call(arguments);
222 t.call(arguments);
221 break;
223 break;
222 }
224 }
223 }
225 }
224 return 0;
226 return 0;
225 }
227 }
226
228
@@ -1,141 +1,141
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 <Python.h>
45 #include <Python.h>
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include "PythonQtObjectPtr.h"
47 #include "PythonQtObjectPtr.h"
48
48
49 class PythonQtMethodInfo;
49 class PythonQtMethodInfo;
50 class PythonQtClassInfo;
50 class PythonQtClassInfo;
51
51
52 //! stores information about a signal target
52 //! stores information about a signal target
53 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
53 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 */
54 */
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 public:
56 public:
57 PythonQtSignalTarget() {
57 PythonQtSignalTarget() {
58 _signalId = -1;
58 _signalId = -1;
59 _methodInfo = NULL;
59 _methodInfo = NULL;
60 _slotId = -1;
60 _slotId = -1;
61 }
61 }
62
62
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 {
64 {
65 _signalId = signalId;
65 _signalId = signalId;
66 _slotId = slotId;
66 _slotId = slotId;
67 _methodInfo = methodInfo;
67 _methodInfo = methodInfo;
68 _callable = callable;
68 _callable = callable;
69 };
69 };
70
70
71 ~PythonQtSignalTarget() {
71 ~PythonQtSignalTarget() {
72 };
72 };
73
73
74 //! get the id of the original signal
74 //! get the id of the original signal
75 int signalId() const { return _signalId; }
75 int signalId() const { return _signalId; }
76
76
77 //! get the id that was assigned to this simulated slot
77 //! get the id that was assigned to this simulated slot
78 int slotId() const { return _slotId; }
78 int slotId() const { return _slotId; }
79
79
80 //! get the signals parameter info
80 //! get the signals parameter info
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82
82
83 //! call the python callable with the given arguments (as defined in methodInfo)
83 //! call the python callable with the given arguments (as defined in methodInfo)
84 void call(void **arguments) const;
84 void call(void **arguments) const;
85
85
86 //! check if it is the same signal target
86 //! check if it is the same signal target
87 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
87 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
88
88
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91
91
92 private:
92 private:
93 int _signalId;
93 int _signalId;
94 int _slotId;
94 int _slotId;
95 const PythonQtMethodInfo* _methodInfo;
95 const PythonQtMethodInfo* _methodInfo;
96 PythonQtObjectPtr _callable;
96 PythonQtObjectPtr _callable;
97 };
97 };
98
98
99 //! base class for signal receivers
99 //! base class for signal receivers
100 /*!
100 /*!
101 */
101 */
102 class PythonQtSignalReceiverBase : public QObject {
102 class PythonQtSignalReceiverBase : public QObject {
103 Q_OBJECT
103 Q_OBJECT
104 public:
104 public:
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 };
106 };
107
107
108 //! receives all signals for one QObject
108 //! receives all signals for one QObject
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 */
110 */
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112
112
113 public:
113 public:
114 PythonQtSignalReceiver(QObject* obj);
114 PythonQtSignalReceiver(QObject* obj);
115 ~PythonQtSignalReceiver();
115 ~PythonQtSignalReceiver();
116
116
117 //! add a signal handler
117 //! add a signal handler
118 bool addSignalHandler(const char* signal, PyObject* callable);
118 bool addSignalHandler(const char* signal, PyObject* callable);
119
119
120 //! remove a signal handler
120 //! remove a signal handler
121 bool removeSignalHandler(const char* signal, PyObject* callable);
121 bool removeSignalHandler(const char* signal, PyObject* callable);
122
122
123 //! remove all signal handlers
123 //! remove all signal handlers
124 void removeSignalHandlers();
124 void removeSignalHandlers();
125
125
126 //! we implement this method to simulate a number of slots that match the ids in _targets
126 //! we implement this method to simulate a number of slots that match the ids in _targets
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
128
128
129 private:
129 private:
130 //! get the index of the signal
130 //! get the index of the signal
131 int getSignalIndex(const char* signal);
131 int getSignalIndex(const char* signal);
132
132
133 QObject* _obj;
133 QObject* _obj;
134 PythonQtClassInfo* _objClassInfo;
134 PythonQtClassInfo* _objClassInfo;
135 int _slotCount;
135 int _slotCount;
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
137 QList<PythonQtSignalTarget> _targets;
137 QList<PythonQtSignalTarget> _targets;
138 };
138 };
139
139
140
140
141 #endif
141 #endif
@@ -1,509 +1,526
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 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
57 if (directReturnValuePointer) {
57 if (directReturnValuePointer) {
58 *directReturnValuePointer = NULL;
58 *directReturnValuePointer = NULL;
59 }
59 }
60 // store the current storage position, so that we can get back to this state after a slot is called
60 // store the current storage position, so that we can get back to this state after a slot is called
61 // (do this locally, so that we have all positions on the stack
61 // (do this locally, so that we have all positions on the stack
62 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalValueStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
68
68
69 recursiveEntry++;
69 recursiveEntry++;
70
70
71 // the arguments that are passed to qt_metacall
71 // the arguments that are passed to qt_metacall
72 void* argList[PYTHONQT_MAX_ARGS];
72 void* argList[PYTHONQT_MAX_ARGS];
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 int argc = info->parameterCount();
74 int argc = info->parameterCount();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
76
76
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
78 // set return argument to NULL
78 // set return argument to NULL
79 argList[0] = NULL;
79 argList[0] = NULL;
80
80
81 bool ok = true;
81 bool ok = true;
82 bool skipFirst = false;
82 bool skipFirst = false;
83 if (info->isInstanceDecorator()) {
83 if (info->isInstanceDecorator()) {
84 skipFirst = true;
84 skipFirst = true;
85
85
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
87 void* arg1 = firstArgument;
87 void* arg1 = firstArgument;
88 if (!arg1) {
88 if (!arg1) {
89 arg1 = objectToCall;
89 arg1 = objectToCall;
90 }
90 }
91 if (arg1) {
91 if (arg1) {
92 // upcast to correct parent class
92 // upcast to correct parent class
93 arg1 = ((char*)arg1)+info->upcastingOffset();
93 arg1 = ((char*)arg1)+info->upcastingOffset();
94 }
94 }
95
95
96 argList[1] = &arg1;
96 argList[1] = &arg1;
97 if (ok) {
97 if (ok) {
98 for (int i = 2; i<argc && ok; i++) {
98 for (int i = 2; i<argc && ok; i++) {
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
100 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
100 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
101 if (argList[i]==NULL) {
101 if (argList[i]==NULL) {
102 ok = false;
102 ok = false;
103 break;
103 break;
104 }
104 }
105 }
105 }
106 }
106 }
107 } else {
107 } else {
108 for (int i = 1; i<argc && ok; i++) {
108 for (int i = 1; i<argc && ok; i++) {
109 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
109 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
110 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
110 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
111 if (argList[i]==NULL) {
111 if (argList[i]==NULL) {
112 ok = false;
112 ok = false;
113 break;
113 break;
114 }
114 }
115 }
115 }
116 }
116 }
117
117
118 if (ok) {
118 if (ok) {
119 // parameters are ok, now create the qt return value which is assigned to by metacall
119 // parameters are ok, now create the qt return value which is assigned to by metacall
120 if (returnValueParam.typeId != QMetaType::Void) {
120 if (returnValueParam.typeId != QMetaType::Void) {
121 // create empty default value for the return value
121 // create empty default value for the return value
122 if (!directReturnValuePointer) {
122 if (!directReturnValuePointer) {
123 // create empty default value for the return value
123 // create empty default value for the return value
124 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
124 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
125 if (argList[0]==NULL) {
125 if (argList[0]==NULL) {
126 // 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
126 // 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
127 // pass its internal pointer
127 // pass its internal pointer
128 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
128 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
129 if (info && info->pythonQtClassWrapper()) {
129 if (info && info->pythonQtClassWrapper()) {
130 PyObject* emptyTuple = PyTuple_New(0);
130 PyObject* emptyTuple = PyTuple_New(0);
131 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
131 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
132 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
132 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
133 if (result) {
133 if (result) {
134 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
134 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
135 }
135 }
136 Py_DECREF(emptyTuple);
136 Py_DECREF(emptyTuple);
137 }
137 }
138 }
138 }
139 } else {
139 } else {
140 // we can use our pointer directly!
140 // we can use our pointer directly!
141 argList[0] = directReturnValuePointer;
141 argList[0] = directReturnValuePointer;
142 }
142 }
143 }
143 }
144
144
145
146 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
147 if (profilingCB) {
148 const char* className = NULL;
149 if (info->decorator()) {
150 className = info->decorator()->metaObject()->className();
151 } else {
152 className = objectToCall->metaObject()->className();
153 }
154
155 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
156 }
157
145 // invoke the slot via metacall
158 // invoke the slot via metacall
146 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
159 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
147
160
161 if (profilingCB) {
162 profilingCB(PythonQt::Leave, NULL, NULL);
163 }
164
148 // handle the return value (which in most cases still needs to be converted to a Python object)
165 // handle the return value (which in most cases still needs to be converted to a Python object)
149 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
166 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
150 if (directReturnValuePointer) {
167 if (directReturnValuePointer) {
151 result = NULL;
168 result = NULL;
152 } else {
169 } else {
153 // the resulting object maybe present already, because we created it above at 1)...
170 // the resulting object maybe present already, because we created it above at 1)...
154 if (!result) {
171 if (!result) {
155 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
172 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
156 }
173 }
157 }
174 }
158 } else {
175 } else {
159 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.";
176 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.";
160 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
177 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
161 result = NULL;
178 result = NULL;
162 }
179 }
163 }
180 }
164 recursiveEntry--;
181 recursiveEntry--;
165
182
166 // reset the parameter storage position to the stored pos to "pop" the parameter stack
183 // reset the parameter storage position to the stored pos to "pop" the parameter stack
167 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
184 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
168 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
185 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
169 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
186 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
170
187
171 *pythonReturnValue = result;
188 *pythonReturnValue = result;
172 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
189 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
173 return result || (directReturnValuePointer && *directReturnValuePointer);
190 return result || (directReturnValuePointer && *directReturnValuePointer);
174 }
191 }
175
192
176 //-----------------------------------------------------------------------------------
193 //-----------------------------------------------------------------------------------
177
194
178 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
195 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
179
196
180 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
197 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
181 {
198 {
182 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
199 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
183 PythonQtSlotInfo* info = f->m_ml;
200 PythonQtSlotInfo* info = f->m_ml;
184 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
201 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
185 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
202 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
186 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
203 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
187 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
204 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
188 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
205 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
189 return NULL;
206 return NULL;
190 } else {
207 } else {
191 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
208 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
192 }
209 }
193 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
210 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
194 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
211 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
195 if (info->isClassDecorator()) {
212 if (info->isClassDecorator()) {
196 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
213 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
197 } else {
214 } else {
198 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
215 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
199 Py_ssize_t argc = PyTuple_Size(args);
216 Py_ssize_t argc = PyTuple_Size(args);
200 if (argc>0) {
217 if (argc>0) {
201 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
218 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
202 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
219 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
203 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
220 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
204 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
221 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
205 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
222 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
206 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
223 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
207 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
224 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
208 return NULL;
225 return NULL;
209 }
226 }
210 // strip the first argument...
227 // strip the first argument...
211 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
228 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
212 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
229 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
213 Py_DECREF(newargs);
230 Py_DECREF(newargs);
214 return result;
231 return result;
215 } else {
232 } else {
216 // first arg is not of correct type!
233 // first arg is not of correct type!
217 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
234 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
218 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
235 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
219 return NULL;
236 return NULL;
220 }
237 }
221 } else {
238 } else {
222 // wrong number of args
239 // wrong number of args
223 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
240 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
224 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
241 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
225 return NULL;
242 return NULL;
226 }
243 }
227 }
244 }
228 }
245 }
229 return NULL;
246 return NULL;
230 }
247 }
231
248
232 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
249 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
233 {
250 {
234 int argc = args?PyTuple_Size(args):0;
251 int argc = args?PyTuple_Size(args):0;
235
252
236 #ifdef PYTHONQT_DEBUG
253 #ifdef PYTHONQT_DEBUG
237 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
254 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
238 #endif
255 #endif
239
256
240 PyObject* r = NULL;
257 PyObject* r = NULL;
241 bool ok = false;
258 bool ok = false;
242 if (directReturnValuePointer) {
259 if (directReturnValuePointer) {
243 *directReturnValuePointer = NULL;
260 *directReturnValuePointer = NULL;
244 }
261 }
245 if (info->nextInfo()) {
262 if (info->nextInfo()) {
246 // overloaded slot call, try on all slots with strict conversion first
263 // overloaded slot call, try on all slots with strict conversion first
247 bool strict = true;
264 bool strict = true;
248 PythonQtSlotInfo* i = info;
265 PythonQtSlotInfo* i = info;
249 while (i) {
266 while (i) {
250 bool skipFirst = i->isInstanceDecorator();
267 bool skipFirst = i->isInstanceDecorator();
251 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
268 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
252 PyErr_Clear();
269 PyErr_Clear();
253 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
270 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
254 if (PyErr_Occurred() || ok) break;
271 if (PyErr_Occurred() || ok) break;
255 }
272 }
256 i = i->nextInfo();
273 i = i->nextInfo();
257 if (!i) {
274 if (!i) {
258 if (strict) {
275 if (strict) {
259 // one more run without being strict
276 // one more run without being strict
260 strict = false;
277 strict = false;
261 i = info;
278 i = info;
262 }
279 }
263 }
280 }
264 }
281 }
265 if (!ok && !PyErr_Occurred()) {
282 if (!ok && !PyErr_Occurred()) {
266 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
283 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
267 PythonQtSlotInfo* i = info;
284 PythonQtSlotInfo* i = info;
268 while (i) {
285 while (i) {
269 e += QString(i->fullSignature()) + "\n";
286 e += QString(i->fullSignature()) + "\n";
270 i = i->nextInfo();
287 i = i->nextInfo();
271 }
288 }
272 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
289 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
273 }
290 }
274 } else {
291 } else {
275 // simple (non-overloaded) slot call
292 // simple (non-overloaded) slot call
276 bool skipFirst = info->isInstanceDecorator();
293 bool skipFirst = info->isInstanceDecorator();
277 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
294 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
278 PyErr_Clear();
295 PyErr_Clear();
279 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
296 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
280 if (!ok && !PyErr_Occurred()) {
297 if (!ok && !PyErr_Occurred()) {
281 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
298 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
282 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
299 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
283 }
300 }
284 } else {
301 } else {
285 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
302 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
286 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
303 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
287 }
304 }
288 }
305 }
289
306
290 return r;
307 return r;
291 }
308 }
292
309
293 PyObject *
310 PyObject *
294 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
311 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
295 {
312 {
296 PythonQtSlotFunctionObject *op;
313 PythonQtSlotFunctionObject *op;
297 op = pythonqtslot_free_list;
314 op = pythonqtslot_free_list;
298 if (op != NULL) {
315 if (op != NULL) {
299 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
316 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
300 PyObject_INIT(op, &PythonQtSlotFunction_Type);
317 PyObject_INIT(op, &PythonQtSlotFunction_Type);
301 }
318 }
302 else {
319 else {
303 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
320 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
304 if (op == NULL)
321 if (op == NULL)
305 return NULL;
322 return NULL;
306 }
323 }
307 op->m_ml = ml;
324 op->m_ml = ml;
308 Py_XINCREF(self);
325 Py_XINCREF(self);
309 op->m_self = self;
326 op->m_self = self;
310 Py_XINCREF(module);
327 Py_XINCREF(module);
311 op->m_module = module;
328 op->m_module = module;
312 PyObject_GC_Track(op);
329 PyObject_GC_Track(op);
313 return (PyObject *)op;
330 return (PyObject *)op;
314 }
331 }
315
332
316 PythonQtSlotInfo*
333 PythonQtSlotInfo*
317 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
334 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
318 {
335 {
319 if (!PythonQtSlotFunction_Check(op)) {
336 if (!PythonQtSlotFunction_Check(op)) {
320 PyErr_BadInternalCall();
337 PyErr_BadInternalCall();
321 return NULL;
338 return NULL;
322 }
339 }
323 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
340 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
324 }
341 }
325
342
326 PyObject *
343 PyObject *
327 PythonQtSlotFunction_GetSelf(PyObject *op)
344 PythonQtSlotFunction_GetSelf(PyObject *op)
328 {
345 {
329 if (!PythonQtSlotFunction_Check(op)) {
346 if (!PythonQtSlotFunction_Check(op)) {
330 PyErr_BadInternalCall();
347 PyErr_BadInternalCall();
331 return NULL;
348 return NULL;
332 }
349 }
333 return ((PythonQtSlotFunctionObject *)op) -> m_self;
350 return ((PythonQtSlotFunctionObject *)op) -> m_self;
334 }
351 }
335
352
336 /* Methods (the standard built-in methods, that is) */
353 /* Methods (the standard built-in methods, that is) */
337
354
338 static void
355 static void
339 meth_dealloc(PythonQtSlotFunctionObject *m)
356 meth_dealloc(PythonQtSlotFunctionObject *m)
340 {
357 {
341 PyObject_GC_UnTrack(m);
358 PyObject_GC_UnTrack(m);
342 Py_XDECREF(m->m_self);
359 Py_XDECREF(m->m_self);
343 Py_XDECREF(m->m_module);
360 Py_XDECREF(m->m_module);
344 m->m_self = (PyObject *)pythonqtslot_free_list;
361 m->m_self = (PyObject *)pythonqtslot_free_list;
345 pythonqtslot_free_list = m;
362 pythonqtslot_free_list = m;
346 }
363 }
347
364
348 static PyObject *
365 static PyObject *
349 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
366 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
350 {
367 {
351 Py_INCREF(Py_None);
368 Py_INCREF(Py_None);
352 return Py_None;
369 return Py_None;
353 }
370 }
354
371
355 static PyObject *
372 static PyObject *
356 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
373 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
357 {
374 {
358 return PyString_FromString(m->m_ml->metaMethod()->signature());
375 return PyString_FromString(m->m_ml->metaMethod()->signature());
359 }
376 }
360
377
361 static int
378 static int
362 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
379 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
363 {
380 {
364 int err;
381 int err;
365 if (m->m_self != NULL) {
382 if (m->m_self != NULL) {
366 err = visit(m->m_self, arg);
383 err = visit(m->m_self, arg);
367 if (err)
384 if (err)
368 return err;
385 return err;
369 }
386 }
370 if (m->m_module != NULL) {
387 if (m->m_module != NULL) {
371 err = visit(m->m_module, arg);
388 err = visit(m->m_module, arg);
372 if (err)
389 if (err)
373 return err;
390 return err;
374 }
391 }
375 return 0;
392 return 0;
376 }
393 }
377
394
378 static PyObject *
395 static PyObject *
379 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
396 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
380 {
397 {
381 PyObject *self;
398 PyObject *self;
382 if (PyEval_GetRestricted()) {
399 if (PyEval_GetRestricted()) {
383 PyErr_SetString(PyExc_RuntimeError,
400 PyErr_SetString(PyExc_RuntimeError,
384 "method.__self__ not accessible in restricted mode");
401 "method.__self__ not accessible in restricted mode");
385 return NULL;
402 return NULL;
386 }
403 }
387 self = m->m_self;
404 self = m->m_self;
388 if (self == NULL)
405 if (self == NULL)
389 self = Py_None;
406 self = Py_None;
390 Py_INCREF(self);
407 Py_INCREF(self);
391 return self;
408 return self;
392 }
409 }
393
410
394 static PyGetSetDef meth_getsets [] = {
411 static PyGetSetDef meth_getsets [] = {
395 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
412 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
396 {"__name__", (getter)meth_get__name__, NULL, NULL},
413 {"__name__", (getter)meth_get__name__, NULL, NULL},
397 {"__self__", (getter)meth_get__self__, NULL, NULL},
414 {"__self__", (getter)meth_get__self__, NULL, NULL},
398 {NULL, NULL, NULL,NULL},
415 {NULL, NULL, NULL,NULL},
399 };
416 };
400
417
401 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
418 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
402 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
419 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
403 #endif
420 #endif
404
421
405 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
422 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
406
423
407 static PyMemberDef meth_members[] = {
424 static PyMemberDef meth_members[] = {
408 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
425 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
409 {NULL}
426 {NULL}
410 };
427 };
411
428
412 static PyObject *
429 static PyObject *
413 meth_repr(PythonQtSlotFunctionObject *f)
430 meth_repr(PythonQtSlotFunctionObject *f)
414 {
431 {
415 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
432 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
416 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
433 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
417 return PyString_FromFormat("<unbound qt slot %s of %s type>",
434 return PyString_FromFormat("<unbound qt slot %s of %s type>",
418 f->m_ml->slotName().data(),
435 f->m_ml->slotName().data(),
419 self->classInfo()->className());
436 self->classInfo()->className());
420 } else {
437 } else {
421 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
438 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
422 f->m_ml->slotName().data(),
439 f->m_ml->slotName().data(),
423 f->m_self->ob_type->tp_name,
440 f->m_self->ob_type->tp_name,
424 f->m_self);
441 f->m_self);
425 }
442 }
426 }
443 }
427
444
428 static int
445 static int
429 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
446 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
430 {
447 {
431 if (a->m_self != b->m_self)
448 if (a->m_self != b->m_self)
432 return (a->m_self < b->m_self) ? -1 : 1;
449 return (a->m_self < b->m_self) ? -1 : 1;
433 if (a->m_ml == b->m_ml)
450 if (a->m_ml == b->m_ml)
434 return 0;
451 return 0;
435 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
452 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
436 return -1;
453 return -1;
437 else
454 else
438 return 1;
455 return 1;
439 }
456 }
440
457
441 static long
458 static long
442 meth_hash(PythonQtSlotFunctionObject *a)
459 meth_hash(PythonQtSlotFunctionObject *a)
443 {
460 {
444 long x,y;
461 long x,y;
445 if (a->m_self == NULL)
462 if (a->m_self == NULL)
446 x = 0;
463 x = 0;
447 else {
464 else {
448 x = PyObject_Hash(a->m_self);
465 x = PyObject_Hash(a->m_self);
449 if (x == -1)
466 if (x == -1)
450 return -1;
467 return -1;
451 }
468 }
452 y = _Py_HashPointer((void*)(a->m_ml));
469 y = _Py_HashPointer((void*)(a->m_ml));
453 if (y == -1)
470 if (y == -1)
454 return -1;
471 return -1;
455 x ^= y;
472 x ^= y;
456 if (x == -1)
473 if (x == -1)
457 x = -2;
474 x = -2;
458 return x;
475 return x;
459 }
476 }
460
477
461
478
462 PyTypeObject PythonQtSlotFunction_Type = {
479 PyTypeObject PythonQtSlotFunction_Type = {
463 PyObject_HEAD_INIT(&PyType_Type)
480 PyObject_HEAD_INIT(&PyType_Type)
464 0,
481 0,
465 "builtin_qt_slot",
482 "builtin_qt_slot",
466 sizeof(PythonQtSlotFunctionObject),
483 sizeof(PythonQtSlotFunctionObject),
467 0,
484 0,
468 (destructor)meth_dealloc, /* tp_dealloc */
485 (destructor)meth_dealloc, /* tp_dealloc */
469 0, /* tp_print */
486 0, /* tp_print */
470 0, /* tp_getattr */
487 0, /* tp_getattr */
471 0, /* tp_setattr */
488 0, /* tp_setattr */
472 (cmpfunc)meth_compare, /* tp_compare */
489 (cmpfunc)meth_compare, /* tp_compare */
473 (reprfunc)meth_repr, /* tp_repr */
490 (reprfunc)meth_repr, /* tp_repr */
474 0, /* tp_as_number */
491 0, /* tp_as_number */
475 0, /* tp_as_sequence */
492 0, /* tp_as_sequence */
476 0, /* tp_as_mapping */
493 0, /* tp_as_mapping */
477 (hashfunc)meth_hash, /* tp_hash */
494 (hashfunc)meth_hash, /* tp_hash */
478 PythonQtSlotFunction_Call, /* tp_call */
495 PythonQtSlotFunction_Call, /* tp_call */
479 0, /* tp_str */
496 0, /* tp_str */
480 PyObject_GenericGetAttr, /* tp_getattro */
497 PyObject_GenericGetAttr, /* tp_getattro */
481 0, /* tp_setattro */
498 0, /* tp_setattro */
482 0, /* tp_as_buffer */
499 0, /* tp_as_buffer */
483 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
500 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
484 0, /* tp_doc */
501 0, /* tp_doc */
485 (traverseproc)meth_traverse, /* tp_traverse */
502 (traverseproc)meth_traverse, /* tp_traverse */
486 0, /* tp_clear */
503 0, /* tp_clear */
487 0, /* tp_richcompare */
504 0, /* tp_richcompare */
488 0, /* tp_weaklistoffset */
505 0, /* tp_weaklistoffset */
489 0, /* tp_iter */
506 0, /* tp_iter */
490 0, /* tp_iternext */
507 0, /* tp_iternext */
491 0, /* tp_methods */
508 0, /* tp_methods */
492 meth_members, /* tp_members */
509 meth_members, /* tp_members */
493 meth_getsets, /* tp_getset */
510 meth_getsets, /* tp_getset */
494 0, /* tp_base */
511 0, /* tp_base */
495 0, /* tp_dict */
512 0, /* tp_dict */
496 };
513 };
497
514
498 /* Clear out the free list */
515 /* Clear out the free list */
499
516
500 void
517 void
501 PythonQtSlotFunction_Fini(void)
518 PythonQtSlotFunction_Fini(void)
502 {
519 {
503 while (pythonqtslot_free_list) {
520 while (pythonqtslot_free_list) {
504 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
521 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
505 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
522 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
506 PyObject_GC_Del(v);
523 PyObject_GC_Del(v);
507 }
524 }
508 }
525 }
509
526
@@ -1,314 +1,305
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 QByteArray signalTmp;
49 QByteArray signalTmp;
50 char first = signal.at(0);
50 char first = signal.at(0);
51 if (first>='0' && first<='9') {
51 if (first>='0' && first<='9') {
52 signalTmp = signal;
52 signalTmp = signal;
53 } else {
53 } else {
54 signalTmp = "2" + signal;
54 signalTmp = "2" + signal;
55 }
55 }
56
56
57 if (sender) {
57 if (sender) {
58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
59 } else {
59 } else {
60 return false;
60 return false;
61 }
61 }
62 }
62 }
63
63
64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
65 {
65 {
66 bool r = false;
66 bool r = false;
67 if (sender && receiver) {
67 if (sender && receiver) {
68 QByteArray signalTmp;
68 QByteArray signalTmp;
69 char first = signal.at(0);
69 char first = signal.at(0);
70 if (first>='0' && first<='9') {
70 if (first>='0' && first<='9') {
71 signalTmp = signal;
71 signalTmp = signal;
72 } else {
72 } else {
73 signalTmp = "2" + signal;
73 signalTmp = "2" + signal;
74 }
74 }
75
75
76 QByteArray slotTmp;
76 QByteArray slotTmp;
77 first = slot.at(0);
77 first = slot.at(0);
78 if (first>='0' && first<='9') {
78 if (first>='0' && first<='9') {
79 slotTmp = slot;
79 slotTmp = slot;
80 } else {
80 } else {
81 slotTmp = "1" + slot;
81 slotTmp = "1" + slot;
82 }
82 }
83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
84 }
84 }
85 return r;
85 return r;
86 }
86 }
87
87
88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
89 {
89 {
90 QByteArray signalTmp;
90 QByteArray signalTmp;
91 char first = signal.at(0);
91 char first = signal.at(0);
92 if (first>='0' && first<='9') {
92 if (first>='0' && first<='9') {
93 signalTmp = signal;
93 signalTmp = signal;
94 } else {
94 } else {
95 signalTmp = "2" + signal;
95 signalTmp = "2" + signal;
96 }
96 }
97 if (sender) {
97 if (sender) {
98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
99 } else {
99 } else {
100 return false;
100 return false;
101 }
101 }
102 }
102 }
103
103
104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
105 {
105 {
106 bool r = false;
106 bool r = false;
107 if (sender && receiver) {
107 if (sender && receiver) {
108 QByteArray signalTmp;
108 QByteArray signalTmp;
109 char first = signal.at(0);
109 char first = signal.at(0);
110 if (first>='0' && first<='9') {
110 if (first>='0' && first<='9') {
111 signalTmp = signal;
111 signalTmp = signal;
112 } else {
112 } else {
113 signalTmp = "2" + signal;
113 signalTmp = "2" + signal;
114 }
114 }
115
115
116 QByteArray slotTmp;
116 QByteArray slotTmp;
117 first = slot.at(0);
117 first = slot.at(0);
118 if (first>='0' && first<='9') {
118 if (first>='0' && first<='9') {
119 slotTmp = slot;
119 slotTmp = slot;
120 } else {
120 } else {
121 slotTmp = "1" + slot;
121 slotTmp = "1" + slot;
122 }
122 }
123
123
124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
125 }
125 }
126 return r;
126 return r;
127 }
127 }
128
128
129 #undef emit
130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
132 {
133 // TODO xxx
134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
135 }
136 #define emit
137
138 QObject* PythonQtStdDecorators::parent(QObject* o) {
129 QObject* PythonQtStdDecorators::parent(QObject* o) {
139 return o->parent();
130 return o->parent();
140 }
131 }
141
132
142 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
133 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
143 {
134 {
144 o->setParent(parent);
135 o->setParent(parent);
145 }
136 }
146
137
147 const QObjectList* PythonQtStdDecorators::children(QObject* o)
138 const QObjectList* PythonQtStdDecorators::children(QObject* o)
148 {
139 {
149 return &o->children();
140 return &o->children();
150 }
141 }
151
142
152 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
143 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
153 {
144 {
154 return o->setProperty(name, value);
145 return o->setProperty(name, value);
155 }
146 }
156
147
157 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
148 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
158 {
149 {
159 return o->property(name);
150 return o->property(name);
160 }
151 }
161
152
162 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
153 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
163 {
154 {
164 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
155 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
165 }
156 }
166
157
167 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
158 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
168 {
159 {
169 const QMetaObject* meta = NULL;
160 const QMetaObject* meta = NULL;
170 const char* typeName = NULL;
161 const char* typeName = NULL;
171
162
172 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
163 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
173 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
164 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
174 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
165 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
175 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
166 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
176 } else if (PyString_Check(type)) {
167 } else if (PyString_Check(type)) {
177 typeName = PyString_AsString(type);
168 typeName = PyString_AsString(type);
178 }
169 }
179
170
180 if (!typeName && !meta)
171 if (!typeName && !meta)
181 return NULL;
172 return NULL;
182
173
183 return findChild(parent, typeName, meta, name);
174 return findChild(parent, typeName, meta, name);
184 }
175 }
185
176
186 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
177 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
187 {
178 {
188 const QMetaObject* meta = NULL;
179 const QMetaObject* meta = NULL;
189 const char* typeName = NULL;
180 const char* typeName = NULL;
190
181
191 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
182 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
192 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
183 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
193 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
184 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
194 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
185 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
195 } else if (PyString_Check(type)) {
186 } else if (PyString_Check(type)) {
196 typeName = PyString_AsString(type);
187 typeName = PyString_AsString(type);
197 }
188 }
198
189
199 QList<QObject*> list;
190 QList<QObject*> list;
200
191
201 if (!typeName && !meta)
192 if (!typeName && !meta)
202 return list;
193 return list;
203
194
204 findChildren(parent, typeName, meta, name, list);
195 findChildren(parent, typeName, meta, name, list);
205
196
206 return list;
197 return list;
207 }
198 }
208
199
209 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
200 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
210 {
201 {
211 const QMetaObject* meta = NULL;
202 const QMetaObject* meta = NULL;
212 const char* typeName = NULL;
203 const char* typeName = NULL;
213
204
214 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
205 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
215 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
206 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
216 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
207 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
217 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
208 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
218 } else if (PyString_Check(type)) {
209 } else if (PyString_Check(type)) {
219 typeName = PyString_AsString(type);
210 typeName = PyString_AsString(type);
220 }
211 }
221
212
222 QList<QObject*> list;
213 QList<QObject*> list;
223
214
224 if (!typeName && !meta)
215 if (!typeName && !meta)
225 return list;
216 return list;
226
217
227 findChildren(parent, typeName, meta, regExp, list);
218 findChildren(parent, typeName, meta, regExp, list);
228
219
229 return list;
220 return list;
230 }
221 }
231
222
232 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
223 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
233 {
224 {
234 const QObjectList &children = parent->children();
225 const QObjectList &children = parent->children();
235
226
236 int i;
227 int i;
237 for (i = 0; i < children.size(); ++i) {
228 for (i = 0; i < children.size(); ++i) {
238 QObject* obj = children.at(i);
229 QObject* obj = children.at(i);
239
230
240 if (!obj)
231 if (!obj)
241 return NULL;
232 return NULL;
242
233
243 // Skip if the name doesn't match.
234 // Skip if the name doesn't match.
244 if (!name.isNull() && obj->objectName() != name)
235 if (!name.isNull() && obj->objectName() != name)
245 continue;
236 continue;
246
237
247 if ((typeName && obj->inherits(typeName)) ||
238 if ((typeName && obj->inherits(typeName)) ||
248 (meta && meta->cast(obj)))
239 (meta && meta->cast(obj)))
249 return obj;
240 return obj;
250 }
241 }
251
242
252 for (i = 0; i < children.size(); ++i) {
243 for (i = 0; i < children.size(); ++i) {
253 QObject* obj = findChild(children.at(i), typeName, meta, name);
244 QObject* obj = findChild(children.at(i), typeName, meta, name);
254
245
255 if (obj != NULL)
246 if (obj != NULL)
256 return obj;
247 return obj;
257 }
248 }
258
249
259 return NULL;
250 return NULL;
260 }
251 }
261
252
262 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
253 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
263 {
254 {
264 const QObjectList& children = parent->children();
255 const QObjectList& children = parent->children();
265 int i;
256 int i;
266
257
267 for (i = 0; i < children.size(); ++i) {
258 for (i = 0; i < children.size(); ++i) {
268 QObject* obj = children.at(i);
259 QObject* obj = children.at(i);
269
260
270 if (!obj)
261 if (!obj)
271 return -1;
262 return -1;
272
263
273 // Skip if the name doesn't match.
264 // Skip if the name doesn't match.
274 if (!name.isNull() && obj->objectName() != name)
265 if (!name.isNull() && obj->objectName() != name)
275 continue;
266 continue;
276
267
277 if ((typeName && obj->inherits(typeName)) ||
268 if ((typeName && obj->inherits(typeName)) ||
278 (meta && meta->cast(obj))) {
269 (meta && meta->cast(obj))) {
279 list += obj;
270 list += obj;
280 }
271 }
281
272
282 if (findChildren(obj, typeName, meta, name, list) < 0)
273 if (findChildren(obj, typeName, meta, name, list) < 0)
283 return -1;
274 return -1;
284 }
275 }
285
276
286 return 0;
277 return 0;
287 }
278 }
288
279
289 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
280 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
290 {
281 {
291 const QObjectList& children = parent->children();
282 const QObjectList& children = parent->children();
292 int i;
283 int i;
293
284
294 for (i = 0; i < children.size(); ++i) {
285 for (i = 0; i < children.size(); ++i) {
295 QObject* obj = children.at(i);
286 QObject* obj = children.at(i);
296
287
297 if (!obj)
288 if (!obj)
298 return -1;
289 return -1;
299
290
300 // Skip if the name doesn't match.
291 // Skip if the name doesn't match.
301 if (regExp.indexIn(obj->objectName()) == -1)
292 if (regExp.indexIn(obj->objectName()) == -1)
302 continue;
293 continue;
303
294
304 if ((typeName && obj->inherits(typeName)) ||
295 if ((typeName && obj->inherits(typeName)) ||
305 (meta && meta->cast(obj))) {
296 (meta && meta->cast(obj))) {
306 list += obj;
297 list += obj;
307 }
298 }
308
299
309 if (findChildren(obj, typeName, meta, regExp, list) < 0)
300 if (findChildren(obj, typeName, meta, regExp, list) < 0)
310 return -1;
301 return -1;
311 }
302 }
312
303
313 return 0;
304 return 0;
314 }
305 }
@@ -1,112 +1,107
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 "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include <Python.h>
46 #include <Python.h>
47 #include <QObject>
47 #include <QObject>
48 #include <QVariantList>
48 #include <QVariantList>
49 #include <QTextDocument>
49 #include <QTextDocument>
50 #include <QColor>
50 #include <QColor>
51 #include <QDateTime>
51 #include <QDateTime>
52 #include <QDate>
52 #include <QDate>
53 #include <QTime>
53 #include <QTime>
54
54
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
56 {
56 {
57 Q_OBJECT
57 Q_OBJECT
58
58
59 public slots:
59 public slots:
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64
64
65 #undef emit
66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
68 #define emit
69
70 QObject* parent(QObject* o);
65 QObject* parent(QObject* o);
71 void setParent(QObject* o, QObject* parent);
66 void setParent(QObject* o, QObject* parent);
72
67
73 const QObjectList* children(QObject* o);
68 const QObjectList* children(QObject* o);
74 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
69 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
75 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
70 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
76 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
71 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
77
72
78 bool setProperty(QObject* o, const char* name, const QVariant& value);
73 bool setProperty(QObject* o, const char* name, const QVariant& value);
79 QVariant property(QObject* o, const char* name);
74 QVariant property(QObject* o, const char* name);
80
75
81 double static_Qt_qAbs(double a) { return qAbs(a); }
76 double static_Qt_qAbs(double a) { return qAbs(a); }
82 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
77 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
83 void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }
78 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
84 // TODO: multi arg qDebug...
79 // TODO: multi arg qDebug...
85 void static_Qt_qWarning(const QByteArray& msg) { qWarning(msg.constData()); }
80 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
86 // TODO: multi arg qWarning...
81 // TODO: multi arg qWarning...
87 void static_Qt_qCritical(const QByteArray& msg) { qCritical(msg.constData()); }
82 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
88 // TODO: multi arg qCritical...
83 // TODO: multi arg qCritical...
89 void static_Qt_qFatal(const QByteArray& msg) { qFatal(msg.constData()); }
84 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
90 // TODO: multi arg qFatal...
85 // TODO: multi arg qFatal...
91 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
86 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
92 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
87 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
93 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
88 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
94 int static_Qt_qRound(double a) { return qRound(a); }
89 int static_Qt_qRound(double a) { return qRound(a); }
95 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
90 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
96 const char* static_Qt_qVersion() { return qVersion(); }
91 const char* static_Qt_qVersion() { return qVersion(); }
97 int static_Qt_qrand() { return qrand(); }
92 int static_Qt_qrand() { return qrand(); }
98 void static_Qt_qsrand(uint a) { qsrand(a); }
93 void static_Qt_qsrand(uint a) { qsrand(a); }
99
94
100 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
95 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
101
96
102 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
97 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
103 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
98 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
104
99
105 private:
100 private:
106 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
101 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
107 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
102 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
108 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
103 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
109 };
104 };
110
105
111
106
112 #endif
107 #endif
General Comments 0
You need to be logged in to leave comments. Login now