##// END OF EJS Templates
fixed support for more than one * indirection via pointerCount, QPixmap crashed on char** constructor, which was thought to be * only...
florianlink -
r134:1fceea800edd
parent child
Show More
@@ -1,1220 +1,1220
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 Py_SetProgramName("PythonQt");
152 Py_SetProgramName("PythonQt");
153 if (flags & IgnoreSiteModule) {
153 if (flags & IgnoreSiteModule) {
154 // this prevents the automatic importing of Python site files
154 // this prevents the automatic importing of Python site files
155 Py_NoSiteFlag = 1;
155 Py_NoSiteFlag = 1;
156 }
156 }
157 Py_Initialize();
157 Py_Initialize();
158
158
159 // add our own python object types for qt object slots
159 // add our own python object types for qt object slots
160 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
160 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
161 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
161 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
162 }
162 }
163 Py_INCREF(&PythonQtSlotFunction_Type);
163 Py_INCREF(&PythonQtSlotFunction_Type);
164
164
165 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
165 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
166 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
166 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
167 // add our own python object types for classes
167 // add our own python object types for classes
168 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
168 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
169 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
169 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 }
170 }
171 Py_INCREF(&PythonQtClassWrapper_Type);
171 Py_INCREF(&PythonQtClassWrapper_Type);
172
172
173 // add our own python object types for CPP instances
173 // add our own python object types for CPP instances
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
175 PythonQt::handleError();
175 PythonQt::handleError();
176 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
176 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 }
177 }
178 Py_INCREF(&PythonQtInstanceWrapper_Type);
178 Py_INCREF(&PythonQtInstanceWrapper_Type);
179
179
180 // add our own python object types for redirection of stdout
180 // add our own python object types for redirection of stdout
181 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
181 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
182 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
183 }
183 }
184 Py_INCREF(&PythonQtStdOutRedirectType);
184 Py_INCREF(&PythonQtStdOutRedirectType);
185
185
186 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
186 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
187
187
188 _p->setupSharedLibrarySuffixes();
188 _p->setupSharedLibrarySuffixes();
189
189
190 }
190 }
191
191
192 PythonQt::~PythonQt() {
192 PythonQt::~PythonQt() {
193 delete _p;
193 delete _p;
194 _p = NULL;
194 _p = NULL;
195 }
195 }
196
196
197 PythonQtPrivate::~PythonQtPrivate() {
197 PythonQtPrivate::~PythonQtPrivate() {
198 delete _defaultImporter;
198 delete _defaultImporter;
199 _defaultImporter = NULL;
199 _defaultImporter = NULL;
200
200
201 {
201 {
202 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
202 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
203 while (i.hasNext()) {
203 while (i.hasNext()) {
204 delete i.next().value();
204 delete i.next().value();
205 }
205 }
206 }
206 }
207 PythonQtConv::global_valueStorage.clear();
207 PythonQtConv::global_valueStorage.clear();
208 PythonQtConv::global_ptrStorage.clear();
208 PythonQtConv::global_ptrStorage.clear();
209 PythonQtConv::global_variantStorage.clear();
209 PythonQtConv::global_variantStorage.clear();
210
210
211 PythonQtMethodInfo::cleanupCachedMethodInfos();
211 PythonQtMethodInfo::cleanupCachedMethodInfos();
212 }
212 }
213
213
214 PythonQtImportFileInterface* PythonQt::importInterface()
214 PythonQtImportFileInterface* PythonQt::importInterface()
215 {
215 {
216 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
216 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
217 }
217 }
218
218
219 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
219 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
220 {
220 {
221 if (_self->_p->_noLongerWrappedCB) {
221 if (_self->_p->_noLongerWrappedCB) {
222 (*_self->_p->_noLongerWrappedCB)(o);
222 (*_self->_p->_noLongerWrappedCB)(o);
223 };
223 };
224 }
224 }
225
225
226 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
226 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
227 {
227 {
228 _p->registerClass(metaobject, package, wrapperCreator, shell);
228 _p->registerClass(metaobject, package, wrapperCreator, shell);
229 }
229 }
230
230
231 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
231 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
232 {
232 {
233 // we register all classes in the hierarchy
233 // we register all classes in the hierarchy
234 const QMetaObject* m = metaobject;
234 const QMetaObject* m = metaobject;
235 bool first = true;
235 bool first = true;
236 while (m) {
236 while (m) {
237 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
237 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
238 if (!info->pythonQtClassWrapper()) {
238 if (!info->pythonQtClassWrapper()) {
239 info->setTypeSlots(typeSlots);
239 info->setTypeSlots(typeSlots);
240 info->setupQObject(m);
240 info->setupQObject(m);
241 createPythonQtClassWrapper(info, package, module);
241 createPythonQtClassWrapper(info, package, module);
242 if (m->superClass()) {
242 if (m->superClass()) {
243 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
243 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
244 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
244 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
245 }
245 }
246 }
246 }
247 if (first) {
247 if (first) {
248 first = false;
248 first = false;
249 if (wrapperCreator) {
249 if (wrapperCreator) {
250 info->setDecoratorProvider(wrapperCreator);
250 info->setDecoratorProvider(wrapperCreator);
251 }
251 }
252 if (shell) {
252 if (shell) {
253 info->setShellSetInstanceWrapperCB(shell);
253 info->setShellSetInstanceWrapperCB(shell);
254 }
254 }
255 }
255 }
256 m = m->superClass();
256 m = m->superClass();
257 }
257 }
258 }
258 }
259
259
260 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
260 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
261 {
261 {
262 PyObject* pack = module?module:packageByName(package);
262 PyObject* pack = module?module:packageByName(package);
263 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
263 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
264 PyModule_AddObject(pack, info->className(), pyobj);
264 PyModule_AddObject(pack, info->className(), pyobj);
265 if (!module && package && strncmp(package,"Qt",2)==0) {
265 if (!module && package && strncmp(package,"Qt",2)==0) {
266 // since PyModule_AddObject steals the reference, we need a incref once more...
266 // since PyModule_AddObject steals the reference, we need a incref once more...
267 Py_INCREF(pyobj);
267 Py_INCREF(pyobj);
268 // put all qt objects into Qt as well
268 // put all qt objects into Qt as well
269 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
269 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
270 }
270 }
271 info->setPythonQtClassWrapper(pyobj);
271 info->setPythonQtClassWrapper(pyobj);
272 }
272 }
273
273
274 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
274 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
275 {
275 {
276 if (!obj) {
276 if (!obj) {
277 Py_INCREF(Py_None);
277 Py_INCREF(Py_None);
278 return Py_None;
278 return Py_None;
279 }
279 }
280 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
280 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
281 if (!wrap) {
281 if (!wrap) {
282 // smuggling it in...
282 // smuggling it in...
283 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
283 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
284 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
284 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
285 registerClass(obj->metaObject());
285 registerClass(obj->metaObject());
286 classInfo = _knownClassInfos.value(obj->metaObject()->className());
286 classInfo = _knownClassInfos.value(obj->metaObject()->className());
287 }
287 }
288 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
288 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
289 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
289 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
290 } else {
290 } else {
291 Py_INCREF(wrap);
291 Py_INCREF(wrap);
292 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
292 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
293 }
293 }
294 return (PyObject*)wrap;
294 return (PyObject*)wrap;
295 }
295 }
296
296
297 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
297 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
298 {
298 {
299 if (!ptr) {
299 if (!ptr) {
300 Py_INCREF(Py_None);
300 Py_INCREF(Py_None);
301 return Py_None;
301 return Py_None;
302 }
302 }
303
303
304 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
304 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
305 if (!wrap) {
305 if (!wrap) {
306 PythonQtClassInfo* info = _knownClassInfos.value(name);
306 PythonQtClassInfo* info = _knownClassInfos.value(name);
307 if (!info) {
307 if (!info) {
308 // maybe it is a PyObject, which we can return directly
308 // maybe it is a PyObject, which we can return directly
309 if (name == "PyObject") {
309 if (name == "PyObject") {
310 PyObject* p = (PyObject*)ptr;
310 PyObject* p = (PyObject*)ptr;
311 Py_INCREF(p);
311 Py_INCREF(p);
312 return p;
312 return p;
313 }
313 }
314
314
315 // we do not know the metaobject yet, but we might know it by it's name:
315 // we do not know the metaobject yet, but we might know it by it's name:
316 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
316 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
317 // yes, we know it, so we can convert to QObject
317 // yes, we know it, so we can convert to QObject
318 QObject* qptr = (QObject*)ptr;
318 QObject* qptr = (QObject*)ptr;
319 registerClass(qptr->metaObject());
319 registerClass(qptr->metaObject());
320 info = _knownClassInfos.value(qptr->metaObject()->className());
320 info = _knownClassInfos.value(qptr->metaObject()->className());
321 }
321 }
322 }
322 }
323 if (info && info->isQObject()) {
323 if (info && info->isQObject()) {
324 QObject* qptr = (QObject*)ptr;
324 QObject* qptr = (QObject*)ptr;
325 // if the object is a derived object, we want to switch the class info to the one of the derived class:
325 // if the object is a derived object, we want to switch the class info to the one of the derived class:
326 if (name!=(qptr->metaObject()->className())) {
326 if (name!=(qptr->metaObject()->className())) {
327 registerClass(qptr->metaObject());
327 registerClass(qptr->metaObject());
328 info = _knownClassInfos.value(qptr->metaObject()->className());
328 info = _knownClassInfos.value(qptr->metaObject()->className());
329 }
329 }
330 wrap = createNewPythonQtInstanceWrapper(qptr, info);
330 wrap = createNewPythonQtInstanceWrapper(qptr, info);
331 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
331 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
332 return (PyObject*)wrap;
332 return (PyObject*)wrap;
333 }
333 }
334
334
335 // not a known QObject, so try our wrapper factory:
335 // not a known QObject, so try our wrapper factory:
336 QObject* wrapper = NULL;
336 QObject* wrapper = NULL;
337 for (int i=0; i<_cppWrapperFactories.size(); i++) {
337 for (int i=0; i<_cppWrapperFactories.size(); i++) {
338 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
338 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
339 if (wrapper) {
339 if (wrapper) {
340 break;
340 break;
341 }
341 }
342 }
342 }
343
343
344 if (info) {
344 if (info) {
345 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
345 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
346 ptr = info->castDownIfPossible(ptr, &info);
346 ptr = info->castDownIfPossible(ptr, &info);
347 }
347 }
348
348
349 if (!info || info->pythonQtClassWrapper()==NULL) {
349 if (!info || info->pythonQtClassWrapper()==NULL) {
350 // still unknown, register as CPP class
350 // still unknown, register as CPP class
351 registerCPPClass(name.constData());
351 registerCPPClass(name.constData());
352 info = _knownClassInfos.value(name);
352 info = _knownClassInfos.value(name);
353 }
353 }
354 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
354 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
355 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
355 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
356 info->setMetaObject(wrapper->metaObject());
356 info->setMetaObject(wrapper->metaObject());
357 }
357 }
358 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
358 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
359 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
359 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
360 } else {
360 } else {
361 Py_INCREF(wrap);
361 Py_INCREF(wrap);
362 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
362 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
363 }
363 }
364 return (PyObject*)wrap;
364 return (PyObject*)wrap;
365 }
365 }
366
366
367 PyObject* PythonQtPrivate::dummyTuple() {
367 PyObject* PythonQtPrivate::dummyTuple() {
368 static PyObject* dummyTuple = NULL;
368 static PyObject* dummyTuple = NULL;
369 if (dummyTuple==NULL) {
369 if (dummyTuple==NULL) {
370 dummyTuple = PyTuple_New(1);
370 dummyTuple = PyTuple_New(1);
371 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
371 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
372 }
372 }
373 return dummyTuple;
373 return dummyTuple;
374 }
374 }
375
375
376
376
377 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
377 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
378 // call the associated class type to create a new instance...
378 // call the associated class type to create a new instance...
379 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
379 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
380
380
381 result->setQObject(obj);
381 result->setQObject(obj);
382 result->_wrappedPtr = wrappedPtr;
382 result->_wrappedPtr = wrappedPtr;
383 result->_ownedByPythonQt = false;
383 result->_ownedByPythonQt = false;
384 result->_useQMetaTypeDestroy = false;
384 result->_useQMetaTypeDestroy = false;
385
385
386 if (wrappedPtr) {
386 if (wrappedPtr) {
387 _wrappedObjects.insert(wrappedPtr, result);
387 _wrappedObjects.insert(wrappedPtr, result);
388 } else {
388 } else {
389 _wrappedObjects.insert(obj, result);
389 _wrappedObjects.insert(obj, result);
390 if (obj->parent()== NULL && _wrappedCB) {
390 if (obj->parent()== NULL && _wrappedCB) {
391 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
391 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
392 (*_wrappedCB)(obj);
392 (*_wrappedCB)(obj);
393 }
393 }
394 }
394 }
395 return result;
395 return result;
396 }
396 }
397
397
398 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
398 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
399 PythonQtClassWrapper* result;
399 PythonQtClassWrapper* result;
400
400
401 PyObject* className = PyString_FromString(info->className());
401 PyObject* className = PyString_FromString(info->className());
402
402
403 PyObject* baseClasses = PyTuple_New(1);
403 PyObject* baseClasses = PyTuple_New(1);
404 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
404 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
405
405
406 PyObject* typeDict = PyDict_New();
406 PyObject* typeDict = PyDict_New();
407 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
407 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
408 PyDict_SetItemString(typeDict, "__module__", moduleName);
408 PyDict_SetItemString(typeDict, "__module__", moduleName);
409
409
410 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
410 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
411
411
412 // set the class info so that PythonQtClassWrapper_new can read it
412 // set the class info so that PythonQtClassWrapper_new can read it
413 _currentClassInfoForClassWrapperCreation = info;
413 _currentClassInfoForClassWrapperCreation = info;
414 // create the new type object by calling the type
414 // create the new type object by calling the type
415 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
415 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
416
416
417 Py_DECREF(baseClasses);
417 Py_DECREF(baseClasses);
418 Py_DECREF(typeDict);
418 Py_DECREF(typeDict);
419 Py_DECREF(args);
419 Py_DECREF(args);
420 Py_DECREF(className);
420 Py_DECREF(className);
421
421
422 return result;
422 return result;
423 }
423 }
424
424
425 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
425 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
426 {
426 {
427 PyObject* args = Py_BuildValue("(i)", enumValue);
427 PyObject* args = Py_BuildValue("(i)", enumValue);
428 PyObject* result = PyObject_Call(enumType, args, NULL);
428 PyObject* result = PyObject_Call(enumType, args, NULL);
429 Py_DECREF(args);
429 Py_DECREF(args);
430 return result;
430 return result;
431 }
431 }
432
432
433 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
433 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
434 PyObject* result;
434 PyObject* result;
435
435
436 PyObject* className = PyString_FromString(enumName);
436 PyObject* className = PyString_FromString(enumName);
437
437
438 PyObject* baseClasses = PyTuple_New(1);
438 PyObject* baseClasses = PyTuple_New(1);
439 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
439 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
440
440
441 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
441 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
442 PyObject* typeDict = PyDict_New();
442 PyObject* typeDict = PyDict_New();
443 PyDict_SetItemString(typeDict, "__module__", module);
443 PyDict_SetItemString(typeDict, "__module__", module);
444
444
445 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
445 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
446
446
447 // create the new int derived type object by calling the core type
447 // create the new int derived type object by calling the core type
448 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
448 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
449
449
450 Py_DECREF(baseClasses);
450 Py_DECREF(baseClasses);
451 Py_DECREF(typeDict);
451 Py_DECREF(typeDict);
452 Py_DECREF(args);
452 Py_DECREF(args);
453 Py_DECREF(className);
453 Py_DECREF(className);
454
454
455 return result;
455 return result;
456 }
456 }
457
457
458 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
458 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
459 {
459 {
460 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
460 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
461 if (!r) {
461 if (!r) {
462 r = new PythonQtSignalReceiver(obj);
462 r = new PythonQtSignalReceiver(obj);
463 _p->_signalReceivers.insert(obj, r);
463 _p->_signalReceivers.insert(obj, r);
464 }
464 }
465 return r;
465 return r;
466 }
466 }
467
467
468 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
468 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
469 {
469 {
470 bool flag = false;
470 bool flag = false;
471 PythonQtObjectPtr callable = lookupCallable(module, objectname);
471 PythonQtObjectPtr callable = lookupCallable(module, objectname);
472 if (callable) {
472 if (callable) {
473 PythonQtSignalReceiver* r = getSignalReceiver(obj);
473 PythonQtSignalReceiver* r = getSignalReceiver(obj);
474 flag = r->addSignalHandler(signal, callable);
474 flag = r->addSignalHandler(signal, callable);
475 if (!flag) {
475 if (!flag) {
476 // signal not found
476 // signal not found
477 }
477 }
478 } else {
478 } else {
479 // callable not found
479 // callable not found
480 }
480 }
481 return flag;
481 return flag;
482 }
482 }
483
483
484 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
484 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
485 {
485 {
486 bool flag = false;
486 bool flag = false;
487 PythonQtSignalReceiver* r = getSignalReceiver(obj);
487 PythonQtSignalReceiver* r = getSignalReceiver(obj);
488 if (r) {
488 if (r) {
489 flag = r->addSignalHandler(signal, receiver);
489 flag = r->addSignalHandler(signal, receiver);
490 }
490 }
491 return flag;
491 return flag;
492 }
492 }
493
493
494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
495 {
495 {
496 bool flag = false;
496 bool flag = false;
497 PythonQtObjectPtr callable = lookupCallable(module, objectname);
497 PythonQtObjectPtr callable = lookupCallable(module, objectname);
498 if (callable) {
498 if (callable) {
499 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
499 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
500 if (r) {
500 if (r) {
501 flag = r->removeSignalHandler(signal, callable);
501 flag = r->removeSignalHandler(signal, callable);
502 }
502 }
503 } else {
503 } else {
504 // callable not found
504 // callable not found
505 }
505 }
506 return flag;
506 return flag;
507 }
507 }
508
508
509 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
509 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
510 {
510 {
511 bool flag = false;
511 bool flag = false;
512 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
512 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
513 if (r) {
513 if (r) {
514 flag = r->removeSignalHandler(signal, receiver);
514 flag = r->removeSignalHandler(signal, receiver);
515 }
515 }
516 return flag;
516 return flag;
517 }
517 }
518
518
519 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
519 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
520 {
520 {
521 PythonQtObjectPtr p = lookupObject(module, name);
521 PythonQtObjectPtr p = lookupObject(module, name);
522 if (p) {
522 if (p) {
523 if (PyCallable_Check(p)) {
523 if (PyCallable_Check(p)) {
524 return p;
524 return p;
525 }
525 }
526 }
526 }
527 PyErr_Clear();
527 PyErr_Clear();
528 return NULL;
528 return NULL;
529 }
529 }
530
530
531 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
531 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
532 {
532 {
533 QStringList l = name.split('.');
533 QStringList l = name.split('.');
534 PythonQtObjectPtr p = module;
534 PythonQtObjectPtr p = module;
535 PythonQtObjectPtr prev;
535 PythonQtObjectPtr prev;
536 QString s;
536 QString s;
537 QByteArray b;
537 QByteArray b;
538 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
538 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
539 prev = p;
539 prev = p;
540 b = (*i).toLatin1();
540 b = (*i).toLatin1();
541 if (PyDict_Check(p)) {
541 if (PyDict_Check(p)) {
542 p = PyDict_GetItemString(p, b.data());
542 p = PyDict_GetItemString(p, b.data());
543 } else {
543 } else {
544 p.setNewRef(PyObject_GetAttrString(p, b.data()));
544 p.setNewRef(PyObject_GetAttrString(p, b.data()));
545 }
545 }
546 }
546 }
547 PyErr_Clear();
547 PyErr_Clear();
548 return p;
548 return p;
549 }
549 }
550
550
551 PythonQtObjectPtr PythonQt::getMainModule() {
551 PythonQtObjectPtr PythonQt::getMainModule() {
552 //both borrowed
552 //both borrowed
553 PythonQtObjectPtr dict = PyImport_GetModuleDict();
553 PythonQtObjectPtr dict = PyImport_GetModuleDict();
554 return PyDict_GetItemString(dict, "__main__");
554 return PyDict_GetItemString(dict, "__main__");
555 }
555 }
556
556
557 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
557 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
558 QVariant result;
558 QVariant result;
559 if (pycode) {
559 if (pycode) {
560 PyObject* dict = NULL;
560 PyObject* dict = NULL;
561 if (PyModule_Check(object)) {
561 if (PyModule_Check(object)) {
562 dict = PyModule_GetDict(object);
562 dict = PyModule_GetDict(object);
563 } else if (PyDict_Check(object)) {
563 } else if (PyDict_Check(object)) {
564 dict = object;
564 dict = object;
565 }
565 }
566 PyObject* r = NULL;
566 PyObject* r = NULL;
567 if (dict) {
567 if (dict) {
568 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
568 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
569 }
569 }
570 if (r) {
570 if (r) {
571 result = PythonQtConv::PyObjToQVariant(r);
571 result = PythonQtConv::PyObjToQVariant(r);
572 Py_DECREF(r);
572 Py_DECREF(r);
573 } else {
573 } else {
574 handleError();
574 handleError();
575 }
575 }
576 } else {
576 } else {
577 handleError();
577 handleError();
578 }
578 }
579 return result;
579 return result;
580 }
580 }
581
581
582 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
582 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
583 {
583 {
584 QVariant result;
584 QVariant result;
585 PythonQtObjectPtr p;
585 PythonQtObjectPtr p;
586 PyObject* dict = NULL;
586 PyObject* dict = NULL;
587 if (PyModule_Check(object)) {
587 if (PyModule_Check(object)) {
588 dict = PyModule_GetDict(object);
588 dict = PyModule_GetDict(object);
589 } else if (PyDict_Check(object)) {
589 } else if (PyDict_Check(object)) {
590 dict = object;
590 dict = object;
591 }
591 }
592 if (dict) {
592 if (dict) {
593 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
593 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
594 }
594 }
595 if (p) {
595 if (p) {
596 result = PythonQtConv::PyObjToQVariant(p);
596 result = PythonQtConv::PyObjToQVariant(p);
597 } else {
597 } else {
598 handleError();
598 handleError();
599 }
599 }
600 return result;
600 return result;
601 }
601 }
602
602
603 void PythonQt::evalFile(PyObject* module, const QString& filename)
603 void PythonQt::evalFile(PyObject* module, const QString& filename)
604 {
604 {
605 PythonQtObjectPtr code = parseFile(filename);
605 PythonQtObjectPtr code = parseFile(filename);
606 if (code) {
606 if (code) {
607 evalCode(module, code);
607 evalCode(module, code);
608 } else {
608 } else {
609 handleError();
609 handleError();
610 }
610 }
611 }
611 }
612
612
613 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
613 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
614 {
614 {
615 PythonQtObjectPtr p;
615 PythonQtObjectPtr p;
616 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
616 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
617 if (!p) {
617 if (!p) {
618 handleError();
618 handleError();
619 }
619 }
620 return p;
620 return p;
621 }
621 }
622
622
623 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
623 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
624 {
624 {
625 PythonQtObjectPtr code = parseFile(filename);
625 PythonQtObjectPtr code = parseFile(filename);
626 PythonQtObjectPtr module = _p->createModule(name, code);
626 PythonQtObjectPtr module = _p->createModule(name, code);
627 return module;
627 return module;
628 }
628 }
629
629
630 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
630 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
631 {
631 {
632 PyErr_Clear();
632 PyErr_Clear();
633 QString scriptCode = script;
633 QString scriptCode = script;
634 if (scriptCode.isEmpty()) {
634 if (scriptCode.isEmpty()) {
635 // we always need at least a linefeed
635 // we always need at least a linefeed
636 scriptCode = "\n";
636 scriptCode = "\n";
637 }
637 }
638 PythonQtObjectPtr pycode;
638 PythonQtObjectPtr pycode;
639 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
639 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
640 PythonQtObjectPtr module = _p->createModule(name, pycode);
640 PythonQtObjectPtr module = _p->createModule(name, pycode);
641 return module;
641 return module;
642 }
642 }
643
643
644 PythonQtObjectPtr PythonQt::createUniqueModule()
644 PythonQtObjectPtr PythonQt::createUniqueModule()
645 {
645 {
646 static QString pyQtStr("PythonQt_module");
646 static QString pyQtStr("PythonQt_module");
647 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
647 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
648 return createModuleFromScript(moduleName);
648 return createModuleFromScript(moduleName);
649 }
649 }
650
650
651 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
651 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
652 {
652 {
653 if (PyModule_Check(object)) {
653 if (PyModule_Check(object)) {
654 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
654 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 } else if (PyDict_Check(object)) {
655 } else if (PyDict_Check(object)) {
656 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
656 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 } else {
657 } else {
658 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
658 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
659 }
659 }
660 }
660 }
661
661
662 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
662 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
663 {
663 {
664 if (PyModule_Check(object)) {
664 if (PyModule_Check(object)) {
665 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
665 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 } else if (PyDict_Check(object)) {
666 } else if (PyDict_Check(object)) {
667 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
667 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 } else {
668 } else {
669 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
669 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
670 }
670 }
671 }
671 }
672
672
673 void PythonQt::removeVariable(PyObject* object, const QString& name)
673 void PythonQt::removeVariable(PyObject* object, const QString& name)
674 {
674 {
675 if (PyDict_Check(object)) {
675 if (PyDict_Check(object)) {
676 PyDict_DelItemString(object, name.toLatin1().data());
676 PyDict_DelItemString(object, name.toLatin1().data());
677 } else {
677 } else {
678 PyObject_DelAttrString(object, name.toLatin1().data());
678 PyObject_DelAttrString(object, name.toLatin1().data());
679 }
679 }
680 }
680 }
681
681
682 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
682 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
683 {
683 {
684 QVariant result;
684 QVariant result;
685 PythonQtObjectPtr obj = lookupObject(object, objectname);
685 PythonQtObjectPtr obj = lookupObject(object, objectname);
686 if (obj) {
686 if (obj) {
687 result = PythonQtConv::PyObjToQVariant(obj);
687 result = PythonQtConv::PyObjToQVariant(obj);
688 }
688 }
689 return result;
689 return result;
690 }
690 }
691
691
692 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
692 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
693 {
693 {
694 QStringList results;
694 QStringList results;
695
695
696 PythonQtObjectPtr object;
696 PythonQtObjectPtr object;
697 if (objectname.isEmpty()) {
697 if (objectname.isEmpty()) {
698 object = module;
698 object = module;
699 } else {
699 } else {
700 object = lookupObject(module, objectname);
700 object = lookupObject(module, objectname);
701 if (!object && type == CallOverloads) {
701 if (!object && type == CallOverloads) {
702 PyObject* dict = lookupObject(module, "__builtins__");
702 PyObject* dict = lookupObject(module, "__builtins__");
703 if (dict) {
703 if (dict) {
704 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
704 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
705 }
705 }
706 }
706 }
707 }
707 }
708
708
709 if (object) {
709 if (object) {
710 if (type == CallOverloads) {
710 if (type == CallOverloads) {
711 if (PythonQtSlotFunction_Check(object)) {
711 if (PythonQtSlotFunction_Check(object)) {
712 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
712 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
713 PythonQtSlotInfo* info = o->m_ml;
713 PythonQtSlotInfo* info = o->m_ml;
714
714
715 while (info) {
715 while (info) {
716 results << info->fullSignature();
716 results << info->fullSignature();
717 info = info->nextInfo();
717 info = info->nextInfo();
718 }
718 }
719 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
719 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
720 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
720 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
721 PythonQtSlotInfo* info = o->classInfo()->constructors();
721 PythonQtSlotInfo* info = o->classInfo()->constructors();
722
722
723 while (info) {
723 while (info) {
724 results << info->fullSignature();
724 results << info->fullSignature();
725 info = info->nextInfo();
725 info = info->nextInfo();
726 }
726 }
727 } else {
727 } else {
728 //TODO: use pydoc!
728 //TODO: use pydoc!
729 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
729 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
730 if (doc) {
730 if (doc) {
731 results << PyString_AsString(doc);
731 results << PyString_AsString(doc);
732 Py_DECREF(doc);
732 Py_DECREF(doc);
733 }
733 }
734 }
734 }
735 } else {
735 } else {
736 PyObject* keys = NULL;
736 PyObject* keys = NULL;
737 bool isDict = false;
737 bool isDict = false;
738 if (PyDict_Check(object)) {
738 if (PyDict_Check(object)) {
739 keys = PyDict_Keys(object);
739 keys = PyDict_Keys(object);
740 isDict = true;
740 isDict = true;
741 } else {
741 } else {
742 keys = PyObject_Dir(object);
742 keys = PyObject_Dir(object);
743 }
743 }
744 if (keys) {
744 if (keys) {
745 int count = PyList_Size(keys);
745 int count = PyList_Size(keys);
746 PyObject* key;
746 PyObject* key;
747 PyObject* value;
747 PyObject* value;
748 QString keystr;
748 QString keystr;
749 for (int i = 0;i<count;i++) {
749 for (int i = 0;i<count;i++) {
750 key = PyList_GetItem(keys,i);
750 key = PyList_GetItem(keys,i);
751 if (isDict) {
751 if (isDict) {
752 value = PyDict_GetItem(object, key);
752 value = PyDict_GetItem(object, key);
753 Py_INCREF(value);
753 Py_INCREF(value);
754 } else {
754 } else {
755 value = PyObject_GetAttr(object, key);
755 value = PyObject_GetAttr(object, key);
756 }
756 }
757 if (!value) continue;
757 if (!value) continue;
758 keystr = PyString_AsString(key);
758 keystr = PyString_AsString(key);
759 static const QString underscoreStr("__tmp");
759 static const QString underscoreStr("__tmp");
760 if (!keystr.startsWith(underscoreStr)) {
760 if (!keystr.startsWith(underscoreStr)) {
761 switch (type) {
761 switch (type) {
762 case Anything:
762 case Anything:
763 results << keystr;
763 results << keystr;
764 break;
764 break;
765 case Class:
765 case Class:
766 if (value->ob_type == &PyClass_Type) {
766 if (value->ob_type == &PyClass_Type) {
767 results << keystr;
767 results << keystr;
768 }
768 }
769 break;
769 break;
770 case Variable:
770 case Variable:
771 if (value->ob_type != &PyClass_Type
771 if (value->ob_type != &PyClass_Type
772 && value->ob_type != &PyCFunction_Type
772 && value->ob_type != &PyCFunction_Type
773 && value->ob_type != &PyFunction_Type
773 && value->ob_type != &PyFunction_Type
774 && value->ob_type != &PyModule_Type
774 && value->ob_type != &PyModule_Type
775 ) {
775 ) {
776 results << keystr;
776 results << keystr;
777 }
777 }
778 break;
778 break;
779 case Function:
779 case Function:
780 if (value->ob_type == &PyFunction_Type ||
780 if (value->ob_type == &PyFunction_Type ||
781 value->ob_type == &PyMethod_Type
781 value->ob_type == &PyMethod_Type
782 ) {
782 ) {
783 results << keystr;
783 results << keystr;
784 }
784 }
785 break;
785 break;
786 case Module:
786 case Module:
787 if (value->ob_type == &PyModule_Type) {
787 if (value->ob_type == &PyModule_Type) {
788 results << keystr;
788 results << keystr;
789 }
789 }
790 break;
790 break;
791 default:
791 default:
792 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
792 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
793 }
793 }
794 }
794 }
795 Py_DECREF(value);
795 Py_DECREF(value);
796 }
796 }
797 Py_DECREF(keys);
797 Py_DECREF(keys);
798 }
798 }
799 }
799 }
800 }
800 }
801 return results;
801 return results;
802 }
802 }
803
803
804 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
804 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
805 {
805 {
806 PythonQtObjectPtr callable = lookupCallable(object, name);
806 PythonQtObjectPtr callable = lookupCallable(object, name);
807 if (callable) {
807 if (callable) {
808 return call(callable, args);
808 return call(callable, args);
809 } else {
809 } else {
810 return QVariant();
810 return QVariant();
811 }
811 }
812 }
812 }
813
813
814 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
814 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
815 {
815 {
816 QVariant r;
816 QVariant r;
817 PythonQtObjectPtr result;
817 PythonQtObjectPtr result;
818 result.setNewRef(callAndReturnPyObject(callable, args));
818 result.setNewRef(callAndReturnPyObject(callable, args));
819 if (result) {
819 if (result) {
820 r = PythonQtConv::PyObjToQVariant(result);
820 r = PythonQtConv::PyObjToQVariant(result);
821 } else {
821 } else {
822 PythonQt::self()->handleError();
822 PythonQt::self()->handleError();
823 }
823 }
824 return r;
824 return r;
825 }
825 }
826
826
827 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
827 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
828 {
828 {
829 PyObject* result = NULL;
829 PyObject* result = NULL;
830 if (callable) {
830 if (callable) {
831 PythonQtObjectPtr pargs;
831 PythonQtObjectPtr pargs;
832 int count = args.size();
832 int count = args.size();
833 if (count>0) {
833 if (count>0) {
834 pargs.setNewRef(PyTuple_New(count));
834 pargs.setNewRef(PyTuple_New(count));
835 }
835 }
836 bool err = false;
836 bool err = false;
837 // transform QVariants to Python
837 // transform QVariants to Python
838 for (int i = 0; i < count; i++) {
838 for (int i = 0; i < count; i++) {
839 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
839 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
840 if (arg) {
840 if (arg) {
841 // steals reference, no unref
841 // steals reference, no unref
842 PyTuple_SetItem(pargs, i,arg);
842 PyTuple_SetItem(pargs, i,arg);
843 } else {
843 } else {
844 err = true;
844 err = true;
845 break;
845 break;
846 }
846 }
847 }
847 }
848
848
849 if (!err) {
849 if (!err) {
850 PyErr_Clear();
850 PyErr_Clear();
851 result = PyObject_CallObject(callable, pargs);
851 result = PyObject_CallObject(callable, pargs);
852 }
852 }
853 }
853 }
854 return result;
854 return result;
855 }
855 }
856
856
857 void PythonQt::addInstanceDecorators(QObject* o)
857 void PythonQt::addInstanceDecorators(QObject* o)
858 {
858 {
859 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
859 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
860 }
860 }
861
861
862 void PythonQt::addClassDecorators(QObject* o)
862 void PythonQt::addClassDecorators(QObject* o)
863 {
863 {
864 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
864 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
865 }
865 }
866
866
867 void PythonQt::addDecorators(QObject* o)
867 void PythonQt::addDecorators(QObject* o)
868 {
868 {
869 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
869 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
870 }
870 }
871
871
872 void PythonQt::registerQObjectClassNames(const QStringList& names)
872 void PythonQt::registerQObjectClassNames(const QStringList& names)
873 {
873 {
874 _p->registerQObjectClassNames(names);
874 _p->registerQObjectClassNames(names);
875 }
875 }
876
876
877 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
877 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
878 {
878 {
879 _p->_importInterface = importInterface;
879 _p->_importInterface = importInterface;
880 PythonQtImport::init();
880 PythonQtImport::init();
881 }
881 }
882
882
883 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
883 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
884 {
884 {
885 _p->_importIgnorePaths = paths;
885 _p->_importIgnorePaths = paths;
886 }
886 }
887
887
888 const QStringList& PythonQt::getImporterIgnorePaths()
888 const QStringList& PythonQt::getImporterIgnorePaths()
889 {
889 {
890 return _p->_importIgnorePaths;
890 return _p->_importIgnorePaths;
891 }
891 }
892
892
893 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
893 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
894 {
894 {
895 _p->_cppWrapperFactories.append(factory);
895 _p->_cppWrapperFactories.append(factory);
896 }
896 }
897
897
898 //---------------------------------------------------------------------------------------------------
898 //---------------------------------------------------------------------------------------------------
899 PythonQtPrivate::PythonQtPrivate()
899 PythonQtPrivate::PythonQtPrivate()
900 {
900 {
901 _importInterface = NULL;
901 _importInterface = NULL;
902 _defaultImporter = new PythonQtQFileImporter;
902 _defaultImporter = new PythonQtQFileImporter;
903 _noLongerWrappedCB = NULL;
903 _noLongerWrappedCB = NULL;
904 _wrappedCB = NULL;
904 _wrappedCB = NULL;
905 _currentClassInfoForClassWrapperCreation = NULL;
905 _currentClassInfoForClassWrapperCreation = NULL;
906 }
906 }
907
907
908 void PythonQtPrivate::setupSharedLibrarySuffixes()
908 void PythonQtPrivate::setupSharedLibrarySuffixes()
909 {
909 {
910 _sharedLibrarySuffixes.clear();
910 _sharedLibrarySuffixes.clear();
911 PythonQtObjectPtr imp;
911 PythonQtObjectPtr imp;
912 imp.setNewRef(PyImport_ImportModule("imp"));
912 imp.setNewRef(PyImport_ImportModule("imp"));
913 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
913 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
914 QVariant result = imp.call("get_suffixes");
914 QVariant result = imp.call("get_suffixes");
915 foreach (QVariant entry, result.toList()) {
915 foreach (QVariant entry, result.toList()) {
916 QVariantList suffixEntry = entry.toList();
916 QVariantList suffixEntry = entry.toList();
917 if (suffixEntry.count()==3) {
917 if (suffixEntry.count()==3) {
918 int code = suffixEntry.at(2).toInt();
918 int code = suffixEntry.at(2).toInt();
919 if (code == cExtensionCode) {
919 if (code == cExtensionCode) {
920 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
920 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
921 }
921 }
922 }
922 }
923 }
923 }
924 }
924 }
925
925
926 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
926 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
927 {
927 {
928 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
928 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
929 _currentClassInfoForClassWrapperCreation = NULL;
929 _currentClassInfoForClassWrapperCreation = NULL;
930 return info;
930 return info;
931 }
931 }
932
932
933 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
933 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
934 {
934 {
935 o->setParent(this);
935 o->setParent(this);
936 int numMethods = o->metaObject()->methodCount();
936 int numMethods = o->metaObject()->methodCount();
937 for (int i = 0; i < numMethods; i++) {
937 for (int i = 0; i < numMethods; i++) {
938 QMetaMethod m = o->metaObject()->method(i);
938 QMetaMethod m = o->metaObject()->method(i);
939 if ((m.methodType() == QMetaMethod::Method ||
939 if ((m.methodType() == QMetaMethod::Method ||
940 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
940 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
941 if (qstrncmp(m.signature(), "new_", 4)==0) {
941 if (qstrncmp(m.signature(), "new_", 4)==0) {
942 if ((decoTypes & ConstructorDecorator) == 0) continue;
942 if ((decoTypes & ConstructorDecorator) == 0) continue;
943 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
943 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
944 if (info->parameters().at(0).isPointer) {
944 if (info->parameters().at(0).pointerCount == 1) {
945 QByteArray signature = m.signature();
945 QByteArray signature = m.signature();
946 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
946 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
947 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
947 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
948 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
948 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
949 classInfo->addConstructor(newSlot);
949 classInfo->addConstructor(newSlot);
950 }
950 }
951 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
951 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
952 if ((decoTypes & DestructorDecorator) == 0) continue;
952 if ((decoTypes & DestructorDecorator) == 0) continue;
953 QByteArray signature = m.signature();
953 QByteArray signature = m.signature();
954 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
954 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
955 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
955 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
956 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
956 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
957 classInfo->setDestructor(newSlot);
957 classInfo->setDestructor(newSlot);
958 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
958 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
959 if ((decoTypes & StaticDecorator) == 0) continue;
959 if ((decoTypes & StaticDecorator) == 0) continue;
960 QByteArray signature = m.signature();
960 QByteArray signature = m.signature();
961 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
961 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
962 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
962 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
963 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
963 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
964 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
964 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
965 classInfo->addDecoratorSlot(newSlot);
965 classInfo->addDecoratorSlot(newSlot);
966 } else {
966 } else {
967 if ((decoTypes & InstanceDecorator) == 0) continue;
967 if ((decoTypes & InstanceDecorator) == 0) continue;
968 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
968 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
969 if (info->parameters().count()>1) {
969 if (info->parameters().count()>1) {
970 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
970 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
971 if (p.isPointer) {
971 if (p.pointerCount==1) {
972 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
972 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
973 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
973 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
974 classInfo->addDecoratorSlot(newSlot);
974 classInfo->addDecoratorSlot(newSlot);
975 }
975 }
976 }
976 }
977 }
977 }
978 }
978 }
979 }
979 }
980 }
980 }
981
981
982 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
982 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
983 {
983 {
984 foreach(QString name, names) {
984 foreach(QString name, names) {
985 _knownQObjectClassNames.insert(name.toLatin1(), true);
985 _knownQObjectClassNames.insert(name.toLatin1(), true);
986 }
986 }
987 }
987 }
988
988
989 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
989 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
990 {
990 {
991 _signalReceivers.remove(obj);
991 _signalReceivers.remove(obj);
992 }
992 }
993
993
994 bool PythonQt::handleError()
994 bool PythonQt::handleError()
995 {
995 {
996 bool flag = false;
996 bool flag = false;
997 if (PyErr_Occurred()) {
997 if (PyErr_Occurred()) {
998
998
999 // currently we just print the error and the stderr handler parses the errors
999 // currently we just print the error and the stderr handler parses the errors
1000 PyErr_Print();
1000 PyErr_Print();
1001
1001
1002 /*
1002 /*
1003 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1003 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1004 PyObject *ptype;
1004 PyObject *ptype;
1005 PyObject *pvalue;
1005 PyObject *pvalue;
1006 PyObject *ptraceback;
1006 PyObject *ptraceback;
1007 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1007 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1008
1008
1009 Py_XDECREF(ptype);
1009 Py_XDECREF(ptype);
1010 Py_XDECREF(pvalue);
1010 Py_XDECREF(pvalue);
1011 Py_XDECREF(ptraceback);
1011 Py_XDECREF(ptraceback);
1012 */
1012 */
1013 PyErr_Clear();
1013 PyErr_Clear();
1014 flag = true;
1014 flag = true;
1015 }
1015 }
1016 return flag;
1016 return flag;
1017 }
1017 }
1018
1018
1019 void PythonQt::addSysPath(const QString& path)
1019 void PythonQt::addSysPath(const QString& path)
1020 {
1020 {
1021 PythonQtObjectPtr sys;
1021 PythonQtObjectPtr sys;
1022 sys.setNewRef(PyImport_ImportModule("sys"));
1022 sys.setNewRef(PyImport_ImportModule("sys"));
1023 PythonQtObjectPtr obj = lookupObject(sys, "path");
1023 PythonQtObjectPtr obj = lookupObject(sys, "path");
1024 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1024 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1025 }
1025 }
1026
1026
1027 void PythonQt::overwriteSysPath(const QStringList& paths)
1027 void PythonQt::overwriteSysPath(const QStringList& paths)
1028 {
1028 {
1029 PythonQtObjectPtr sys;
1029 PythonQtObjectPtr sys;
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1031 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1031 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1032 }
1032 }
1033
1033
1034 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1034 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1035 {
1035 {
1036 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1036 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1037 }
1037 }
1038
1038
1039 void PythonQt::stdOutRedirectCB(const QString& str)
1039 void PythonQt::stdOutRedirectCB(const QString& str)
1040 {
1040 {
1041 emit PythonQt::self()->pythonStdOut(str);
1041 emit PythonQt::self()->pythonStdOut(str);
1042 }
1042 }
1043
1043
1044 void PythonQt::stdErrRedirectCB(const QString& str)
1044 void PythonQt::stdErrRedirectCB(const QString& str)
1045 {
1045 {
1046 emit PythonQt::self()->pythonStdErr(str);
1046 emit PythonQt::self()->pythonStdErr(str);
1047 }
1047 }
1048
1048
1049 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1049 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1050 {
1050 {
1051 _p->_wrappedCB = cb;
1051 _p->_wrappedCB = cb;
1052 }
1052 }
1053
1053
1054 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1054 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1055 {
1055 {
1056 _p->_noLongerWrappedCB = cb;
1056 _p->_noLongerWrappedCB = cb;
1057 }
1057 }
1058
1058
1059
1059
1060
1060
1061 static PyMethodDef PythonQtMethods[] = {
1061 static PyMethodDef PythonQtMethods[] = {
1062 {NULL, NULL, 0, NULL}
1062 {NULL, NULL, 0, NULL}
1063 };
1063 };
1064
1064
1065 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1065 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1066 {
1066 {
1067 QByteArray name = "PythonQt";
1067 QByteArray name = "PythonQt";
1068 if (!pythonQtModuleName.isEmpty()) {
1068 if (!pythonQtModuleName.isEmpty()) {
1069 name = pythonQtModuleName;
1069 name = pythonQtModuleName;
1070 }
1070 }
1071 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1071 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1072 _p->_pythonQtModuleName = name;
1072 _p->_pythonQtModuleName = name;
1073
1073
1074 if (redirectStdOut) {
1074 if (redirectStdOut) {
1075 PythonQtObjectPtr sys;
1075 PythonQtObjectPtr sys;
1076 PythonQtObjectPtr out;
1076 PythonQtObjectPtr out;
1077 PythonQtObjectPtr err;
1077 PythonQtObjectPtr err;
1078 sys.setNewRef(PyImport_ImportModule("sys"));
1078 sys.setNewRef(PyImport_ImportModule("sys"));
1079 // create a redirection object for stdout and stderr
1079 // create a redirection object for stdout and stderr
1080 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1080 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1081 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1081 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1082 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1082 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1083 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1083 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1084 // replace the built in file objects with our own objects
1084 // replace the built in file objects with our own objects
1085 PyModule_AddObject(sys, "stdout", out);
1085 PyModule_AddObject(sys, "stdout", out);
1086 PyModule_AddObject(sys, "stderr", err);
1086 PyModule_AddObject(sys, "stderr", err);
1087 }
1087 }
1088 }
1088 }
1089
1089
1090 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1090 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1091 {
1091 {
1092 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1092 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1093 }
1093 }
1094
1094
1095
1095
1096 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1096 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1097 {
1097 {
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1099 if (!info) {
1099 if (!info) {
1100 info = new PythonQtClassInfo();
1100 info = new PythonQtClassInfo();
1101 info->setupCPPObject(typeName);
1101 info->setupCPPObject(typeName);
1102 _knownClassInfos.insert(typeName, info);
1102 _knownClassInfos.insert(typeName, info);
1103 }
1103 }
1104 return info;
1104 return info;
1105 }
1105 }
1106
1106
1107 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1107 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1108 {
1108 {
1109 _p->addPolymorphicHandler(typeName, cb);
1109 _p->addPolymorphicHandler(typeName, cb);
1110 }
1110 }
1111
1111
1112 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1112 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1113 {
1113 {
1114 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1114 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1115 info->addPolymorphicHandler(cb);
1115 info->addPolymorphicHandler(cb);
1116 }
1116 }
1117
1117
1118 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1118 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1119 {
1119 {
1120 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1120 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1121 }
1121 }
1122
1122
1123 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1123 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1124 {
1124 {
1125 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1125 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1126 if (info) {
1126 if (info) {
1127 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1127 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1128 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1128 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1129 return true;
1129 return true;
1130 } else {
1130 } else {
1131 return false;
1131 return false;
1132 }
1132 }
1133 }
1133 }
1134
1134
1135 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1135 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1136 {
1136 {
1137 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1137 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1138 if (!info->pythonQtClassWrapper()) {
1138 if (!info->pythonQtClassWrapper()) {
1139 info->setTypeSlots(typeSlots);
1139 info->setTypeSlots(typeSlots);
1140 info->setupCPPObject(typeName);
1140 info->setupCPPObject(typeName);
1141 createPythonQtClassWrapper(info, package, module);
1141 createPythonQtClassWrapper(info, package, module);
1142 }
1142 }
1143 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1143 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1144 addParentClass(typeName, parentTypeName, 0);
1144 addParentClass(typeName, parentTypeName, 0);
1145 }
1145 }
1146 if (wrapperCreator) {
1146 if (wrapperCreator) {
1147 info->setDecoratorProvider(wrapperCreator);
1147 info->setDecoratorProvider(wrapperCreator);
1148 }
1148 }
1149 if (shell) {
1149 if (shell) {
1150 info->setShellSetInstanceWrapperCB(shell);
1150 info->setShellSetInstanceWrapperCB(shell);
1151 }
1151 }
1152 }
1152 }
1153
1153
1154 PyObject* PythonQtPrivate::packageByName(const char* name)
1154 PyObject* PythonQtPrivate::packageByName(const char* name)
1155 {
1155 {
1156 if (name==NULL || name[0]==0) {
1156 if (name==NULL || name[0]==0) {
1157 name = "private";
1157 name = "private";
1158 }
1158 }
1159 PyObject* v = _packages.value(name);
1159 PyObject* v = _packages.value(name);
1160 if (!v) {
1160 if (!v) {
1161 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1161 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1162 _packages.insert(name, v);
1162 _packages.insert(name, v);
1163 // AddObject steals the reference, so increment it!
1163 // AddObject steals the reference, so increment it!
1164 Py_INCREF(v);
1164 Py_INCREF(v);
1165 PyModule_AddObject(_pythonQtModule, name, v);
1165 PyModule_AddObject(_pythonQtModule, name, v);
1166 }
1166 }
1167 return v;
1167 return v;
1168 }
1168 }
1169
1169
1170 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1170 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1171 {
1171 {
1172 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;
1172 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;
1173 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1173 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1174 PythonQt::self()->handleError();
1174 PythonQt::self()->handleError();
1175 }
1175 }
1176
1176
1177 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1177 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1178 {
1178 {
1179 if (_p->_initFlags & ExternalHelp) {
1179 if (_p->_initFlags & ExternalHelp) {
1180 emit pythonHelpRequest(QByteArray(info->className()));
1180 emit pythonHelpRequest(QByteArray(info->className()));
1181 return Py_BuildValue("");
1181 return Py_BuildValue("");
1182 } else {
1182 } else {
1183 return PyString_FromString(info->help().toLatin1().data());
1183 return PyString_FromString(info->help().toLatin1().data());
1184 }
1184 }
1185 }
1185 }
1186
1186
1187 void PythonQtPrivate::removeWrapperPointer(void* obj)
1187 void PythonQtPrivate::removeWrapperPointer(void* obj)
1188 {
1188 {
1189 _wrappedObjects.remove(obj);
1189 _wrappedObjects.remove(obj);
1190 }
1190 }
1191
1191
1192 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1192 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1193 {
1193 {
1194 _wrappedObjects.insert(obj, wrapper);
1194 _wrappedObjects.insert(obj, wrapper);
1195 }
1195 }
1196
1196
1197 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1197 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1198 {
1198 {
1199 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1199 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1200 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1200 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1201 // this is a wrapper whose QObject was already removed due to destruction
1201 // this is a wrapper whose QObject was already removed due to destruction
1202 // so the obj pointer has to be a new QObject with the same address...
1202 // so the obj pointer has to be a new QObject with the same address...
1203 // we remove the old one and set the copy to NULL
1203 // we remove the old one and set the copy to NULL
1204 wrap->_objPointerCopy = NULL;
1204 wrap->_objPointerCopy = NULL;
1205 removeWrapperPointer(obj);
1205 removeWrapperPointer(obj);
1206 wrap = NULL;
1206 wrap = NULL;
1207 }
1207 }
1208 return wrap;
1208 return wrap;
1209 }
1209 }
1210
1210
1211 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1211 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1212 {
1212 {
1213 PythonQtObjectPtr result;
1213 PythonQtObjectPtr result;
1214 if (pycode) {
1214 if (pycode) {
1215 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1215 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1216 } else {
1216 } else {
1217 PythonQt::self()->handleError();
1217 PythonQt::self()->handleError();
1218 }
1218 }
1219 return result;
1219 return result;
1220 }
1220 }
@@ -1,1228 +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 PythonQtValueStorage<QVariant, 32> 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.isPointer) {
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.isPointer && (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;
86 QList<void*>* listPtr = NULL;
87 if (info.isPointer) {
87 if (info.pointerCount == 1) {
88 listPtr = *((QList<void*>**)data);
88 listPtr = *((QList<void*>**)data);
89 } else {
89 } else if (info.pointerCount == 0) {
90 listPtr = (QList<void*>*)data;
90 listPtr = (QList<void*>*)data;
91 }
91 }
92 if (listPtr) {
92 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
94 } else {
95 return NULL;
96 }
93 }
97 }
94 }
98 }
95
99
96 if (info.typeId >= QMetaType::User) {
100 if (info.typeId >= QMetaType::User) {
97 // if a converter is registered, we use is:
101 // if a converter is registered, we use is:
98 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
99 if (converter) {
103 if (converter) {
100 return (*converter)(data, info.typeId);
104 return (*converter)(data, info.typeId);
101 }
105 }
102 }
106 }
103
107
104 // 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):
105 if (info.isPointer) {
109 if (info.pointerCount == 1) {
106 // 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)
107 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
108 } else {
112 } else if (info.pointerCount == 0) {
109 // handle values that are not yet handled and not pointers
113 // handle values that are not yet handled and not pointers
110 return ConvertQtValueToPythonInternal(info.typeId, data);
114 return ConvertQtValueToPythonInternal(info.typeId, data);
115 } else {
116 return NULL;
111 }
117 }
112 }
118 }
113
119
114 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
115 switch (type) {
121 switch (type) {
116 case QMetaType::Void:
122 case QMetaType::Void:
117 Py_INCREF(Py_None);
123 Py_INCREF(Py_None);
118 return Py_None;
124 return Py_None;
119 case QMetaType::Char:
125 case QMetaType::Char:
120 return PyInt_FromLong(*((char*)data));
126 return PyInt_FromLong(*((char*)data));
121 case QMetaType::UChar:
127 case QMetaType::UChar:
122 return PyInt_FromLong(*((unsigned char*)data));
128 return PyInt_FromLong(*((unsigned char*)data));
123 case QMetaType::Short:
129 case QMetaType::Short:
124 return PyInt_FromLong(*((short*)data));
130 return PyInt_FromLong(*((short*)data));
125 case QMetaType::UShort:
131 case QMetaType::UShort:
126 return PyInt_FromLong(*((unsigned short*)data));
132 return PyInt_FromLong(*((unsigned short*)data));
127 case QMetaType::Long:
133 case QMetaType::Long:
128 return PyInt_FromLong(*((long*)data));
134 return PyInt_FromLong(*((long*)data));
129 case QMetaType::ULong:
135 case QMetaType::ULong:
130 // does not fit into simple int of python
136 // does not fit into simple int of python
131 return PyLong_FromUnsignedLong(*((unsigned long*)data));
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
132 case QMetaType::Bool:
138 case QMetaType::Bool:
133 return PythonQtConv::GetPyBool(*((bool*)data));
139 return PythonQtConv::GetPyBool(*((bool*)data));
134 case QMetaType::Int:
140 case QMetaType::Int:
135 return PyInt_FromLong(*((int*)data));
141 return PyInt_FromLong(*((int*)data));
136 case QMetaType::UInt:
142 case QMetaType::UInt:
137 // does not fit into simple int of python
143 // does not fit into simple int of python
138 return PyLong_FromUnsignedLong(*((unsigned int*)data));
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
139 case QMetaType::QChar:
145 case QMetaType::QChar:
140 return PyInt_FromLong(*((short*)data));
146 return PyInt_FromLong(*((short*)data));
141 case QMetaType::Float:
147 case QMetaType::Float:
142 return PyFloat_FromDouble(*((float*)data));
148 return PyFloat_FromDouble(*((float*)data));
143 case QMetaType::Double:
149 case QMetaType::Double:
144 return PyFloat_FromDouble(*((double*)data));
150 return PyFloat_FromDouble(*((double*)data));
145 case QMetaType::LongLong:
151 case QMetaType::LongLong:
146 return PyLong_FromLongLong(*((qint64*)data));
152 return PyLong_FromLongLong(*((qint64*)data));
147 case QMetaType::ULongLong:
153 case QMetaType::ULongLong:
148 return PyLong_FromUnsignedLongLong(*((quint64*)data));
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
149 // implicit conversion from QByteArray to str has been removed:
155 // implicit conversion from QByteArray to str has been removed:
150 //case QMetaType::QByteArray: {
156 //case QMetaType::QByteArray: {
151 // QByteArray* v = (QByteArray*) data;
157 // QByteArray* v = (QByteArray*) data;
152 // return PyString_FromStringAndSize(*v, v->size());
158 // return PyString_FromStringAndSize(*v, v->size());
153 // }
159 // }
154 case QMetaType::QVariantMap:
160 case QMetaType::QVariantMap:
155 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
156 case QMetaType::QVariantList:
162 case QMetaType::QVariantList:
157 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
158 case QMetaType::QString:
164 case QMetaType::QString:
159 return PythonQtConv::QStringToPyObject(*((QString*)data));
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
160 case QMetaType::QStringList:
166 case QMetaType::QStringList:
161 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
162
168
163 case PythonQtMethodInfo::Variant:
169 case PythonQtMethodInfo::Variant:
164 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
165 case QMetaType::QObjectStar:
171 case QMetaType::QObjectStar:
166 case QMetaType::QWidgetStar:
172 case QMetaType::QWidgetStar:
167 return PythonQt::priv()->wrapQObject(*((QObject**)data));
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
168
174
169 default:
175 default:
170 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
171 // 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:
172 PyObject* o = ((PythonQtObjectPtr*)data)->object();
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
173 Py_INCREF(o);
179 Py_INCREF(o);
174 return o;
180 return o;
175 } else {
181 } else {
176 if (type > 0) {
182 if (type > 0) {
177 // 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
178 void* newCPPObject = QMetaType::construct(type, data);
184 void* newCPPObject = QMetaType::construct(type, data);
179 // XXX this could be optimized by using metatypeid directly
185 // XXX this could be optimized by using metatypeid directly
180 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
181 wrap->_ownedByPythonQt = true;
187 wrap->_ownedByPythonQt = true;
182 wrap->_useQMetaTypeDestroy = true;
188 wrap->_useQMetaTypeDestroy = true;
183 return (PyObject*)wrap;
189 return (PyObject*)wrap;
184 }
190 }
185 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;
186 }
192 }
187 }
193 }
188 Py_INCREF(Py_None);
194 Py_INCREF(Py_None);
189 return Py_None;
195 return Py_None;
190 }
196 }
191
197
192 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
193 void* ptr = NULL;
199 void* ptr = NULL;
194 if (info.isPointer) {
200 if (info.pointerCount>1) {
201 return NULL;
202 } else if (info.pointerCount==1) {
195 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
196 } else if (info.enumWrapper) {
204 } else if (info.enumWrapper) {
197 // create enum return value
205 // create enum return value
198 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
199 } else {
207 } else {
200 switch (info.typeId) {
208 switch (info.typeId) {
201 case QMetaType::Char:
209 case QMetaType::Char:
202 case QMetaType::UChar:
210 case QMetaType::UChar:
203 case QMetaType::Short:
211 case QMetaType::Short:
204 case QMetaType::UShort:
212 case QMetaType::UShort:
205 case QMetaType::Long:
213 case QMetaType::Long:
206 case QMetaType::ULong:
214 case QMetaType::ULong:
207 case QMetaType::Bool:
215 case QMetaType::Bool:
208 case QMetaType::Int:
216 case QMetaType::Int:
209 case QMetaType::UInt:
217 case QMetaType::UInt:
210 case QMetaType::QChar:
218 case QMetaType::QChar:
211 case QMetaType::Float:
219 case QMetaType::Float:
212 case QMetaType::Double:
220 case QMetaType::Double:
213 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
214 break;
222 break;
215 case PythonQtMethodInfo::Variant:
223 case PythonQtMethodInfo::Variant:
216 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
217 // return the ptr to the variant
225 // return the ptr to the variant
218 break;
226 break;
219 default:
227 default:
220 if (info.typeId == PythonQtMethodInfo::Unknown) {
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
221 // 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*>
222 if (info.name.startsWith("QList<")) {
230 if (info.name.startsWith("QList<")) {
223 QByteArray innerType = info.name.mid(6,info.name.length()-7);
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
224 if (innerType.endsWith("*")) {
232 if (innerType.endsWith("*")) {
225 static int id = QMetaType::type("QList<void*>");
233 static int id = QMetaType::type("QList<void*>");
226 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
227 // 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
228 ptr = (void*)((QVariant*)ptr)->constData();
236 ptr = (void*)((QVariant*)ptr)->constData();
229 }
237 }
230 }
238 }
231 }
239 }
232
240
233 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
234 // 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...
235 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
236 // 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
237 ptr = (void*)((QVariant*)ptr)->constData();
245 ptr = (void*)((QVariant*)ptr)->constData();
238 }
246 }
239 }
247 }
240 }
248 }
241 return ptr;
249 return ptr;
242 }
250 }
243
251
244 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
245 {
253 {
246 void* object;
254 void* object;
247 if (wrapper->classInfo()->isCPPWrapper()) {
255 if (wrapper->classInfo()->isCPPWrapper()) {
248 object = wrapper->_wrappedPtr;
256 object = wrapper->_wrappedPtr;
249 } else {
257 } else {
250 QObject* tmp = wrapper->_obj;
258 QObject* tmp = wrapper->_obj;
251 object = tmp;
259 object = tmp;
252 }
260 }
253 if (object) {
261 if (object) {
254 // 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:
255 object = wrapper->classInfo()->castTo(object, className);
263 object = wrapper->classInfo()->castTo(object, className);
256 ok = object!=NULL;
264 ok = object!=NULL;
257 } else {
265 } else {
258 // 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
259 ok = wrapper->classInfo()->inherits(className);
267 ok = wrapper->classInfo()->inherits(className);
260 }
268 }
261 return object;
269 return object;
262 }
270 }
263
271
264 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
265 {
273 {
266 void* ptr = alreadyAllocatedCPPObject;
274 void* ptr = alreadyAllocatedCPPObject;
267
275
268 static int penId = QMetaType::type("QPen");
276 static int penId = QMetaType::type("QPen");
269 static int brushId = QMetaType::type("QBrush");
277 static int brushId = QMetaType::type("QBrush");
270 static int cursorId = QMetaType::type("QCursor");
278 static int cursorId = QMetaType::type("QCursor");
271 static int colorId = QMetaType::type("QColor");
279 static int colorId = QMetaType::type("QColor");
272 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
273 if (typeId == cursorId) {
281 if (typeId == cursorId) {
274 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
275 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
276 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
277 if (!ptr) {
285 if (!ptr) {
278 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
279 ptr = (void*)((QVariant*)ptr)->constData();
287 ptr = (void*)((QVariant*)ptr)->constData();
280 }
288 }
281 *((QCursor*)ptr) = QCursor(val);
289 *((QCursor*)ptr) = QCursor(val);
282 return ptr;
290 return ptr;
283 }
291 }
284 } else if (typeId == penId) {
292 } else if (typeId == penId) {
285 // 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)
286 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
287 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
288 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
289 if (!ptr) {
297 if (!ptr) {
290 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
291 ptr = (void*)((QVariant*)ptr)->constData();
299 ptr = (void*)((QVariant*)ptr)->constData();
292 }
300 }
293 *((QPen*)ptr) = QPen(QColor(val));
301 *((QPen*)ptr) = QPen(QColor(val));
294 return ptr;
302 return ptr;
295 } else if ((PyObject*)obj->ob_type == qtColorClass) {
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
296 if (!ptr) {
304 if (!ptr) {
297 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 ptr = (void*)((QVariant*)ptr)->constData();
306 ptr = (void*)((QVariant*)ptr)->constData();
299 }
307 }
300 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
301 return ptr;
309 return ptr;
302 }
310 }
303 } else if (typeId == brushId) {
311 } else if (typeId == brushId) {
304 // 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)
305 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
306 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
307 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
308 if (!ptr) {
316 if (!ptr) {
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
310 ptr = (void*)((QVariant*)ptr)->constData();
318 ptr = (void*)((QVariant*)ptr)->constData();
311 }
319 }
312 *((QBrush*)ptr) = QBrush(QColor(val));
320 *((QBrush*)ptr) = QBrush(QColor(val));
313 return ptr;
321 return ptr;
314 } else if ((PyObject*)obj->ob_type == qtColorClass) {
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
315 if (!ptr) {
323 if (!ptr) {
316 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 ptr = (void*)((QVariant*)ptr)->constData();
325 ptr = (void*)((QVariant*)ptr)->constData();
318 }
326 }
319 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
320 return ptr;
328 return ptr;
321 }
329 }
322 } else if (typeId == colorId) {
330 } else if (typeId == colorId) {
323 // 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)
324 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
325 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
326 if (!ptr) {
334 if (!ptr) {
327 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
328 ptr = (void*)((QVariant*)ptr)->constData();
336 ptr = (void*)((QVariant*)ptr)->constData();
329 }
337 }
330 *((QColor*)ptr) = QColor(val);
338 *((QColor*)ptr) = QColor(val);
331 return ptr;
339 return ptr;
332 }
340 }
333 }
341 }
334 return NULL;
342 return NULL;
335 }
343 }
336
344
337 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)
338 {
346 {
339 bool ok = false;
347 bool ok = false;
340 void* ptr = NULL;
348 void* ptr = NULL;
341
349
342 // autoconversion of QPen/QBrush/QCursor/QColor from different type
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
343 if (!info.isPointer && !strict) {
351 if (info.pointerCount==0 && !strict) {
344 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
345 if (ptr) {
353 if (ptr) {
346 return ptr;
354 return ptr;
347 }
355 }
348 }
356 }
349
357
350 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
351 // 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:
352 // (the Variant case is handled below in a switch)
360 // (the Variant case is handled below in a switch)
353
361
354 // a C++ wrapper (can be passed as pointer or reference)
362 // a C++ wrapper (can be passed as pointer or reference)
355 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
356 void* object = castWrapperTo(wrap, info.name, ok);
364 void* object = castWrapperTo(wrap, info.name, ok);
357 if (ok) {
365 if (ok) {
358 if (info.isPointer) {
366 if (info.pointerCount==1) {
359 // 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
360 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
361 } else {
369 } else if (info.pointerCount==0) {
362 // store the wrapped pointer directly, since we are a reference
370 // store the wrapped pointer directly, since we are a reference
363 ptr = object;
371 ptr = object;
364 }
372 }
365 } else {
373 } else {
366 // not matching
374 // not matching
367 }
375 }
368 } else if (info.isPointer) {
376 } else if (info.pointerCount == 1) {
369 // a pointer
377 // a pointer
370 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
371 {
379 {
372 QString str = PyObjGetString(obj, strict, ok);
380 QString str = PyObjGetString(obj, strict, ok);
373 if (ok) {
381 if (ok) {
374 void* ptr2 = NULL;
382 void* ptr2 = NULL;
375 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);
376 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);
377 }
385 }
378 } else if (info.name == "PyObject") {
386 } else if (info.name == "PyObject") {
379 // handle low level PyObject directly
387 // handle low level PyObject directly
380 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
381 } else if (obj == Py_None) {
389 } else if (obj == Py_None) {
382 // None is treated as a NULL ptr
390 // None is treated as a NULL ptr
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
384 } else {
392 } else {
385 // 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
386 if (!strict) {
394 if (!strict) {
387 bool ok;
395 bool ok;
388 int value = PyObjGetInt(obj, true, ok);
396 int value = PyObjGetInt(obj, true, ok);
389 if (ok && value==0) {
397 if (ok && value==0) {
390 // 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?
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
399 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
392 }
400 }
393 }
401 }
394 }
402 }
395 } else {
403 } else if (info.pointerCount == 0) {
396 // not a pointer
404 // not a pointer
397 switch (info.typeId) {
405 switch (info.typeId) {
398 case QMetaType::Char:
406 case QMetaType::Char:
399 {
407 {
400 int val = PyObjGetInt(obj, strict, ok);
408 int val = PyObjGetInt(obj, strict, ok);
401 if (ok) {
409 if (ok) {
402 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
403 }
411 }
404 }
412 }
405 break;
413 break;
406 case QMetaType::UChar:
414 case QMetaType::UChar:
407 {
415 {
408 int val = PyObjGetInt(obj, strict, ok);
416 int val = PyObjGetInt(obj, strict, ok);
409 if (ok) {
417 if (ok) {
410 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);
411 }
419 }
412 }
420 }
413 break;
421 break;
414 case QMetaType::Short:
422 case QMetaType::Short:
415 {
423 {
416 int val = PyObjGetInt(obj, strict, ok);
424 int val = PyObjGetInt(obj, strict, ok);
417 if (ok) {
425 if (ok) {
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
419 }
427 }
420 }
428 }
421 break;
429 break;
422 case QMetaType::UShort:
430 case QMetaType::UShort:
423 {
431 {
424 int val = PyObjGetInt(obj, strict, ok);
432 int val = PyObjGetInt(obj, strict, ok);
425 if (ok) {
433 if (ok) {
426 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);
427 }
435 }
428 }
436 }
429 break;
437 break;
430 case QMetaType::Long:
438 case QMetaType::Long:
431 {
439 {
432 long val = (long)PyObjGetLongLong(obj, strict, ok);
440 long val = (long)PyObjGetLongLong(obj, strict, ok);
433 if (ok) {
441 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
435 }
443 }
436 }
444 }
437 break;
445 break;
438 case QMetaType::ULong:
446 case QMetaType::ULong:
439 {
447 {
440 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
448 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
441 if (ok) {
449 if (ok) {
442 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);
443 }
451 }
444 }
452 }
445 break;
453 break;
446 case QMetaType::Bool:
454 case QMetaType::Bool:
447 {
455 {
448 bool val = PyObjGetBool(obj, strict, ok);
456 bool val = PyObjGetBool(obj, strict, ok);
449 if (ok) {
457 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
451 }
459 }
452 }
460 }
453 break;
461 break;
454 case QMetaType::Int:
462 case QMetaType::Int:
455 {
463 {
456 int val = PyObjGetInt(obj, strict, ok);
464 int val = PyObjGetInt(obj, strict, ok);
457 if (ok) {
465 if (ok) {
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
459 }
467 }
460 }
468 }
461 break;
469 break;
462 case QMetaType::UInt:
470 case QMetaType::UInt:
463 {
471 {
464 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
472 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
465 if (ok) {
473 if (ok) {
466 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);
467 }
475 }
468 }
476 }
469 break;
477 break;
470 case QMetaType::QChar:
478 case QMetaType::QChar:
471 {
479 {
472 int val = PyObjGetInt(obj, strict, ok);
480 int val = PyObjGetInt(obj, strict, ok);
473 if (ok) {
481 if (ok) {
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
475 }
483 }
476 }
484 }
477 break;
485 break;
478 case QMetaType::Float:
486 case QMetaType::Float:
479 {
487 {
480 float val = (float)PyObjGetDouble(obj, strict, ok);
488 float val = (float)PyObjGetDouble(obj, strict, ok);
481 if (ok) {
489 if (ok) {
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
483 }
491 }
484 }
492 }
485 break;
493 break;
486 case QMetaType::Double:
494 case QMetaType::Double:
487 {
495 {
488 double val = (double)PyObjGetDouble(obj, strict, ok);
496 double val = (double)PyObjGetDouble(obj, strict, ok);
489 if (ok) {
497 if (ok) {
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
491 }
499 }
492 }
500 }
493 break;
501 break;
494 case QMetaType::LongLong:
502 case QMetaType::LongLong:
495 {
503 {
496 qint64 val = PyObjGetLongLong(obj, strict, ok);
504 qint64 val = PyObjGetLongLong(obj, strict, ok);
497 if (ok) {
505 if (ok) {
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
499 }
507 }
500 }
508 }
501 break;
509 break;
502 case QMetaType::ULongLong:
510 case QMetaType::ULongLong:
503 {
511 {
504 quint64 val = PyObjGetULongLong(obj, strict, ok);
512 quint64 val = PyObjGetULongLong(obj, strict, ok);
505 if (ok) {
513 if (ok) {
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
507 }
515 }
508 }
516 }
509 break;
517 break;
510 case QMetaType::QByteArray:
518 case QMetaType::QByteArray:
511 {
519 {
512 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
520 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
513 if (ok) {
521 if (ok) {
514 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);
515 ptr = (void*)((QVariant*)ptr)->constData();
523 ptr = (void*)((QVariant*)ptr)->constData();
516 }
524 }
517 }
525 }
518 break;
526 break;
519 case QMetaType::QString:
527 case QMetaType::QString:
520 {
528 {
521 QString str = PyObjGetString(obj, strict, ok);
529 QString str = PyObjGetString(obj, strict, ok);
522 if (ok) {
530 if (ok) {
523 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);
524 ptr = (void*)((QVariant*)ptr)->constData();
532 ptr = (void*)((QVariant*)ptr)->constData();
525 }
533 }
526 }
534 }
527 break;
535 break;
528 case QMetaType::QStringList:
536 case QMetaType::QStringList:
529 {
537 {
530 QStringList l = PyObjToStringList(obj, strict, ok);
538 QStringList l = PyObjToStringList(obj, strict, ok);
531 if (ok) {
539 if (ok) {
532 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);
533 ptr = (void*)((QVariant*)ptr)->constData();
541 ptr = (void*)((QVariant*)ptr)->constData();
534 }
542 }
535 }
543 }
536 break;
544 break;
537
545
538 case PythonQtMethodInfo::Variant:
546 case PythonQtMethodInfo::Variant:
539 {
547 {
540 QVariant v = PyObjToQVariant(obj);
548 QVariant v = PyObjToQVariant(obj);
541 // 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(),
542 // so we do not check v.isValid() here
550 // so we do not check v.isValid() here
543 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
551 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
544 }
552 }
545 break;
553 break;
546 default:
554 default:
547 {
555 {
548 // check for enum case
556 // check for enum case
549 if (info.enumWrapper) {
557 if (info.enumWrapper) {
550 unsigned int val;
558 unsigned int val;
551 ok = false;
559 ok = false;
552 if ((PyObject*)obj->ob_type == info.enumWrapper) {
560 if ((PyObject*)obj->ob_type == info.enumWrapper) {
553 // we have a exact enum type match:
561 // we have a exact enum type match:
554 val = PyInt_AS_LONG(obj);
562 val = PyInt_AS_LONG(obj);
555 ok = true;
563 ok = true;
556 } else if (!strict) {
564 } else if (!strict) {
557 // 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
558 // we want an integer overload to be taken first!
566 // we want an integer overload to be taken first!
559 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
567 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
560 }
568 }
561 if (ok) {
569 if (ok) {
562 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);
563 return ptr;
571 return ptr;
564 } else {
572 } else {
565 return NULL;
573 return NULL;
566 }
574 }
567 }
575 }
568
576
569 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
577 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
570 // 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
571 if (info.name.startsWith("QList<")) {
579 if (info.name.startsWith("QList<")) {
572 QByteArray innerType = info.name.mid(6,info.name.length()-7);
580 QByteArray innerType = info.name.mid(6,info.name.length()-7);
573 if (innerType.endsWith("*")) {
581 if (innerType.endsWith("*")) {
574 innerType.truncate(innerType.length()-1);
582 innerType.truncate(innerType.length()-1);
575 static int id = QMetaType::type("QList<void*>");
583 static int id = QMetaType::type("QList<void*>");
576 if (!alreadyAllocatedCPPObject) {
584 if (!alreadyAllocatedCPPObject) {
577 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);
578 ptr = (void*)((QVariant*)ptr)->constData();
586 ptr = (void*)((QVariant*)ptr)->constData();
579 } else {
587 } else {
580 ptr = alreadyAllocatedCPPObject;
588 ptr = alreadyAllocatedCPPObject;
581 }
589 }
582 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
590 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
583 if (ok) {
591 if (ok) {
584 return ptr;
592 return ptr;
585 } else {
593 } else {
586 return NULL;
594 return NULL;
587 }
595 }
588 }
596 }
589 }
597 }
590 }
598 }
591
599
592 // 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.
593 if (info.typeId >= QMetaType::User) {
601 if (info.typeId >= QMetaType::User) {
594 // 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:
595 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
603 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
596 if (converter) {
604 if (converter) {
597 if (!alreadyAllocatedCPPObject) {
605 if (!alreadyAllocatedCPPObject) {
598 // create a new empty variant of concrete type:
606 // create a new empty variant of concrete type:
599 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);
600 ptr = (void*)((QVariant*)ptr)->constData();
608 ptr = (void*)((QVariant*)ptr)->constData();
601 } else {
609 } else {
602 ptr = alreadyAllocatedCPPObject;
610 ptr = alreadyAllocatedCPPObject;
603 }
611 }
604 // now call the converter, passing the internal object of the variant
612 // now call the converter, passing the internal object of the variant
605 ok = (*converter)(obj, ptr, info.typeId, strict);
613 ok = (*converter)(obj, ptr, info.typeId, strict);
606 if (ok) {
614 if (ok) {
607 return ptr;
615 return ptr;
608 } else {
616 } else {
609 return NULL;
617 return NULL;
610 }
618 }
611 }
619 }
612 }
620 }
613 // 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
614 if (info.typeId != PythonQtMethodInfo::Unknown) {
622 if (info.typeId != PythonQtMethodInfo::Unknown) {
615 // 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:
616 QVariant v = PyObjToQVariant(obj, info.typeId);
624 QVariant v = PyObjToQVariant(obj, info.typeId);
617 if (v.isValid()) {
625 if (v.isValid()) {
618 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
626 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
619 ptr = (void*)((QVariant*)ptr)->constData();
627 ptr = (void*)((QVariant*)ptr)->constData();
620 }
628 }
621 }
629 }
622 }
630 }
623 }
631 }
624 }
632 }
625 return ptr;
633 return ptr;
626 }
634 }
627
635
628
636
629 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
637 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
630 QStringList v;
638 QStringList v;
631 ok = false;
639 ok = false;
632 // 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
633 // (strings in python are detected to be sequences)
641 // (strings in python are detected to be sequences)
634 if (strict &&
642 if (strict &&
635 (val->ob_type == &PyString_Type ||
643 (val->ob_type == &PyString_Type ||
636 PyUnicode_Check(val))) {
644 PyUnicode_Check(val))) {
637 ok = false;
645 ok = false;
638 return v;
646 return v;
639 }
647 }
640 if (PySequence_Check(val)) {
648 if (PySequence_Check(val)) {
641 int count = PySequence_Size(val);
649 int count = PySequence_Size(val);
642 for (int i = 0;i<count;i++) {
650 for (int i = 0;i<count;i++) {
643 PyObject* value = PySequence_GetItem(val,i);
651 PyObject* value = PySequence_GetItem(val,i);
644 v.append(PyObjGetString(value,false,ok));
652 v.append(PyObjGetString(value,false,ok));
645 }
653 }
646 ok = true;
654 ok = true;
647 }
655 }
648 return v;
656 return v;
649 }
657 }
650
658
651 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
659 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
652 {
660 {
653 QString r;
661 QString r;
654 PyObject* str = PyObject_Repr(val);
662 PyObject* str = PyObject_Repr(val);
655 if (str) {
663 if (str) {
656 r = QString(PyString_AS_STRING(str));
664 r = QString(PyString_AS_STRING(str));
657 Py_DECREF(str);
665 Py_DECREF(str);
658 }
666 }
659 return r;
667 return r;
660 }
668 }
661
669
662 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
670 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
663 QString r;
671 QString r;
664 ok = true;
672 ok = true;
665 if (val->ob_type == &PyString_Type) {
673 if (val->ob_type == &PyString_Type) {
666 r = QString(PyString_AS_STRING(val));
674 r = QString(PyString_AS_STRING(val));
667 } else if (PyUnicode_Check(val)) {
675 } else if (PyUnicode_Check(val)) {
668 #ifdef WIN32
676 #ifdef WIN32
669 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
677 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
670 #else
678 #else
671 PyObject *ptmp = PyUnicode_AsUTF8String(val);
679 PyObject *ptmp = PyUnicode_AsUTF8String(val);
672 if(ptmp) {
680 if(ptmp) {
673 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
681 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
674 Py_DECREF(ptmp);
682 Py_DECREF(ptmp);
675 }
683 }
676 #endif
684 #endif
677 } else if (!strict) {
685 } else if (!strict) {
678 // EXTRA: could also use _Unicode, but why should we?
686 // EXTRA: could also use _Unicode, but why should we?
679 PyObject* str = PyObject_Str(val);
687 PyObject* str = PyObject_Str(val);
680 if (str) {
688 if (str) {
681 r = QString(PyString_AS_STRING(str));
689 r = QString(PyString_AS_STRING(str));
682 Py_DECREF(str);
690 Py_DECREF(str);
683 } else {
691 } else {
684 ok = false;
692 ok = false;
685 }
693 }
686 } else {
694 } else {
687 ok = false;
695 ok = false;
688 }
696 }
689 return r;
697 return r;
690 }
698 }
691
699
692 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
700 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
693 // TODO: support buffer objects in general
701 // TODO: support buffer objects in general
694 QByteArray r;
702 QByteArray r;
695 ok = true;
703 ok = true;
696 if (val->ob_type == &PyString_Type) {
704 if (val->ob_type == &PyString_Type) {
697 long size = PyString_GET_SIZE(val);
705 long size = PyString_GET_SIZE(val);
698 r = QByteArray(PyString_AS_STRING(val), size);
706 r = QByteArray(PyString_AS_STRING(val), size);
699 } else {
707 } else {
700 ok = false;
708 ok = false;
701 }
709 }
702 return r;
710 return r;
703 }
711 }
704
712
705 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
713 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
706 bool d = false;
714 bool d = false;
707 ok = false;
715 ok = false;
708 if (val == Py_False) {
716 if (val == Py_False) {
709 d = false;
717 d = false;
710 ok = true;
718 ok = true;
711 } else if (val == Py_True) {
719 } else if (val == Py_True) {
712 d = true;
720 d = true;
713 ok = true;
721 ok = true;
714 } else if (!strict) {
722 } else if (!strict) {
715 d = PyObjGetInt(val, false, ok)!=0;
723 d = PyObjGetInt(val, false, ok)!=0;
716 ok = true;
724 ok = true;
717 }
725 }
718 return d;
726 return d;
719 }
727 }
720
728
721 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
729 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
722 int d = 0;
730 int d = 0;
723 ok = true;
731 ok = true;
724 if (val->ob_type == &PyInt_Type) {
732 if (val->ob_type == &PyInt_Type) {
725 d = PyInt_AS_LONG(val);
733 d = PyInt_AS_LONG(val);
726 } else if (!strict) {
734 } else if (!strict) {
727 if (PyObject_TypeCheck(val, &PyInt_Type)) {
735 if (PyObject_TypeCheck(val, &PyInt_Type)) {
728 // support for derived int classes, e.g. for our enums
736 // support for derived int classes, e.g. for our enums
729 d = PyInt_AS_LONG(val);
737 d = PyInt_AS_LONG(val);
730 } else if (val->ob_type == &PyFloat_Type) {
738 } else if (val->ob_type == &PyFloat_Type) {
731 d = floor(PyFloat_AS_DOUBLE(val));
739 d = floor(PyFloat_AS_DOUBLE(val));
732 } else if (val->ob_type == &PyLong_Type) {
740 } else if (val->ob_type == &PyLong_Type) {
733 // handle error on overflow!
741 // handle error on overflow!
734 d = PyLong_AsLong(val);
742 d = PyLong_AsLong(val);
735 } else if (val == Py_False) {
743 } else if (val == Py_False) {
736 d = 0;
744 d = 0;
737 } else if (val == Py_True) {
745 } else if (val == Py_True) {
738 d = 1;
746 d = 1;
739 } else {
747 } else {
740 ok = false;
748 ok = false;
741 }
749 }
742 } else {
750 } else {
743 ok = false;
751 ok = false;
744 }
752 }
745 return d;
753 return d;
746 }
754 }
747
755
748 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
756 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
749 qint64 d = 0;
757 qint64 d = 0;
750 ok = true;
758 ok = true;
751 if (val->ob_type == &PyInt_Type) {
759 if (val->ob_type == &PyInt_Type) {
752 d = PyInt_AS_LONG(val);
760 d = PyInt_AS_LONG(val);
753 } else if (val->ob_type == &PyLong_Type) {
761 } else if (val->ob_type == &PyLong_Type) {
754 d = PyLong_AsLongLong(val);
762 d = PyLong_AsLongLong(val);
755 } else if (!strict) {
763 } else if (!strict) {
756 if (PyObject_TypeCheck(val, &PyInt_Type)) {
764 if (PyObject_TypeCheck(val, &PyInt_Type)) {
757 // support for derived int classes, e.g. for our enums
765 // support for derived int classes, e.g. for our enums
758 d = PyInt_AS_LONG(val);
766 d = PyInt_AS_LONG(val);
759 } else if (val->ob_type == &PyFloat_Type) {
767 } else if (val->ob_type == &PyFloat_Type) {
760 d = floor(PyFloat_AS_DOUBLE(val));
768 d = floor(PyFloat_AS_DOUBLE(val));
761 } else if (val == Py_False) {
769 } else if (val == Py_False) {
762 d = 0;
770 d = 0;
763 } else if (val == Py_True) {
771 } else if (val == Py_True) {
764 d = 1;
772 d = 1;
765 } else {
773 } else {
766 ok = false;
774 ok = false;
767 }
775 }
768 } else {
776 } else {
769 ok = false;
777 ok = false;
770 }
778 }
771 return d;
779 return d;
772 }
780 }
773
781
774 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
782 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
775 quint64 d = 0;
783 quint64 d = 0;
776 ok = true;
784 ok = true;
777 if (PyObject_TypeCheck(val, &PyInt_Type)) {
785 if (PyObject_TypeCheck(val, &PyInt_Type)) {
778 d = PyInt_AS_LONG(val);
786 d = PyInt_AS_LONG(val);
779 } else if (val->ob_type == &PyLong_Type) {
787 } else if (val->ob_type == &PyLong_Type) {
780 d = PyLong_AsLongLong(val);
788 d = PyLong_AsLongLong(val);
781 } else if (!strict) {
789 } else if (!strict) {
782 if (PyObject_TypeCheck(val, &PyInt_Type)) {
790 if (PyObject_TypeCheck(val, &PyInt_Type)) {
783 // support for derived int classes, e.g. for our enums
791 // support for derived int classes, e.g. for our enums
784 d = PyInt_AS_LONG(val);
792 d = PyInt_AS_LONG(val);
785 } else if (val->ob_type == &PyFloat_Type) {
793 } else if (val->ob_type == &PyFloat_Type) {
786 d = floor(PyFloat_AS_DOUBLE(val));
794 d = floor(PyFloat_AS_DOUBLE(val));
787 } else if (val == Py_False) {
795 } else if (val == Py_False) {
788 d = 0;
796 d = 0;
789 } else if (val == Py_True) {
797 } else if (val == Py_True) {
790 d = 1;
798 d = 1;
791 } else {
799 } else {
792 ok = false;
800 ok = false;
793 }
801 }
794 } else {
802 } else {
795 ok = false;
803 ok = false;
796 }
804 }
797 return d;
805 return d;
798 }
806 }
799
807
800 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
808 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
801 double d = 0;
809 double d = 0;
802 ok = true;
810 ok = true;
803 if (val->ob_type == &PyFloat_Type) {
811 if (val->ob_type == &PyFloat_Type) {
804 d = PyFloat_AS_DOUBLE(val);
812 d = PyFloat_AS_DOUBLE(val);
805 } else if (!strict) {
813 } else if (!strict) {
806 if (PyObject_TypeCheck(val, &PyInt_Type)) {
814 if (PyObject_TypeCheck(val, &PyInt_Type)) {
807 d = PyInt_AS_LONG(val);
815 d = PyInt_AS_LONG(val);
808 } else if (val->ob_type == &PyLong_Type) {
816 } else if (val->ob_type == &PyLong_Type) {
809 d = PyLong_AsLong(val);
817 d = PyLong_AsLong(val);
810 } else if (val == Py_False) {
818 } else if (val == Py_False) {
811 d = 0;
819 d = 0;
812 } else if (val == Py_True) {
820 } else if (val == Py_True) {
813 d = 1;
821 d = 1;
814 } else {
822 } else {
815 ok = false;
823 ok = false;
816 }
824 }
817 } else {
825 } else {
818 ok = false;
826 ok = false;
819 }
827 }
820 return d;
828 return d;
821 }
829 }
822
830
823 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
831 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
824 {
832 {
825 QVariant v;
833 QVariant v;
826 bool ok = true;
834 bool ok = true;
827
835
828 if (type==-1) {
836 if (type==-1) {
829 // no special type requested
837 // no special type requested
830 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
838 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
831 type = QVariant::String;
839 type = QVariant::String;
832 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
840 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
833 type = QVariant::Int;
841 type = QVariant::Int;
834 } else if (val->ob_type==&PyLong_Type) {
842 } else if (val->ob_type==&PyLong_Type) {
835 type = QVariant::LongLong;
843 type = QVariant::LongLong;
836 } else if (val->ob_type==&PyFloat_Type) {
844 } else if (val->ob_type==&PyFloat_Type) {
837 type = QVariant::Double;
845 type = QVariant::Double;
838 } else if (val == Py_False || val == Py_True) {
846 } else if (val == Py_False || val == Py_True) {
839 type = QVariant::Bool;
847 type = QVariant::Bool;
840 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
848 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
841 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
849 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
842 // 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
843 if (wrap->classInfo()->isCPPWrapper()) {
851 if (wrap->classInfo()->isCPPWrapper()) {
844 if (wrap->classInfo()->metaTypeId()>0) {
852 if (wrap->classInfo()->metaTypeId()>0) {
845 // 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!)
846 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
854 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
847 } else {
855 } else {
848 // 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
849 // the pointer here...
857 // the pointer here...
850 // 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
851 v = qVariantFromValue(wrap->_wrappedPtr);
859 v = qVariantFromValue(wrap->_wrappedPtr);
852 }
860 }
853 } else {
861 } else {
854 // this gives us a QObject pointer
862 // this gives us a QObject pointer
855 QObject* myObject = wrap->_obj;
863 QObject* myObject = wrap->_obj;
856 v = qVariantFromValue(myObject);
864 v = qVariantFromValue(myObject);
857 }
865 }
858 return v;
866 return v;
859 } else if (val->ob_type==&PyDict_Type) {
867 } else if (val->ob_type==&PyDict_Type) {
860 type = QVariant::Map;
868 type = QVariant::Map;
861 } 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)) {
862 type = QVariant::List;
870 type = QVariant::List;
863 } else if (val == Py_None) {
871 } else if (val == Py_None) {
864 // none is invalid
872 // none is invalid
865 type = QVariant::Invalid;
873 type = QVariant::Invalid;
866 } else {
874 } else {
867 // this used to be:
875 // this used to be:
868 // type = QVariant::String;
876 // type = QVariant::String;
869 // but now we want to transport the Python Objects directly:
877 // but now we want to transport the Python Objects directly:
870 PythonQtObjectPtr o(val);
878 PythonQtObjectPtr o(val);
871 v = qVariantFromValue(o);
879 v = qVariantFromValue(o);
872 return v;
880 return v;
873 }
881 }
874 }
882 }
875 // special type request:
883 // special type request:
876 switch (type) {
884 switch (type) {
877 case QVariant::Invalid:
885 case QVariant::Invalid:
878 return v;
886 return v;
879 break;
887 break;
880 case QVariant::Int:
888 case QVariant::Int:
881 {
889 {
882 int d = PyObjGetInt(val, false, ok);
890 int d = PyObjGetInt(val, false, ok);
883 if (ok) return QVariant(d);
891 if (ok) return QVariant(d);
884 }
892 }
885 break;
893 break;
886 case QVariant::UInt:
894 case QVariant::UInt:
887 {
895 {
888 int d = PyObjGetInt(val, false,ok);
896 int d = PyObjGetInt(val, false,ok);
889 if (ok) v = QVariant((unsigned int)d);
897 if (ok) v = QVariant((unsigned int)d);
890 }
898 }
891 break;
899 break;
892 case QVariant::Bool:
900 case QVariant::Bool:
893 {
901 {
894 int d = PyObjGetBool(val,false,ok);
902 int d = PyObjGetBool(val,false,ok);
895 if (ok) v = QVariant((bool)(d!=0));
903 if (ok) v = QVariant((bool)(d!=0));
896 }
904 }
897 break;
905 break;
898 case QVariant::Double:
906 case QVariant::Double:
899 {
907 {
900 double d = PyObjGetDouble(val,false,ok);
908 double d = PyObjGetDouble(val,false,ok);
901 if (ok) v = QVariant(d);
909 if (ok) v = QVariant(d);
902 break;
910 break;
903 }
911 }
904 case QMetaType::Float:
912 case QMetaType::Float:
905 {
913 {
906 float d = (float) PyObjGetDouble(val,false,ok);
914 float d = (float) PyObjGetDouble(val,false,ok);
907 if (ok) v = qVariantFromValue(d);
915 if (ok) v = qVariantFromValue(d);
908 break;
916 break;
909 }
917 }
910 case QMetaType::Long:
918 case QMetaType::Long:
911 {
919 {
912 long d = (long) PyObjGetLongLong(val,false,ok);
920 long d = (long) PyObjGetLongLong(val,false,ok);
913 if (ok) v = qVariantFromValue(d);
921 if (ok) v = qVariantFromValue(d);
914 break;
922 break;
915 }
923 }
916 case QMetaType::ULong:
924 case QMetaType::ULong:
917 {
925 {
918 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
926 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
919 if (ok) v = qVariantFromValue(d);
927 if (ok) v = qVariantFromValue(d);
920 break;
928 break;
921 }
929 }
922 case QMetaType::LongLong:
930 case QMetaType::LongLong:
923 {
931 {
924 qint64 d = PyObjGetLongLong(val, false, ok);
932 qint64 d = PyObjGetLongLong(val, false, ok);
925 if (ok) v = qVariantFromValue(d);
933 if (ok) v = qVariantFromValue(d);
926 }
934 }
927 break;
935 break;
928 case QMetaType::ULongLong:
936 case QMetaType::ULongLong:
929 {
937 {
930 quint64 d = PyObjGetULongLong(val, false, ok);
938 quint64 d = PyObjGetULongLong(val, false, ok);
931 if (ok) v = qVariantFromValue(d);
939 if (ok) v = qVariantFromValue(d);
932 }
940 }
933 break;
941 break;
934 case QMetaType::Short:
942 case QMetaType::Short:
935 {
943 {
936 short d = (short) PyObjGetInt(val,false,ok);
944 short d = (short) PyObjGetInt(val,false,ok);
937 if (ok) v = qVariantFromValue(d);
945 if (ok) v = qVariantFromValue(d);
938 break;
946 break;
939 }
947 }
940 case QMetaType::UShort:
948 case QMetaType::UShort:
941 {
949 {
942 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
950 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
943 if (ok) v = qVariantFromValue(d);
951 if (ok) v = qVariantFromValue(d);
944 break;
952 break;
945 }
953 }
946 case QMetaType::Char:
954 case QMetaType::Char:
947 {
955 {
948 char d = (char) PyObjGetInt(val,false,ok);
956 char d = (char) PyObjGetInt(val,false,ok);
949 if (ok) v = qVariantFromValue(d);
957 if (ok) v = qVariantFromValue(d);
950 break;
958 break;
951 }
959 }
952 case QMetaType::UChar:
960 case QMetaType::UChar:
953 {
961 {
954 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
962 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
955 if (ok) v = qVariantFromValue(d);
963 if (ok) v = qVariantFromValue(d);
956 break;
964 break;
957 }
965 }
958
966
959 case QVariant::ByteArray:
967 case QVariant::ByteArray:
960 case QVariant::String:
968 case QVariant::String:
961 {
969 {
962 bool ok;
970 bool ok;
963 v = QVariant(PyObjGetString(val, false, ok));
971 v = QVariant(PyObjGetString(val, false, ok));
964 }
972 }
965 break;
973 break;
966
974
967 // these are important for MeVisLab
975 // these are important for MeVisLab
968 case QVariant::Map:
976 case QVariant::Map:
969 {
977 {
970 if (PyMapping_Check(val)) {
978 if (PyMapping_Check(val)) {
971 QMap<QString,QVariant> map;
979 QMap<QString,QVariant> map;
972 PyObject* items = PyMapping_Items(val);
980 PyObject* items = PyMapping_Items(val);
973 if (items) {
981 if (items) {
974 int count = PyList_Size(items);
982 int count = PyList_Size(items);
975 PyObject* value;
983 PyObject* value;
976 PyObject* key;
984 PyObject* key;
977 PyObject* tuple;
985 PyObject* tuple;
978 for (int i = 0;i<count;i++) {
986 for (int i = 0;i<count;i++) {
979 tuple = PyList_GetItem(items,i);
987 tuple = PyList_GetItem(items,i);
980 key = PyTuple_GetItem(tuple, 0);
988 key = PyTuple_GetItem(tuple, 0);
981 value = PyTuple_GetItem(tuple, 1);
989 value = PyTuple_GetItem(tuple, 1);
982 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
990 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
983 }
991 }
984 Py_DECREF(items);
992 Py_DECREF(items);
985 v = map;
993 v = map;
986 }
994 }
987 }
995 }
988 }
996 }
989 break;
997 break;
990 case QVariant::List:
998 case QVariant::List:
991 if (PySequence_Check(val)) {
999 if (PySequence_Check(val)) {
992 QVariantList list;
1000 QVariantList list;
993 int count = PySequence_Size(val);
1001 int count = PySequence_Size(val);
994 PyObject* value;
1002 PyObject* value;
995 for (int i = 0;i<count;i++) {
1003 for (int i = 0;i<count;i++) {
996 value = PySequence_GetItem(val,i);
1004 value = PySequence_GetItem(val,i);
997 list.append(PyObjToQVariant(value, -1));
1005 list.append(PyObjToQVariant(value, -1));
998 }
1006 }
999 v = list;
1007 v = list;
1000 }
1008 }
1001 break;
1009 break;
1002 case QVariant::StringList:
1010 case QVariant::StringList:
1003 {
1011 {
1004 bool ok;
1012 bool ok;
1005 QStringList l = PyObjToStringList(val, false, ok);
1013 QStringList l = PyObjToStringList(val, false, ok);
1006 if (ok) {
1014 if (ok) {
1007 v = l;
1015 v = l;
1008 }
1016 }
1009 }
1017 }
1010 break;
1018 break;
1011
1019
1012 default:
1020 default:
1013 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1021 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1014 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1022 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1015 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1023 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1016 // 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
1017 v = QVariant(type, wrap->_wrappedPtr);
1025 v = QVariant(type, wrap->_wrappedPtr);
1018 } else {
1026 } else {
1019 v = QVariant();
1027 v = QVariant();
1020 }
1028 }
1021 } else {
1029 } else {
1022 v = QVariant();
1030 v = QVariant();
1023 }
1031 }
1024 }
1032 }
1025 return v;
1033 return v;
1026 }
1034 }
1027
1035
1028 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1036 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1029 {
1037 {
1030 if (str.isNull()) {
1038 if (str.isNull()) {
1031 return PyString_FromString("");
1039 return PyString_FromString("");
1032 } else {
1040 } else {
1033 #ifdef WIN32
1041 #ifdef WIN32
1034 // return PyString_FromString(str.toLatin1().data());
1042 // return PyString_FromString(str.toLatin1().data());
1035 return PyUnicode_FromUnicode(str.utf16(), str.length());
1043 return PyUnicode_FromUnicode(str.utf16(), str.length());
1036 #else
1044 #else
1037 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);
1038 #endif
1046 #endif
1039 }
1047 }
1040 }
1048 }
1041
1049
1042 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1050 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1043 {
1051 {
1044 PyObject* result = PyTuple_New(list.count());
1052 PyObject* result = PyTuple_New(list.count());
1045 int i = 0;
1053 int i = 0;
1046 QString str;
1054 QString str;
1047 foreach (str, list) {
1055 foreach (str, list) {
1048 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1056 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1049 i++;
1057 i++;
1050 }
1058 }
1051 // why is the error state bad after this?
1059 // why is the error state bad after this?
1052 PyErr_Clear();
1060 PyErr_Clear();
1053 return result;
1061 return result;
1054 }
1062 }
1055
1063
1056 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1064 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1057 {
1065 {
1058 PyObject* result = PyList_New(list.count());
1066 PyObject* result = PyList_New(list.count());
1059 int i = 0;
1067 int i = 0;
1060 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1068 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1061 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1069 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1062 i++;
1070 i++;
1063 }
1071 }
1064 return result;
1072 return result;
1065 }
1073 }
1066
1074
1067 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1075 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1068 {
1076 {
1069 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1077 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1070 }
1078 }
1071
1079
1072 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1080 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1073 PyObject* result = PyDict_New();
1081 PyObject* result = PyDict_New();
1074 QVariantMap::const_iterator t = m.constBegin();
1082 QVariantMap::const_iterator t = m.constBegin();
1075 PyObject* key;
1083 PyObject* key;
1076 PyObject* val;
1084 PyObject* val;
1077 for (;t!=m.end();t++) {
1085 for (;t!=m.end();t++) {
1078 key = QStringToPyObject(t.key());
1086 key = QStringToPyObject(t.key());
1079 val = QVariantToPyObject(t.value());
1087 val = QVariantToPyObject(t.value());
1080 PyDict_SetItem(result, key, val);
1088 PyDict_SetItem(result, key, val);
1081 Py_DECREF(key);
1089 Py_DECREF(key);
1082 Py_DECREF(val);
1090 Py_DECREF(val);
1083 }
1091 }
1084 return result;
1092 return result;
1085 }
1093 }
1086
1094
1087 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1095 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1088 PyObject* result = PyTuple_New(l.count());
1096 PyObject* result = PyTuple_New(l.count());
1089 int i = 0;
1097 int i = 0;
1090 QVariant v;
1098 QVariant v;
1091 foreach (v, l) {
1099 foreach (v, l) {
1092 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1100 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1093 i++;
1101 i++;
1094 }
1102 }
1095 // why is the error state bad after this?
1103 // why is the error state bad after this?
1096 PyErr_Clear();
1104 PyErr_Clear();
1097 return result;
1105 return result;
1098 }
1106 }
1099
1107
1100 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1108 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1101 {
1109 {
1102 PyObject* result = PyTuple_New(list->count());
1110 PyObject* result = PyTuple_New(list->count());
1103 int i = 0;
1111 int i = 0;
1104 foreach (void* value, *list) {
1112 foreach (void* value, *list) {
1105 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1113 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1106 i++;
1114 i++;
1107 }
1115 }
1108 return result;
1116 return result;
1109 }
1117 }
1110
1118
1111 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*/)
1112 {
1120 {
1113 bool result = false;
1121 bool result = false;
1114 if (PySequence_Check(obj)) {
1122 if (PySequence_Check(obj)) {
1115 result = true;
1123 result = true;
1116 int count = PySequence_Size(obj);
1124 int count = PySequence_Size(obj);
1117 PyObject* value;
1125 PyObject* value;
1118 for (int i = 0;i<count;i++) {
1126 for (int i = 0;i<count;i++) {
1119 value = PySequence_GetItem(obj,i);
1127 value = PySequence_GetItem(obj,i);
1120 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1128 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1121 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1129 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1122 bool ok;
1130 bool ok;
1123 void* object = castWrapperTo(wrap, type, ok);
1131 void* object = castWrapperTo(wrap, type, ok);
1124 if (ok) {
1132 if (ok) {
1125 list->append(object);
1133 list->append(object);
1126 } else {
1134 } else {
1127 result = false;
1135 result = false;
1128 break;
1136 break;
1129 }
1137 }
1130 }
1138 }
1131 }
1139 }
1132 }
1140 }
1133 return result;
1141 return result;
1134 }
1142 }
1135
1143
1136 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1144 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1137 {
1145 {
1138 int idx = typeName.indexOf("<");
1146 int idx = typeName.indexOf("<");
1139 if (idx>0) {
1147 if (idx>0) {
1140 int idx2 = typeName.indexOf(">");
1148 int idx2 = typeName.indexOf(">");
1141 if (idx2>0) {
1149 if (idx2>0) {
1142 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1150 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1143 return QMetaType::type(innerType.constData());
1151 return QMetaType::type(innerType.constData());
1144 }
1152 }
1145 }
1153 }
1146 return QMetaType::Void;
1154 return QMetaType::Void;
1147 }
1155 }
1148
1156
1149
1157
1150 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1158 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1151 QString r;
1159 QString r;
1152 switch (type) {
1160 switch (type) {
1153 case QVariant::Size: {
1161 case QVariant::Size: {
1154 const QSize* s = static_cast<const QSize*>(data);
1162 const QSize* s = static_cast<const QSize*>(data);
1155 r = QString::number(s->width()) + ", " + QString::number(s->height());
1163 r = QString::number(s->width()) + ", " + QString::number(s->height());
1156 }
1164 }
1157 break;
1165 break;
1158 case QVariant::SizeF: {
1166 case QVariant::SizeF: {
1159 const QSizeF* s = static_cast<const QSizeF*>(data);
1167 const QSizeF* s = static_cast<const QSizeF*>(data);
1160 r = QString::number(s->width()) + ", " + QString::number(s->height());
1168 r = QString::number(s->width()) + ", " + QString::number(s->height());
1161 }
1169 }
1162 break;
1170 break;
1163 case QVariant::Point: {
1171 case QVariant::Point: {
1164 const QPoint* s = static_cast<const QPoint*>(data);
1172 const QPoint* s = static_cast<const QPoint*>(data);
1165 r = QString::number(s->x()) + ", " + QString::number(s->y());
1173 r = QString::number(s->x()) + ", " + QString::number(s->y());
1166 }
1174 }
1167 break;
1175 break;
1168 case QVariant::PointF: {
1176 case QVariant::PointF: {
1169 const QPointF* s = static_cast<const QPointF*>(data);
1177 const QPointF* s = static_cast<const QPointF*>(data);
1170 r = QString::number(s->x()) + ", " + QString::number(s->y());
1178 r = QString::number(s->x()) + ", " + QString::number(s->y());
1171 }
1179 }
1172 break;
1180 break;
1173 case QVariant::Rect: {
1181 case QVariant::Rect: {
1174 const QRect* s = static_cast<const QRect*>(data);
1182 const QRect* s = static_cast<const QRect*>(data);
1175 r = QString::number(s->x()) + ", " + QString::number(s->y());
1183 r = QString::number(s->x()) + ", " + QString::number(s->y());
1176 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1184 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1177 }
1185 }
1178 break;
1186 break;
1179 case QVariant::RectF: {
1187 case QVariant::RectF: {
1180 const QRectF* s = static_cast<const QRectF*>(data);
1188 const QRectF* s = static_cast<const QRectF*>(data);
1181 r = QString::number(s->x()) + ", " + QString::number(s->y());
1189 r = QString::number(s->x()) + ", " + QString::number(s->y());
1182 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1190 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1183 }
1191 }
1184 break;
1192 break;
1185 case QVariant::Date: {
1193 case QVariant::Date: {
1186 const QDate* s = static_cast<const QDate*>(data);
1194 const QDate* s = static_cast<const QDate*>(data);
1187 r = s->toString(Qt::ISODate);
1195 r = s->toString(Qt::ISODate);
1188 }
1196 }
1189 break;
1197 break;
1190 case QVariant::DateTime: {
1198 case QVariant::DateTime: {
1191 const QDateTime* s = static_cast<const QDateTime*>(data);
1199 const QDateTime* s = static_cast<const QDateTime*>(data);
1192 r = s->toString(Qt::ISODate);
1200 r = s->toString(Qt::ISODate);
1193 }
1201 }
1194 break;
1202 break;
1195 case QVariant::Time: {
1203 case QVariant::Time: {
1196 const QTime* s = static_cast<const QTime*>(data);
1204 const QTime* s = static_cast<const QTime*>(data);
1197 r = s->toString(Qt::ISODate);
1205 r = s->toString(Qt::ISODate);
1198 }
1206 }
1199 break;
1207 break;
1200 case QVariant::Pixmap:
1208 case QVariant::Pixmap:
1201 {
1209 {
1202 const QPixmap* s = static_cast<const QPixmap*>(data);
1210 const QPixmap* s = static_cast<const QPixmap*>(data);
1203 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1211 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1204 }
1212 }
1205 break;
1213 break;
1206 case QVariant::Image:
1214 case QVariant::Image:
1207 {
1215 {
1208 const QImage* s = static_cast<const QImage*>(data);
1216 const QImage* s = static_cast<const QImage*>(data);
1209 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1217 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1210 }
1218 }
1211 break;
1219 break;
1212 case QVariant::Url:
1220 case QVariant::Url:
1213 {
1221 {
1214 const QUrl* s = static_cast<const QUrl*>(data);
1222 const QUrl* s = static_cast<const QUrl*>(data);
1215 r = s->toString();
1223 r = s->toString();
1216 }
1224 }
1217 break;
1225 break;
1218 //TODO: add more printing for other variant types
1226 //TODO: add more printing for other variant types
1219 default:
1227 default:
1220 // 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
1221 // (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!
1222 if (type>0 && type < (int)QVariant::UserType) {
1230 if (type>0 && type < (int)QVariant::UserType) {
1223 QVariant v(type, data);
1231 QVariant v(type, data);
1224 r = v.toString();
1232 r = v.toString();
1225 }
1233 }
1226 }
1234 }
1227 return r;
1235 return r;
1228 }
1236 }
@@ -1,351 +1,353
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 bool hadPointer = false;
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 hadPointer = true;
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.isPointer = hadPointer;
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.isPointer && 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.isPointer = false;
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);
195 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
196 _parameterTypeDict.insert("QString", QMetaType::QString);
196 _parameterTypeDict.insert("QString", QMetaType::QString);
197 _parameterTypeDict.insert("", QMetaType::Void);
197 _parameterTypeDict.insert("", QMetaType::Void);
198 _parameterTypeDict.insert("void", QMetaType::Void);
198 _parameterTypeDict.insert("void", QMetaType::Void);
199 // QVariant names
199 // QVariant names
200 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
200 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
201 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
201 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
202 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
202 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
203 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
203 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
204 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
204 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
205 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
205 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
206 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
219 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
221 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
223 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
225 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
227 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
228 _parameterTypeDict.insert("QFont", QMetaType::QFont);
228 _parameterTypeDict.insert("QFont", QMetaType::QFont);
229 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
229 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
230 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
230 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
231 _parameterTypeDict.insert("QColor", QMetaType::QColor);
231 _parameterTypeDict.insert("QColor", QMetaType::QColor);
232 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
232 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
233 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
233 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
234 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
234 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
235 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
236 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
236 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
237 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
237 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
238 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
238 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
239 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
239 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
240 _parameterTypeDict.insert("QPen", QMetaType::QPen);
240 _parameterTypeDict.insert("QPen", QMetaType::QPen);
241 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
241 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
242 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
242 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
243 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
243 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
244 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
244 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
245 // own special types... (none so far, could be e.g. ObjectList
245 // own special types... (none so far, could be e.g. ObjectList
246 }
246 }
247 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
247 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
248 if (it!=_parameterTypeDict.end()) {
248 if (it!=_parameterTypeDict.end()) {
249 return it.value();
249 return it.value();
250 } else {
250 } else {
251 return PythonQtMethodInfo::Unknown;
251 return PythonQtMethodInfo::Unknown;
252 }
252 }
253 }
253 }
254
254
255 void PythonQtMethodInfo::cleanupCachedMethodInfos()
255 void PythonQtMethodInfo::cleanupCachedMethodInfos()
256 {
256 {
257 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
257 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
258 while (i.hasNext()) {
258 while (i.hasNext()) {
259 delete i.next().value();
259 delete i.next().value();
260 }
260 }
261 }
261 }
262
262
263 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
263 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
264 {
264 {
265 _parameterNameAliases.insert(alias, name);
265 _parameterNameAliases.insert(alias, name);
266 }
266 }
267
267
268 //-------------------------------------------------------------------------------------------------
268 //-------------------------------------------------------------------------------------------------
269
269
270 void PythonQtSlotInfo::deleteOverloadsAndThis()
270 void PythonQtSlotInfo::deleteOverloadsAndThis()
271 {
271 {
272 PythonQtSlotInfo* cur = this;
272 PythonQtSlotInfo* cur = this;
273 while(cur->nextInfo()) {
273 while(cur->nextInfo()) {
274 PythonQtSlotInfo* next = cur->nextInfo();
274 PythonQtSlotInfo* next = cur->nextInfo();
275 delete cur;
275 delete cur;
276 cur = next;
276 cur = next;
277 }
277 }
278 }
278 }
279
279
280
280
281 QString PythonQtSlotInfo::fullSignature()
281 QString PythonQtSlotInfo::fullSignature()
282 {
282 {
283 bool skipFirstArg = isInstanceDecorator();
283 bool skipFirstArg = isInstanceDecorator();
284 QString result = _meta.typeName();
284 QString result = _meta.typeName();
285 QByteArray sig = slotName();
285 QByteArray sig = slotName();
286 QList<QByteArray> names = _meta.parameterNames();
286 QList<QByteArray> names = _meta.parameterNames();
287
287
288 bool isStatic = false;
288 bool isStatic = false;
289 bool isConstructor = false;
289 bool isConstructor = false;
290 bool isDestructor = false;
290 bool isDestructor = false;
291
291
292 if (_type == ClassDecorator) {
292 if (_type == ClassDecorator) {
293 if (sig.startsWith("new_")) {
293 if (sig.startsWith("new_")) {
294 sig = sig.mid(strlen("new_"));
294 sig = sig.mid(strlen("new_"));
295 isConstructor = true;
295 isConstructor = true;
296 } else if (sig.startsWith("delete_")) {
296 } else if (sig.startsWith("delete_")) {
297 sig = sig.mid(strlen("delete_"));
297 sig = sig.mid(strlen("delete_"));
298 isDestructor = true;
298 isDestructor = true;
299 } else if(sig.startsWith("static_")) {
299 } else if(sig.startsWith("static_")) {
300 isStatic = true;
300 isStatic = true;
301 sig = sig.mid(strlen("static_"));
301 sig = sig.mid(strlen("static_"));
302 int idx = sig.indexOf("_");
302 int idx = sig.indexOf("_");
303 if (idx>=0) {
303 if (idx>=0) {
304 sig = sig.mid(idx+1);
304 sig = sig.mid(idx+1);
305 }
305 }
306 }
306 }
307 }
307 }
308
308
309 result += QByteArray(" ") + sig;
309 result += QByteArray(" ") + sig;
310 result += "(";
310 result += "(";
311
311
312 int lastEntry = _parameters.count()-1;
312 int lastEntry = _parameters.count()-1;
313 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
313 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
314 if (_parameters.at(i).isConst) {
314 if (_parameters.at(i).isConst) {
315 result += "const ";
315 result += "const ";
316 }
316 }
317 result += _parameters.at(i).name;
317 result += _parameters.at(i).name;
318 if (_parameters.at(i).isPointer) {
318 if (_parameters.at(i).pointerCount) {
319 result += "*";
319 QByteArray stars;
320 stars.fill('*', _parameters.at(i).pointerCount);
321 result += stars;
320 }
322 }
321 if (!names.at(i-1).isEmpty()) {
323 if (!names.at(i-1).isEmpty()) {
322 result += " ";
324 result += " ";
323 result += names.at(i-1);
325 result += names.at(i-1);
324 }
326 }
325 if (i!=lastEntry) {
327 if (i!=lastEntry) {
326 result += ", ";
328 result += ", ";
327 }
329 }
328 }
330 }
329 result += ")";
331 result += ")";
330
332
331 if (isStatic) {
333 if (isStatic) {
332 result = QString("static ") + result;
334 result = QString("static ") + result;
333 }
335 }
334 if (isConstructor) {
336 if (isConstructor) {
335 // result = QString("constructor ") + result;
337 // result = QString("constructor ") + result;
336 }
338 }
337 if (isDestructor) {
339 if (isDestructor) {
338 result = QString("~") + result;
340 result = QString("~") + result;
339 }
341 }
340 return result;
342 return result;
341 }
343 }
342
344
343
345
344 QByteArray PythonQtSlotInfo::slotName()
346 QByteArray PythonQtSlotInfo::slotName()
345 {
347 {
346 QByteArray sig(_meta.signature());
348 QByteArray sig(_meta.signature());
347 int idx = sig.indexOf('(');
349 int idx = sig.indexOf('(');
348 sig = sig.left(idx);
350 sig = sig.left(idx);
349 return sig;
351 return sig;
350 }
352 }
351
353
@@ -1,190 +1,190
1 #ifndef _PYTHONQTMETHODINFO_H
1 #ifndef _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_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 PythonQtMethodInfo.h
38 // \file PythonQtMethodInfo.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
46
47 #include <QByteArray>
47 #include <QByteArray>
48 #include <QHash>
48 #include <QHash>
49 #include <QList>
49 #include <QList>
50 #include <QMetaMethod>
50 #include <QMetaMethod>
51
51
52 class PythonQtClassInfo;
52 class PythonQtClassInfo;
53 struct _object;
53 struct _object;
54 typedef struct _object PyObject;
54 typedef struct _object PyObject;
55
55
56 //! stores information about a specific signal/slot/method
56 //! stores information about a specific signal/slot/method
57 class PYTHONQT_EXPORT PythonQtMethodInfo
57 class PYTHONQT_EXPORT PythonQtMethodInfo
58 {
58 {
59 public:
59 public:
60 enum ParameterType {
60 enum ParameterType {
61 Unknown = -1,
61 Unknown = -1,
62 Variant = -2
62 Variant = -2
63 };
63 };
64
64
65 //! stores the QVariant id (if available) and the name of the type
65 //! stores the QVariant id (if available) and the name of the type
66 struct ParameterInfo {
66 struct ParameterInfo {
67 QByteArray name;
67 QByteArray name;
68 PyObject* enumWrapper; // if it is an enum, a pointer to the enum wrapper
68 PyObject* enumWrapper; // if it is an enum, a pointer to the enum wrapper
69 int typeId; // a mixture from QMetaType and ParameterType
69 int typeId; // a mixture from QMetaType and ParameterType
70 bool isPointer;
70 char pointerCount; // the number of pointers indirections
71 bool isConst;
71 bool isConst;
72 };
72 };
73
73
74 PythonQtMethodInfo() {};
74 PythonQtMethodInfo() {};
75 ~PythonQtMethodInfo() {};
75 ~PythonQtMethodInfo() {};
76 PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo);
76 PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo);
77 PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args);
77 PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args);
78 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
78 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
79 _parameters = other._parameters;
79 _parameters = other._parameters;
80 }
80 }
81
81
82 //! returns the method info of the signature, uses a cache internally to speed up
82 //! returns the method info of the signature, uses a cache internally to speed up
83 //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized)
83 //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized)
84 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo);
84 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo);
85
85
86 //! get the cached method info using the passed in list of return value and arguments, return value needs to be passed as first arg
86 //! get the cached method info using the passed in list of return value and arguments, return value needs to be passed as first arg
87 static const PythonQtMethodInfo* getCachedMethodInfoFromArgumentList(int numArgs, const char** args);
87 static const PythonQtMethodInfo* getCachedMethodInfoFromArgumentList(int numArgs, const char** args);
88
88
89 //! cleanup the cache
89 //! cleanup the cache
90 static void cleanupCachedMethodInfos();
90 static void cleanupCachedMethodInfos();
91
91
92 //! returns the number of parameters including the return value
92 //! returns the number of parameters including the return value
93 int parameterCount() const { return _parameters.size(); };
93 int parameterCount() const { return _parameters.size(); };
94
94
95 //! returns the id for the given type (using an internal dictionary)
95 //! returns the id for the given type (using an internal dictionary)
96 static int nameToType(const char* name);
96 static int nameToType(const char* name);
97
97
98 //! get the parameter infos
98 //! get the parameter infos
99 const QList<ParameterInfo>& parameters() const { return _parameters; }
99 const QList<ParameterInfo>& parameters() const { return _parameters; }
100
100
101 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
101 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
102 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
102 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
103
103
104 protected:
104 protected:
105 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name, PythonQtClassInfo* classInfo);
105 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name, PythonQtClassInfo* classInfo);
106
106
107 static QHash<QByteArray, int> _parameterTypeDict;
107 static QHash<QByteArray, int> _parameterTypeDict;
108 static QHash<QByteArray, QByteArray> _parameterNameAliases;
108 static QHash<QByteArray, QByteArray> _parameterNameAliases;
109
109
110 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
110 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
111 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
111 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
112
112
113 QList<ParameterInfo> _parameters;
113 QList<ParameterInfo> _parameters;
114 };
114 };
115
115
116 //! stores information about a slot, including a next pointer to overloaded slots
116 //! stores information about a slot, including a next pointer to overloaded slots
117 class PythonQtSlotInfo : public PythonQtMethodInfo
117 class PythonQtSlotInfo : public PythonQtMethodInfo
118 {
118 {
119 public:
119 public:
120 enum Type {
120 enum Type {
121 MemberSlot, InstanceDecorator, ClassDecorator
121 MemberSlot, InstanceDecorator, ClassDecorator
122 };
122 };
123
123
124 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
124 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
125 _meta = info._meta;
125 _meta = info._meta;
126 _parameters = info._parameters;
126 _parameters = info._parameters;
127 _slotIndex = info._slotIndex;
127 _slotIndex = info._slotIndex;
128 _next = NULL;
128 _next = NULL;
129 _decorator = info._decorator;
129 _decorator = info._decorator;
130 _type = info._type;
130 _type = info._type;
131 _upcastingOffset = 0;
131 _upcastingOffset = 0;
132 }
132 }
133
133
134 PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
134 PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
135 {
135 {
136 const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo);
136 const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo);
137 _meta = meta;
137 _meta = meta;
138 _parameters = info->parameters();
138 _parameters = info->parameters();
139 _slotIndex = slotIndex;
139 _slotIndex = slotIndex;
140 _next = NULL;
140 _next = NULL;
141 _decorator = decorator;
141 _decorator = decorator;
142 _type = type;
142 _type = type;
143 _upcastingOffset = 0;
143 _upcastingOffset = 0;
144 }
144 }
145
145
146
146
147 public:
147 public:
148
148
149 void deleteOverloadsAndThis();
149 void deleteOverloadsAndThis();
150
150
151 const QMetaMethod* metaMethod() const { return &_meta; }
151 const QMetaMethod* metaMethod() const { return &_meta; }
152
152
153 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
153 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
154
154
155 int upcastingOffset() const { return _upcastingOffset; }
155 int upcastingOffset() const { return _upcastingOffset; }
156
156
157 //! get the index of the slot (needed for qt_metacall)
157 //! get the index of the slot (needed for qt_metacall)
158 int slotIndex() const { return _slotIndex; }
158 int slotIndex() const { return _slotIndex; }
159
159
160 //! get next overloaded slot (which has the same name)
160 //! get next overloaded slot (which has the same name)
161 PythonQtSlotInfo* nextInfo() const { return _next; }
161 PythonQtSlotInfo* nextInfo() const { return _next; }
162
162
163 //! set the next overloaded slot
163 //! set the next overloaded slot
164 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
164 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
165
165
166 //! returns if the slot is a decorator slot
166 //! returns if the slot is a decorator slot
167 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
167 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
168
168
169 //! returns if the slot is a constructor slot
169 //! returns if the slot is a constructor slot
170 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
170 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
171
171
172 QObject* decorator() { return _decorator; }
172 QObject* decorator() { return _decorator; }
173
173
174 //! get the full signature including return type
174 //! get the full signature including return type
175 QString fullSignature();
175 QString fullSignature();
176
176
177 //! get the short slot name
177 //! get the short slot name
178 QByteArray slotName();
178 QByteArray slotName();
179
179
180 private:
180 private:
181 int _slotIndex;
181 int _slotIndex;
182 PythonQtSlotInfo* _next;
182 PythonQtSlotInfo* _next;
183 QObject* _decorator;
183 QObject* _decorator;
184 Type _type;
184 Type _type;
185 QMetaMethod _meta;
185 QMetaMethod _meta;
186 int _upcastingOffset;
186 int _upcastingOffset;
187 };
187 };
188
188
189
189
190 #endif
190 #endif
@@ -1,511 +1,509
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 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
101 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);
102 if (argList[i]==NULL) {
101 if (argList[i]==NULL) {
103 ok = false;
102 ok = false;
104 break;
103 break;
105 }
104 }
106 }
105 }
107 }
106 }
108 } else {
107 } else {
109 for (int i = 1; i<argc && ok; i++) {
108 for (int i = 1; i<argc && ok; i++) {
110 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
109 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
111 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
112 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);
113 if (argList[i]==NULL) {
111 if (argList[i]==NULL) {
114 ok = false;
112 ok = false;
115 break;
113 break;
116 }
114 }
117 }
115 }
118 }
116 }
119
117
120 if (ok) {
118 if (ok) {
121 // 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
122 if (returnValueParam.typeId != QMetaType::Void) {
120 if (returnValueParam.typeId != QMetaType::Void) {
123 // create empty default value for the return value
121 // create empty default value for the return value
124 if (!directReturnValuePointer) {
122 if (!directReturnValuePointer) {
125 // create empty default value for the return value
123 // create empty default value for the return value
126 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
124 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
127 if (argList[0]==NULL) {
125 if (argList[0]==NULL) {
128 // 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
129 // pass its internal pointer
127 // pass its internal pointer
130 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
128 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
131 if (info && info->pythonQtClassWrapper()) {
129 if (info && info->pythonQtClassWrapper()) {
132 PyObject* emptyTuple = PyTuple_New(0);
130 PyObject* emptyTuple = PyTuple_New(0);
133 // 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
134 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
132 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
135 if (result) {
133 if (result) {
136 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
134 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
137 }
135 }
138 Py_DECREF(emptyTuple);
136 Py_DECREF(emptyTuple);
139 }
137 }
140 }
138 }
141 } else {
139 } else {
142 // we can use our pointer directly!
140 // we can use our pointer directly!
143 argList[0] = directReturnValuePointer;
141 argList[0] = directReturnValuePointer;
144 }
142 }
145 }
143 }
146
144
147 // invoke the slot via metacall
145 // invoke the slot via metacall
148 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
146 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
149
147
150 // handle the return value (which in most cases still needs to be converted to a Python object)
148 // handle the return value (which in most cases still needs to be converted to a Python object)
151 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
149 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
152 if (directReturnValuePointer) {
150 if (directReturnValuePointer) {
153 result = NULL;
151 result = NULL;
154 } else {
152 } else {
155 // the resulting object maybe present already, because we created it above at 1)...
153 // the resulting object maybe present already, because we created it above at 1)...
156 if (!result) {
154 if (!result) {
157 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
155 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
158 }
156 }
159 }
157 }
160 } else {
158 } else {
161 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.";
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.";
162 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
160 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
163 result = NULL;
161 result = NULL;
164 }
162 }
165 }
163 }
166 recursiveEntry--;
164 recursiveEntry--;
167
165
168 // reset the parameter storage position to the stored pos to "pop" the parameter stack
166 // reset the parameter storage position to the stored pos to "pop" the parameter stack
169 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
167 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
170 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
168 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
171 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
169 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
172
170
173 *pythonReturnValue = result;
171 *pythonReturnValue = result;
174 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
172 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
175 return result || (directReturnValuePointer && *directReturnValuePointer);
173 return result || (directReturnValuePointer && *directReturnValuePointer);
176 }
174 }
177
175
178 //-----------------------------------------------------------------------------------
176 //-----------------------------------------------------------------------------------
179
177
180 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
178 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
181
179
182 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
180 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
183 {
181 {
184 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
182 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
185 PythonQtSlotInfo* info = f->m_ml;
183 PythonQtSlotInfo* info = f->m_ml;
186 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
184 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
187 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
185 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
188 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
186 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
189 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
187 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
190 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
188 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
191 return NULL;
189 return NULL;
192 } else {
190 } else {
193 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
191 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
194 }
192 }
195 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
193 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
196 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
194 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
197 if (info->isClassDecorator()) {
195 if (info->isClassDecorator()) {
198 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
196 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
199 } else {
197 } else {
200 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
198 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
201 Py_ssize_t argc = PyTuple_Size(args);
199 Py_ssize_t argc = PyTuple_Size(args);
202 if (argc>0) {
200 if (argc>0) {
203 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
201 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
204 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
202 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
205 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
203 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
206 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
204 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
207 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
205 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
208 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
206 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
209 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
207 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
210 return NULL;
208 return NULL;
211 }
209 }
212 // strip the first argument...
210 // strip the first argument...
213 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
211 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
214 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
212 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
215 Py_DECREF(newargs);
213 Py_DECREF(newargs);
216 return result;
214 return result;
217 } else {
215 } else {
218 // first arg is not of correct type!
216 // first arg is not of correct type!
219 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
217 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
220 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
218 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
221 return NULL;
219 return NULL;
222 }
220 }
223 } else {
221 } else {
224 // wrong number of args
222 // wrong number of args
225 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
223 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
226 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
224 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
227 return NULL;
225 return NULL;
228 }
226 }
229 }
227 }
230 }
228 }
231 return NULL;
229 return NULL;
232 }
230 }
233
231
234 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
232 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
235 {
233 {
236 int argc = args?PyTuple_Size(args):0;
234 int argc = args?PyTuple_Size(args):0;
237
235
238 #ifdef PYTHONQT_DEBUG
236 #ifdef PYTHONQT_DEBUG
239 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
237 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
240 #endif
238 #endif
241
239
242 PyObject* r = NULL;
240 PyObject* r = NULL;
243 bool ok = false;
241 bool ok = false;
244 if (directReturnValuePointer) {
242 if (directReturnValuePointer) {
245 *directReturnValuePointer = NULL;
243 *directReturnValuePointer = NULL;
246 }
244 }
247 if (info->nextInfo()) {
245 if (info->nextInfo()) {
248 // overloaded slot call, try on all slots with strict conversion first
246 // overloaded slot call, try on all slots with strict conversion first
249 bool strict = true;
247 bool strict = true;
250 PythonQtSlotInfo* i = info;
248 PythonQtSlotInfo* i = info;
251 while (i) {
249 while (i) {
252 bool skipFirst = i->isInstanceDecorator();
250 bool skipFirst = i->isInstanceDecorator();
253 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
251 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
254 PyErr_Clear();
252 PyErr_Clear();
255 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
253 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
256 if (PyErr_Occurred() || ok) break;
254 if (PyErr_Occurred() || ok) break;
257 }
255 }
258 i = i->nextInfo();
256 i = i->nextInfo();
259 if (!i) {
257 if (!i) {
260 if (strict) {
258 if (strict) {
261 // one more run without being strict
259 // one more run without being strict
262 strict = false;
260 strict = false;
263 i = info;
261 i = info;
264 }
262 }
265 }
263 }
266 }
264 }
267 if (!ok && !PyErr_Occurred()) {
265 if (!ok && !PyErr_Occurred()) {
268 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
266 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
269 PythonQtSlotInfo* i = info;
267 PythonQtSlotInfo* i = info;
270 while (i) {
268 while (i) {
271 e += QString(i->fullSignature()) + "\n";
269 e += QString(i->fullSignature()) + "\n";
272 i = i->nextInfo();
270 i = i->nextInfo();
273 }
271 }
274 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
272 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
275 }
273 }
276 } else {
274 } else {
277 // simple (non-overloaded) slot call
275 // simple (non-overloaded) slot call
278 bool skipFirst = info->isInstanceDecorator();
276 bool skipFirst = info->isInstanceDecorator();
279 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
277 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
280 PyErr_Clear();
278 PyErr_Clear();
281 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
279 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
282 if (!ok && !PyErr_Occurred()) {
280 if (!ok && !PyErr_Occurred()) {
283 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
281 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
284 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
282 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
285 }
283 }
286 } else {
284 } else {
287 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
285 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
288 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
286 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
289 }
287 }
290 }
288 }
291
289
292 return r;
290 return r;
293 }
291 }
294
292
295 PyObject *
293 PyObject *
296 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
294 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
297 {
295 {
298 PythonQtSlotFunctionObject *op;
296 PythonQtSlotFunctionObject *op;
299 op = pythonqtslot_free_list;
297 op = pythonqtslot_free_list;
300 if (op != NULL) {
298 if (op != NULL) {
301 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
299 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
302 PyObject_INIT(op, &PythonQtSlotFunction_Type);
300 PyObject_INIT(op, &PythonQtSlotFunction_Type);
303 }
301 }
304 else {
302 else {
305 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
303 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
306 if (op == NULL)
304 if (op == NULL)
307 return NULL;
305 return NULL;
308 }
306 }
309 op->m_ml = ml;
307 op->m_ml = ml;
310 Py_XINCREF(self);
308 Py_XINCREF(self);
311 op->m_self = self;
309 op->m_self = self;
312 Py_XINCREF(module);
310 Py_XINCREF(module);
313 op->m_module = module;
311 op->m_module = module;
314 PyObject_GC_Track(op);
312 PyObject_GC_Track(op);
315 return (PyObject *)op;
313 return (PyObject *)op;
316 }
314 }
317
315
318 PythonQtSlotInfo*
316 PythonQtSlotInfo*
319 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
317 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
320 {
318 {
321 if (!PythonQtSlotFunction_Check(op)) {
319 if (!PythonQtSlotFunction_Check(op)) {
322 PyErr_BadInternalCall();
320 PyErr_BadInternalCall();
323 return NULL;
321 return NULL;
324 }
322 }
325 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
323 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
326 }
324 }
327
325
328 PyObject *
326 PyObject *
329 PythonQtSlotFunction_GetSelf(PyObject *op)
327 PythonQtSlotFunction_GetSelf(PyObject *op)
330 {
328 {
331 if (!PythonQtSlotFunction_Check(op)) {
329 if (!PythonQtSlotFunction_Check(op)) {
332 PyErr_BadInternalCall();
330 PyErr_BadInternalCall();
333 return NULL;
331 return NULL;
334 }
332 }
335 return ((PythonQtSlotFunctionObject *)op) -> m_self;
333 return ((PythonQtSlotFunctionObject *)op) -> m_self;
336 }
334 }
337
335
338 /* Methods (the standard built-in methods, that is) */
336 /* Methods (the standard built-in methods, that is) */
339
337
340 static void
338 static void
341 meth_dealloc(PythonQtSlotFunctionObject *m)
339 meth_dealloc(PythonQtSlotFunctionObject *m)
342 {
340 {
343 PyObject_GC_UnTrack(m);
341 PyObject_GC_UnTrack(m);
344 Py_XDECREF(m->m_self);
342 Py_XDECREF(m->m_self);
345 Py_XDECREF(m->m_module);
343 Py_XDECREF(m->m_module);
346 m->m_self = (PyObject *)pythonqtslot_free_list;
344 m->m_self = (PyObject *)pythonqtslot_free_list;
347 pythonqtslot_free_list = m;
345 pythonqtslot_free_list = m;
348 }
346 }
349
347
350 static PyObject *
348 static PyObject *
351 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
349 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
352 {
350 {
353 Py_INCREF(Py_None);
351 Py_INCREF(Py_None);
354 return Py_None;
352 return Py_None;
355 }
353 }
356
354
357 static PyObject *
355 static PyObject *
358 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
356 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
359 {
357 {
360 return PyString_FromString(m->m_ml->metaMethod()->signature());
358 return PyString_FromString(m->m_ml->metaMethod()->signature());
361 }
359 }
362
360
363 static int
361 static int
364 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
362 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
365 {
363 {
366 int err;
364 int err;
367 if (m->m_self != NULL) {
365 if (m->m_self != NULL) {
368 err = visit(m->m_self, arg);
366 err = visit(m->m_self, arg);
369 if (err)
367 if (err)
370 return err;
368 return err;
371 }
369 }
372 if (m->m_module != NULL) {
370 if (m->m_module != NULL) {
373 err = visit(m->m_module, arg);
371 err = visit(m->m_module, arg);
374 if (err)
372 if (err)
375 return err;
373 return err;
376 }
374 }
377 return 0;
375 return 0;
378 }
376 }
379
377
380 static PyObject *
378 static PyObject *
381 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
379 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
382 {
380 {
383 PyObject *self;
381 PyObject *self;
384 if (PyEval_GetRestricted()) {
382 if (PyEval_GetRestricted()) {
385 PyErr_SetString(PyExc_RuntimeError,
383 PyErr_SetString(PyExc_RuntimeError,
386 "method.__self__ not accessible in restricted mode");
384 "method.__self__ not accessible in restricted mode");
387 return NULL;
385 return NULL;
388 }
386 }
389 self = m->m_self;
387 self = m->m_self;
390 if (self == NULL)
388 if (self == NULL)
391 self = Py_None;
389 self = Py_None;
392 Py_INCREF(self);
390 Py_INCREF(self);
393 return self;
391 return self;
394 }
392 }
395
393
396 static PyGetSetDef meth_getsets [] = {
394 static PyGetSetDef meth_getsets [] = {
397 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
395 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
398 {"__name__", (getter)meth_get__name__, NULL, NULL},
396 {"__name__", (getter)meth_get__name__, NULL, NULL},
399 {"__self__", (getter)meth_get__self__, NULL, NULL},
397 {"__self__", (getter)meth_get__self__, NULL, NULL},
400 {NULL, NULL, NULL,NULL},
398 {NULL, NULL, NULL,NULL},
401 };
399 };
402
400
403 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
401 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
404 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
402 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
405 #endif
403 #endif
406
404
407 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
405 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
408
406
409 static PyMemberDef meth_members[] = {
407 static PyMemberDef meth_members[] = {
410 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
408 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
411 {NULL}
409 {NULL}
412 };
410 };
413
411
414 static PyObject *
412 static PyObject *
415 meth_repr(PythonQtSlotFunctionObject *f)
413 meth_repr(PythonQtSlotFunctionObject *f)
416 {
414 {
417 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
415 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
418 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
416 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
419 return PyString_FromFormat("<unbound qt slot %s of %s type>",
417 return PyString_FromFormat("<unbound qt slot %s of %s type>",
420 f->m_ml->slotName().data(),
418 f->m_ml->slotName().data(),
421 self->classInfo()->className());
419 self->classInfo()->className());
422 } else {
420 } else {
423 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
421 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
424 f->m_ml->slotName().data(),
422 f->m_ml->slotName().data(),
425 f->m_self->ob_type->tp_name,
423 f->m_self->ob_type->tp_name,
426 f->m_self);
424 f->m_self);
427 }
425 }
428 }
426 }
429
427
430 static int
428 static int
431 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
429 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
432 {
430 {
433 if (a->m_self != b->m_self)
431 if (a->m_self != b->m_self)
434 return (a->m_self < b->m_self) ? -1 : 1;
432 return (a->m_self < b->m_self) ? -1 : 1;
435 if (a->m_ml == b->m_ml)
433 if (a->m_ml == b->m_ml)
436 return 0;
434 return 0;
437 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
435 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
438 return -1;
436 return -1;
439 else
437 else
440 return 1;
438 return 1;
441 }
439 }
442
440
443 static long
441 static long
444 meth_hash(PythonQtSlotFunctionObject *a)
442 meth_hash(PythonQtSlotFunctionObject *a)
445 {
443 {
446 long x,y;
444 long x,y;
447 if (a->m_self == NULL)
445 if (a->m_self == NULL)
448 x = 0;
446 x = 0;
449 else {
447 else {
450 x = PyObject_Hash(a->m_self);
448 x = PyObject_Hash(a->m_self);
451 if (x == -1)
449 if (x == -1)
452 return -1;
450 return -1;
453 }
451 }
454 y = _Py_HashPointer((void*)(a->m_ml));
452 y = _Py_HashPointer((void*)(a->m_ml));
455 if (y == -1)
453 if (y == -1)
456 return -1;
454 return -1;
457 x ^= y;
455 x ^= y;
458 if (x == -1)
456 if (x == -1)
459 x = -2;
457 x = -2;
460 return x;
458 return x;
461 }
459 }
462
460
463
461
464 PyTypeObject PythonQtSlotFunction_Type = {
462 PyTypeObject PythonQtSlotFunction_Type = {
465 PyObject_HEAD_INIT(&PyType_Type)
463 PyObject_HEAD_INIT(&PyType_Type)
466 0,
464 0,
467 "builtin_qt_slot",
465 "builtin_qt_slot",
468 sizeof(PythonQtSlotFunctionObject),
466 sizeof(PythonQtSlotFunctionObject),
469 0,
467 0,
470 (destructor)meth_dealloc, /* tp_dealloc */
468 (destructor)meth_dealloc, /* tp_dealloc */
471 0, /* tp_print */
469 0, /* tp_print */
472 0, /* tp_getattr */
470 0, /* tp_getattr */
473 0, /* tp_setattr */
471 0, /* tp_setattr */
474 (cmpfunc)meth_compare, /* tp_compare */
472 (cmpfunc)meth_compare, /* tp_compare */
475 (reprfunc)meth_repr, /* tp_repr */
473 (reprfunc)meth_repr, /* tp_repr */
476 0, /* tp_as_number */
474 0, /* tp_as_number */
477 0, /* tp_as_sequence */
475 0, /* tp_as_sequence */
478 0, /* tp_as_mapping */
476 0, /* tp_as_mapping */
479 (hashfunc)meth_hash, /* tp_hash */
477 (hashfunc)meth_hash, /* tp_hash */
480 PythonQtSlotFunction_Call, /* tp_call */
478 PythonQtSlotFunction_Call, /* tp_call */
481 0, /* tp_str */
479 0, /* tp_str */
482 PyObject_GenericGetAttr, /* tp_getattro */
480 PyObject_GenericGetAttr, /* tp_getattro */
483 0, /* tp_setattro */
481 0, /* tp_setattro */
484 0, /* tp_as_buffer */
482 0, /* tp_as_buffer */
485 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
483 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
486 0, /* tp_doc */
484 0, /* tp_doc */
487 (traverseproc)meth_traverse, /* tp_traverse */
485 (traverseproc)meth_traverse, /* tp_traverse */
488 0, /* tp_clear */
486 0, /* tp_clear */
489 0, /* tp_richcompare */
487 0, /* tp_richcompare */
490 0, /* tp_weaklistoffset */
488 0, /* tp_weaklistoffset */
491 0, /* tp_iter */
489 0, /* tp_iter */
492 0, /* tp_iternext */
490 0, /* tp_iternext */
493 0, /* tp_methods */
491 0, /* tp_methods */
494 meth_members, /* tp_members */
492 meth_members, /* tp_members */
495 meth_getsets, /* tp_getset */
493 meth_getsets, /* tp_getset */
496 0, /* tp_base */
494 0, /* tp_base */
497 0, /* tp_dict */
495 0, /* tp_dict */
498 };
496 };
499
497
500 /* Clear out the free list */
498 /* Clear out the free list */
501
499
502 void
500 void
503 PythonQtSlotFunction_Fini(void)
501 PythonQtSlotFunction_Fini(void)
504 {
502 {
505 while (pythonqtslot_free_list) {
503 while (pythonqtslot_free_list) {
506 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
504 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
507 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
505 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
508 PyObject_GC_Del(v);
506 PyObject_GC_Del(v);
509 }
507 }
510 }
508 }
511
509
General Comments 0
You need to be logged in to leave comments. Login now