##// END OF EJS Templates
florianlink -
r161:87322f2ddb44
parent child
Show More
@@ -1,1258 +1,1318
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 "PythonQtStdIn.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
53 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
54 #include <pydebug.h>
54 #include <vector>
55 #include <vector>
55
56
56 PythonQt* PythonQt::_self = NULL;
57 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
58 int PythonQt::_uniqueModuleCount = 0;
58
59
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
61 void PythonQt_init_QtCoreBuiltin(PyObject*);
61
62
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 {
64 {
64 if (!_self) {
65 if (!_self) {
65 _self = new PythonQt(flags, pythonQtModuleName);
66 _self = new PythonQt(flags, pythonQtModuleName);
66
67
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69
70
70 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 // TODO: which other POD types should be available for QList etc.
78 // TODO: which other POD types should be available for QList etc.
78
79
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80
81
81 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
83 PythonQt_init_QtGuiBuiltin(NULL);
83
84
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99
100
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117
118
118
119
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
123 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 for (unsigned int i = 0;i<16; i++) {
125 for (unsigned int i = 0;i<16; i++) {
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 if (obj) {
127 if (obj) {
127 PyModule_AddObject(pack, names[i], obj);
128 PyModule_AddObject(pack, names[i], obj);
128 Py_INCREF(obj);
129 Py_INCREF(obj);
129 PyModule_AddObject(pack2, names[i], obj);
130 PyModule_AddObject(pack2, names[i], obj);
130 } else {
131 } else {
131 std::cerr << "method not found " << names[i];
132 std::cerr << "method not found " << names[i];
132 }
133 }
133 }
134 }
134 }
135 }
135 }
136 }
136
137
137 void PythonQt::cleanup()
138 void PythonQt::cleanup()
138 {
139 {
139 if (_self) {
140 if (_self) {
140 delete _self;
141 delete _self;
141 _self = NULL;
142 _self = NULL;
142 }
143 }
143 }
144 }
144
145
146 PythonQt* PythonQt::self() { return _self; }
147
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
148 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
146 {
149 {
147 _p = new PythonQtPrivate;
150 _p = new PythonQtPrivate;
148 _p->_initFlags = flags;
151 _p->_initFlags = flags;
149
152
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
153 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
151
154
152 if ((flags & PythonAlreadyInitialized) == 0) {
155 if ((flags & PythonAlreadyInitialized) == 0) {
153 Py_SetProgramName("PythonQt");
156 Py_SetProgramName(const_cast<char*>("PythonQt"));
154 if (flags & IgnoreSiteModule) {
157 if (flags & IgnoreSiteModule) {
155 // this prevents the automatic importing of Python site files
158 // this prevents the automatic importing of Python site files
156 Py_NoSiteFlag = 1;
159 Py_NoSiteFlag = 1;
157 }
160 }
158 Py_Initialize();
161 Py_Initialize();
159 }
162 }
160
163
161 // add our own python object types for qt object slots
164 // add our own python object types for qt object slots
162 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
165 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
163 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
166 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
164 }
167 }
165 Py_INCREF(&PythonQtSlotFunction_Type);
168 Py_INCREF(&PythonQtSlotFunction_Type);
166
169
167 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
170 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
168 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
171 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
169 // add our own python object types for classes
172 // add our own python object types for classes
170 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
173 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
171 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
174 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
172 }
175 }
173 Py_INCREF(&PythonQtClassWrapper_Type);
176 Py_INCREF(&PythonQtClassWrapper_Type);
174
177
175 // add our own python object types for CPP instances
178 // add our own python object types for CPP instances
176 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
179 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
177 PythonQt::handleError();
180 PythonQt::handleError();
178 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
181 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 }
182 }
180 Py_INCREF(&PythonQtInstanceWrapper_Type);
183 Py_INCREF(&PythonQtInstanceWrapper_Type);
181
184
182 // add our own python object types for redirection of stdout
185 // add our own python object types for redirection of stdout
183 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
184 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
187 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
188 }
186 Py_INCREF(&PythonQtStdOutRedirectType);
189 Py_INCREF(&PythonQtStdOutRedirectType);
187
190
191 // add our own python object types for redirection of stdin
192 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
193 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
194 }
195 Py_INCREF(&PythonQtStdInRedirectType);
196
188 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
197 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
189
198
190 _p->setupSharedLibrarySuffixes();
199 _p->setupSharedLibrarySuffixes();
191
200
192 }
201 }
193
202
194 PythonQt::~PythonQt() {
203 PythonQt::~PythonQt() {
195 delete _p;
204 delete _p;
196 _p = NULL;
205 _p = NULL;
197 }
206 }
198
207
199 PythonQtPrivate::~PythonQtPrivate() {
208 PythonQtPrivate::~PythonQtPrivate() {
200 delete _defaultImporter;
209 delete _defaultImporter;
201 _defaultImporter = NULL;
210 _defaultImporter = NULL;
202
211
203 {
212 {
204 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
213 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
205 while (i.hasNext()) {
214 while (i.hasNext()) {
206 delete i.next().value();
215 delete i.next().value();
207 }
216 }
208 }
217 }
209 PythonQtConv::global_valueStorage.clear();
218 PythonQtConv::global_valueStorage.clear();
210 PythonQtConv::global_ptrStorage.clear();
219 PythonQtConv::global_ptrStorage.clear();
211 PythonQtConv::global_variantStorage.clear();
220 PythonQtConv::global_variantStorage.clear();
212
221
213 PythonQtMethodInfo::cleanupCachedMethodInfos();
222 PythonQtMethodInfo::cleanupCachedMethodInfos();
214 }
223 }
215
224
225 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
226 {
227 if (!callback)
228 {
229 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
230 return;
231 }
232
233 PythonQtObjectPtr sys;
234 PythonQtObjectPtr in;
235 sys.setNewRef(PyImport_ImportModule("sys"));
236
237 // Backup original 'sys.stdin' if not yet done
238 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
239 "sys.pythonqt_original_stdin = sys.stdin");
240
241 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
242 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
243 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
244 // replace the built in file objects with our own objects
245 PyModule_AddObject(sys, "stdin", in);
246
247 // Backup custom 'stdin' into 'pythonqt_stdin'
248 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
249 }
250
251 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
252 {
253 if (enabled)
254 {
255 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
256 "sys.stdin = sys.pythonqt_stdin");
257 }
258 else
259 {
260 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
261 "sys.stdin = sys.pythonqt_original_stdin");
262 }
263 }
264
216 PythonQtImportFileInterface* PythonQt::importInterface()
265 PythonQtImportFileInterface* PythonQt::importInterface()
217 {
266 {
218 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
267 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
219 }
268 }
220
269
221 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
270 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
222 {
271 {
223 if (_self->_p->_noLongerWrappedCB) {
272 if (_self->_p->_noLongerWrappedCB) {
224 (*_self->_p->_noLongerWrappedCB)(o);
273 (*_self->_p->_noLongerWrappedCB)(o);
225 };
274 };
226 }
275 }
227
276
228 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
277 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
229 {
278 {
230 _p->registerClass(metaobject, package, wrapperCreator, shell);
279 _p->registerClass(metaobject, package, wrapperCreator, shell);
231 }
280 }
232
281
233 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
282 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
234 {
283 {
235 // we register all classes in the hierarchy
284 // we register all classes in the hierarchy
236 const QMetaObject* m = metaobject;
285 const QMetaObject* m = metaobject;
237 bool first = true;
286 bool first = true;
238 while (m) {
287 while (m) {
239 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
288 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
240 if (!info->pythonQtClassWrapper()) {
289 if (!info->pythonQtClassWrapper()) {
241 info->setTypeSlots(typeSlots);
290 info->setTypeSlots(typeSlots);
242 info->setupQObject(m);
291 info->setupQObject(m);
243 createPythonQtClassWrapper(info, package, module);
292 createPythonQtClassWrapper(info, package, module);
244 if (m->superClass()) {
293 if (m->superClass()) {
245 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
294 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
246 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
295 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
247 }
296 }
248 } else if (first && module) {
297 } else if (first && module) {
249 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
298 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
250 // since it might have been placed into "private" earlier on.
299 // since it might have been placed into "private" earlier on.
251 // If the wrapper was already added to module before, it is just readded, which does no harm.
300 // If the wrapper was already added to module before, it is just readded, which does no harm.
252 PyObject* classWrapper = info->pythonQtClassWrapper();
301 PyObject* classWrapper = info->pythonQtClassWrapper();
253 // AddObject steals a reference, so we need to INCREF
302 // AddObject steals a reference, so we need to INCREF
254 Py_INCREF(classWrapper);
303 Py_INCREF(classWrapper);
255 PyModule_AddObject(module, info->className(), classWrapper);
304 PyModule_AddObject(module, info->className(), classWrapper);
256 }
305 }
257 if (first) {
306 if (first) {
258 first = false;
307 first = false;
259 if (wrapperCreator) {
308 if (wrapperCreator) {
260 info->setDecoratorProvider(wrapperCreator);
309 info->setDecoratorProvider(wrapperCreator);
261 }
310 }
262 if (shell) {
311 if (shell) {
263 info->setShellSetInstanceWrapperCB(shell);
312 info->setShellSetInstanceWrapperCB(shell);
264 }
313 }
265 }
314 }
266 m = m->superClass();
315 m = m->superClass();
267 }
316 }
268 }
317 }
269
318
270 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
319 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
271 {
320 {
272 PyObject* pack = module?module:packageByName(package);
321 PyObject* pack = module?module:packageByName(package);
273 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
322 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
274 PyModule_AddObject(pack, info->className(), pyobj);
323 PyModule_AddObject(pack, info->className(), pyobj);
275 if (!module && package && strncmp(package,"Qt",2)==0) {
324 if (!module && package && strncmp(package,"Qt",2)==0) {
276 // since PyModule_AddObject steals the reference, we need a incref once more...
325 // since PyModule_AddObject steals the reference, we need a incref once more...
277 Py_INCREF(pyobj);
326 Py_INCREF(pyobj);
278 // put all qt objects into Qt as well
327 // put all qt objects into Qt as well
279 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
328 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
280 }
329 }
281 info->setPythonQtClassWrapper(pyobj);
330 info->setPythonQtClassWrapper(pyobj);
282 }
331 }
283
332
284 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
333 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
285 {
334 {
286 if (!obj) {
335 if (!obj) {
287 Py_INCREF(Py_None);
336 Py_INCREF(Py_None);
288 return Py_None;
337 return Py_None;
289 }
338 }
290 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
339 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
291 if (!wrap) {
340 if (!wrap) {
292 // smuggling it in...
341 // smuggling it in...
293 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
342 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
294 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
343 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
295 registerClass(obj->metaObject());
344 registerClass(obj->metaObject());
296 classInfo = _knownClassInfos.value(obj->metaObject()->className());
345 classInfo = _knownClassInfos.value(obj->metaObject()->className());
297 }
346 }
298 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
347 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
299 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
348 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
300 } else {
349 } else {
301 Py_INCREF(wrap);
350 Py_INCREF(wrap);
302 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
351 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
303 }
352 }
304 return (PyObject*)wrap;
353 return (PyObject*)wrap;
305 }
354 }
306
355
307 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
356 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
308 {
357 {
309 if (!ptr) {
358 if (!ptr) {
310 Py_INCREF(Py_None);
359 Py_INCREF(Py_None);
311 return Py_None;
360 return Py_None;
312 }
361 }
313
362
314 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
315 if (!wrap) {
364 if (!wrap) {
316 PythonQtClassInfo* info = _knownClassInfos.value(name);
365 PythonQtClassInfo* info = _knownClassInfos.value(name);
317 if (!info) {
366 if (!info) {
318 // maybe it is a PyObject, which we can return directly
367 // maybe it is a PyObject, which we can return directly
319 if (name == "PyObject") {
368 if (name == "PyObject") {
320 PyObject* p = (PyObject*)ptr;
369 PyObject* p = (PyObject*)ptr;
321 Py_INCREF(p);
370 Py_INCREF(p);
322 return p;
371 return p;
323 }
372 }
324
373
325 // we do not know the metaobject yet, but we might know it by it's name:
374 // we do not know the metaobject yet, but we might know it by it's name:
326 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
375 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
327 // yes, we know it, so we can convert to QObject
376 // yes, we know it, so we can convert to QObject
328 QObject* qptr = (QObject*)ptr;
377 QObject* qptr = (QObject*)ptr;
329 registerClass(qptr->metaObject());
378 registerClass(qptr->metaObject());
330 info = _knownClassInfos.value(qptr->metaObject()->className());
379 info = _knownClassInfos.value(qptr->metaObject()->className());
331 }
380 }
332 }
381 }
333 if (info && info->isQObject()) {
382 if (info && info->isQObject()) {
334 QObject* qptr = (QObject*)ptr;
383 QObject* qptr = (QObject*)ptr;
335 // if the object is a derived object, we want to switch the class info to the one of the derived class:
384 // if the object is a derived object, we want to switch the class info to the one of the derived class:
336 if (name!=(qptr->metaObject()->className())) {
385 if (name!=(qptr->metaObject()->className())) {
337 registerClass(qptr->metaObject());
386 registerClass(qptr->metaObject());
338 info = _knownClassInfos.value(qptr->metaObject()->className());
387 info = _knownClassInfos.value(qptr->metaObject()->className());
339 }
388 }
340 wrap = createNewPythonQtInstanceWrapper(qptr, info);
389 wrap = createNewPythonQtInstanceWrapper(qptr, info);
341 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
390 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
342 return (PyObject*)wrap;
391 return (PyObject*)wrap;
343 }
392 }
344
393
345 // not a known QObject, so try our wrapper factory:
394 // not a known QObject, so try our wrapper factory:
346 QObject* wrapper = NULL;
395 QObject* wrapper = NULL;
347 for (int i=0; i<_cppWrapperFactories.size(); i++) {
396 for (int i=0; i<_cppWrapperFactories.size(); i++) {
348 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
397 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
349 if (wrapper) {
398 if (wrapper) {
350 break;
399 break;
351 }
400 }
352 }
401 }
353
402
354 if (info) {
403 if (info) {
355 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
404 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
356 ptr = info->castDownIfPossible(ptr, &info);
405 ptr = info->castDownIfPossible(ptr, &info);
357 }
406 }
358
407
359 if (!info || info->pythonQtClassWrapper()==NULL) {
408 if (!info || info->pythonQtClassWrapper()==NULL) {
360 // still unknown, register as CPP class
409 // still unknown, register as CPP class
361 registerCPPClass(name.constData());
410 registerCPPClass(name.constData());
362 info = _knownClassInfos.value(name);
411 info = _knownClassInfos.value(name);
363 }
412 }
364 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
413 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
365 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
414 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
366 info->setMetaObject(wrapper->metaObject());
415 info->setMetaObject(wrapper->metaObject());
367 }
416 }
417
418 // TODO XXX: delegate wrapping via CB here (pass name and ptr)
419
368 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
420 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
369 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
421 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
370 } else {
422 } else {
371 Py_INCREF(wrap);
423 Py_INCREF(wrap);
372 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
424 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
373 }
425 }
374 return (PyObject*)wrap;
426 return (PyObject*)wrap;
375 }
427 }
376
428
377 PyObject* PythonQtPrivate::dummyTuple() {
429 PyObject* PythonQtPrivate::dummyTuple() {
378 static PyObject* dummyTuple = NULL;
430 static PyObject* dummyTuple = NULL;
379 if (dummyTuple==NULL) {
431 if (dummyTuple==NULL) {
380 dummyTuple = PyTuple_New(1);
432 dummyTuple = PyTuple_New(1);
381 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
433 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
382 }
434 }
383 return dummyTuple;
435 return dummyTuple;
384 }
436 }
385
437
386
438
387 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
439 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
388 // call the associated class type to create a new instance...
440 // call the associated class type to create a new instance...
389 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
441 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
390
442
391 result->setQObject(obj);
443 result->setQObject(obj);
392 result->_wrappedPtr = wrappedPtr;
444 result->_wrappedPtr = wrappedPtr;
393 result->_ownedByPythonQt = false;
445 result->_ownedByPythonQt = false;
394 result->_useQMetaTypeDestroy = false;
446 result->_useQMetaTypeDestroy = false;
395
447
396 if (wrappedPtr) {
448 if (wrappedPtr) {
397 _wrappedObjects.insert(wrappedPtr, result);
449 _wrappedObjects.insert(wrappedPtr, result);
398 } else {
450 } else {
399 _wrappedObjects.insert(obj, result);
451 _wrappedObjects.insert(obj, result);
400 if (obj->parent()== NULL && _wrappedCB) {
452 if (obj->parent()== NULL && _wrappedCB) {
401 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
453 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
402 (*_wrappedCB)(obj);
454 (*_wrappedCB)(obj);
403 }
455 }
404 }
456 }
405 return result;
457 return result;
406 }
458 }
407
459
408 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
460 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
409 PythonQtClassWrapper* result;
461 PythonQtClassWrapper* result;
410
462
411 PyObject* className = PyString_FromString(info->className());
463 PyObject* className = PyString_FromString(info->className());
412
464
413 PyObject* baseClasses = PyTuple_New(1);
465 PyObject* baseClasses = PyTuple_New(1);
414 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
466 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
415
467
416 PyObject* typeDict = PyDict_New();
468 PyObject* typeDict = PyDict_New();
417 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
469 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
418 PyDict_SetItemString(typeDict, "__module__", moduleName);
470 PyDict_SetItemString(typeDict, "__module__", moduleName);
419
471
420 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
472 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
421
473
422 // set the class info so that PythonQtClassWrapper_new can read it
474 // set the class info so that PythonQtClassWrapper_new can read it
423 _currentClassInfoForClassWrapperCreation = info;
475 _currentClassInfoForClassWrapperCreation = info;
424 // create the new type object by calling the type
476 // create the new type object by calling the type
425 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
477 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
426
478
427 Py_DECREF(baseClasses);
479 Py_DECREF(baseClasses);
428 Py_DECREF(typeDict);
480 Py_DECREF(typeDict);
429 Py_DECREF(args);
481 Py_DECREF(args);
430 Py_DECREF(className);
482 Py_DECREF(className);
431
483
432 return result;
484 return result;
433 }
485 }
434
486
435 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
487 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
436 {
488 {
437 PyObject* args = Py_BuildValue("(i)", enumValue);
489 PyObject* args = Py_BuildValue("(i)", enumValue);
438 PyObject* result = PyObject_Call(enumType, args, NULL);
490 PyObject* result = PyObject_Call(enumType, args, NULL);
439 Py_DECREF(args);
491 Py_DECREF(args);
440 return result;
492 return result;
441 }
493 }
442
494
443 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
495 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
444 PyObject* result;
496 PyObject* result;
445
497
446 PyObject* className = PyString_FromString(enumName);
498 PyObject* className = PyString_FromString(enumName);
447
499
448 PyObject* baseClasses = PyTuple_New(1);
500 PyObject* baseClasses = PyTuple_New(1);
449 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
501 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
450
502
451 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
503 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
452 PyObject* typeDict = PyDict_New();
504 PyObject* typeDict = PyDict_New();
453 PyDict_SetItemString(typeDict, "__module__", module);
505 PyDict_SetItemString(typeDict, "__module__", module);
454
506
455 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
507 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
456
508
457 // create the new int derived type object by calling the core type
509 // create the new int derived type object by calling the core type
458 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
510 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
459
511
460 Py_DECREF(baseClasses);
512 Py_DECREF(baseClasses);
461 Py_DECREF(typeDict);
513 Py_DECREF(typeDict);
462 Py_DECREF(args);
514 Py_DECREF(args);
463 Py_DECREF(className);
515 Py_DECREF(className);
464
516
465 return result;
517 return result;
466 }
518 }
467
519
468 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
520 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
469 {
521 {
470 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
522 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
471 if (!r) {
523 if (!r) {
472 r = new PythonQtSignalReceiver(obj);
524 r = new PythonQtSignalReceiver(obj);
473 _p->_signalReceivers.insert(obj, r);
525 _p->_signalReceivers.insert(obj, r);
474 }
526 }
475 return r;
527 return r;
476 }
528 }
477
529
478 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
530 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
479 {
531 {
480 bool flag = false;
532 bool flag = false;
481 PythonQtObjectPtr callable = lookupCallable(module, objectname);
533 PythonQtObjectPtr callable = lookupCallable(module, objectname);
482 if (callable) {
534 if (callable) {
483 PythonQtSignalReceiver* r = getSignalReceiver(obj);
535 PythonQtSignalReceiver* r = getSignalReceiver(obj);
484 flag = r->addSignalHandler(signal, callable);
536 flag = r->addSignalHandler(signal, callable);
485 if (!flag) {
537 if (!flag) {
486 // signal not found
538 // signal not found
487 }
539 }
488 } else {
540 } else {
489 // callable not found
541 // callable not found
490 }
542 }
491 return flag;
543 return flag;
492 }
544 }
493
545
494 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
546 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
495 {
547 {
496 bool flag = false;
548 bool flag = false;
497 PythonQtSignalReceiver* r = getSignalReceiver(obj);
549 PythonQtSignalReceiver* r = getSignalReceiver(obj);
498 if (r) {
550 if (r) {
499 flag = r->addSignalHandler(signal, receiver);
551 flag = r->addSignalHandler(signal, receiver);
500 }
552 }
501 return flag;
553 return flag;
502 }
554 }
503
555
504 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
556 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
505 {
557 {
506 bool flag = false;
558 bool flag = false;
507 PythonQtObjectPtr callable = lookupCallable(module, objectname);
559 PythonQtObjectPtr callable = lookupCallable(module, objectname);
508 if (callable) {
560 if (callable) {
509 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
561 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
510 if (r) {
562 if (r) {
511 flag = r->removeSignalHandler(signal, callable);
563 flag = r->removeSignalHandler(signal, callable);
512 }
564 }
513 } else {
565 } else {
514 // callable not found
566 // callable not found
515 }
567 }
516 return flag;
568 return flag;
517 }
569 }
518
570
519 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
571 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
520 {
572 {
521 bool flag = false;
573 bool flag = false;
522 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
574 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
523 if (r) {
575 if (r) {
524 flag = r->removeSignalHandler(signal, receiver);
576 flag = r->removeSignalHandler(signal, receiver);
525 }
577 }
526 return flag;
578 return flag;
527 }
579 }
528
580
529 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
581 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
530 {
582 {
531 PythonQtObjectPtr p = lookupObject(module, name);
583 PythonQtObjectPtr p = lookupObject(module, name);
532 if (p) {
584 if (p) {
533 if (PyCallable_Check(p)) {
585 if (PyCallable_Check(p)) {
534 return p;
586 return p;
535 }
587 }
536 }
588 }
537 PyErr_Clear();
589 PyErr_Clear();
538 return NULL;
590 return NULL;
539 }
591 }
540
592
541 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
593 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
542 {
594 {
543 QStringList l = name.split('.');
595 QStringList l = name.split('.');
544 PythonQtObjectPtr p = module;
596 PythonQtObjectPtr p = module;
545 PythonQtObjectPtr prev;
597 PythonQtObjectPtr prev;
546 QString s;
598 QString s;
547 QByteArray b;
599 QByteArray b;
548 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
600 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
549 prev = p;
601 prev = p;
550 b = (*i).toLatin1();
602 b = (*i).toLatin1();
551 if (PyDict_Check(p)) {
603 if (PyDict_Check(p)) {
552 p = PyDict_GetItemString(p, b.data());
604 p = PyDict_GetItemString(p, b.data());
553 } else {
605 } else {
554 p.setNewRef(PyObject_GetAttrString(p, b.data()));
606 p.setNewRef(PyObject_GetAttrString(p, b.data()));
555 }
607 }
556 }
608 }
557 PyErr_Clear();
609 PyErr_Clear();
558 return p;
610 return p;
559 }
611 }
560
612
561 PythonQtObjectPtr PythonQt::getMainModule() {
613 PythonQtObjectPtr PythonQt::getMainModule() {
562 //both borrowed
614 //both borrowed
563 PythonQtObjectPtr dict = PyImport_GetModuleDict();
615 PythonQtObjectPtr dict = PyImport_GetModuleDict();
564 return PyDict_GetItemString(dict, "__main__");
616 return PyDict_GetItemString(dict, "__main__");
565 }
617 }
566
618
567 PythonQtObjectPtr PythonQt::importModule(const QString& name)
619 PythonQtObjectPtr PythonQt::importModule(const QString& name)
568 {
620 {
569 PythonQtObjectPtr mod;
621 PythonQtObjectPtr mod;
570 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
622 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
571 return mod;
623 return mod;
572 }
624 }
573
625
574
626
575 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
627 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
576 QVariant result;
628 QVariant result;
577 if (pycode) {
629 if (pycode) {
578 PyObject* dict = NULL;
630 PyObject* dict = NULL;
579 if (PyModule_Check(object)) {
631 if (PyModule_Check(object)) {
580 dict = PyModule_GetDict(object);
632 dict = PyModule_GetDict(object);
581 } else if (PyDict_Check(object)) {
633 } else if (PyDict_Check(object)) {
582 dict = object;
634 dict = object;
583 }
635 }
584 PyObject* r = NULL;
636 PyObject* r = NULL;
585 if (dict) {
637 if (dict) {
586 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
638 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
587 }
639 }
588 if (r) {
640 if (r) {
589 result = PythonQtConv::PyObjToQVariant(r);
641 result = PythonQtConv::PyObjToQVariant(r);
590 Py_DECREF(r);
642 Py_DECREF(r);
591 } else {
643 } else {
592 handleError();
644 handleError();
593 }
645 }
594 } else {
646 } else {
595 handleError();
647 handleError();
596 }
648 }
597 return result;
649 return result;
598 }
650 }
599
651
600 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
652 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
601 {
653 {
602 QVariant result;
654 QVariant result;
603 PythonQtObjectPtr p;
655 PythonQtObjectPtr p;
604 PyObject* dict = NULL;
656 PyObject* dict = NULL;
605 if (PyModule_Check(object)) {
657 if (PyModule_Check(object)) {
606 dict = PyModule_GetDict(object);
658 dict = PyModule_GetDict(object);
607 } else if (PyDict_Check(object)) {
659 } else if (PyDict_Check(object)) {
608 dict = object;
660 dict = object;
609 }
661 }
610 if (dict) {
662 if (dict) {
611 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
663 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
612 }
664 }
613 if (p) {
665 if (p) {
614 result = PythonQtConv::PyObjToQVariant(p);
666 result = PythonQtConv::PyObjToQVariant(p);
615 } else {
667 } else {
616 handleError();
668 handleError();
617 }
669 }
618 return result;
670 return result;
619 }
671 }
620
672
621 void PythonQt::evalFile(PyObject* module, const QString& filename)
673 void PythonQt::evalFile(PyObject* module, const QString& filename)
622 {
674 {
623 PythonQtObjectPtr code = parseFile(filename);
675 PythonQtObjectPtr code = parseFile(filename);
624 if (code) {
676 if (code) {
625 evalCode(module, code);
677 evalCode(module, code);
626 } else {
678 } else {
627 handleError();
679 handleError();
628 }
680 }
629 }
681 }
630
682
631 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
683 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
632 {
684 {
633 PythonQtObjectPtr p;
685 PythonQtObjectPtr p;
634 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
686 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
635 if (!p) {
687 if (!p) {
636 handleError();
688 handleError();
637 }
689 }
638 return p;
690 return p;
639 }
691 }
640
692
641 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
693 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
642 {
694 {
643 PythonQtObjectPtr code = parseFile(filename);
695 PythonQtObjectPtr code = parseFile(filename);
644 PythonQtObjectPtr module = _p->createModule(name, code);
696 PythonQtObjectPtr module = _p->createModule(name, code);
645 return module;
697 return module;
646 }
698 }
647
699
648 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
700 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
649 {
701 {
650 PyErr_Clear();
702 PyErr_Clear();
651 QString scriptCode = script;
703 QString scriptCode = script;
652 if (scriptCode.isEmpty()) {
704 if (scriptCode.isEmpty()) {
653 // we always need at least a linefeed
705 // we always need at least a linefeed
654 scriptCode = "\n";
706 scriptCode = "\n";
655 }
707 }
656 PythonQtObjectPtr pycode;
708 PythonQtObjectPtr pycode;
657 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
709 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
658 PythonQtObjectPtr module = _p->createModule(name, pycode);
710 PythonQtObjectPtr module = _p->createModule(name, pycode);
659 return module;
711 return module;
660 }
712 }
661
713
662 PythonQtObjectPtr PythonQt::createUniqueModule()
714 PythonQtObjectPtr PythonQt::createUniqueModule()
663 {
715 {
664 static QString pyQtStr("PythonQt_module");
716 static QString pyQtStr("PythonQt_module");
665 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
717 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
666 return createModuleFromScript(moduleName);
718 return createModuleFromScript(moduleName);
667 }
719 }
668
720
669 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
721 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
670 {
722 {
671 if (PyModule_Check(object)) {
723 if (PyModule_Check(object)) {
672 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
724 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
673 } else if (PyDict_Check(object)) {
725 } else if (PyDict_Check(object)) {
674 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
726 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
675 } else {
727 } else {
676 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
728 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
677 }
729 }
678 }
730 }
679
731
680 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
732 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
681 {
733 {
682 if (PyModule_Check(object)) {
734 if (PyModule_Check(object)) {
683 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
735 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
684 } else if (PyDict_Check(object)) {
736 } else if (PyDict_Check(object)) {
685 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
737 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
686 } else {
738 } else {
687 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
739 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
688 }
740 }
689 }
741 }
690
742
691 void PythonQt::removeVariable(PyObject* object, const QString& name)
743 void PythonQt::removeVariable(PyObject* object, const QString& name)
692 {
744 {
693 if (PyDict_Check(object)) {
745 if (PyDict_Check(object)) {
694 PyDict_DelItemString(object, name.toLatin1().data());
746 PyDict_DelItemString(object, name.toLatin1().data());
695 } else {
747 } else {
696 PyObject_DelAttrString(object, name.toLatin1().data());
748 PyObject_DelAttrString(object, name.toLatin1().data());
697 }
749 }
698 }
750 }
699
751
700 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
752 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
701 {
753 {
702 QVariant result;
754 QVariant result;
703 PythonQtObjectPtr obj = lookupObject(object, objectname);
755 PythonQtObjectPtr obj = lookupObject(object, objectname);
704 if (obj) {
756 if (obj) {
705 result = PythonQtConv::PyObjToQVariant(obj);
757 result = PythonQtConv::PyObjToQVariant(obj);
706 }
758 }
707 return result;
759 return result;
708 }
760 }
709
761
710 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
762 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
711 {
763 {
712 QStringList results;
764 QStringList results;
713
765
714 PythonQtObjectPtr object;
766 PythonQtObjectPtr object;
715 if (objectname.isEmpty()) {
767 if (objectname.isEmpty()) {
716 object = module;
768 object = module;
717 } else {
769 } else {
718 object = lookupObject(module, objectname);
770 object = lookupObject(module, objectname);
719 if (!object && type == CallOverloads) {
771 if (!object && type == CallOverloads) {
720 PyObject* dict = lookupObject(module, "__builtins__");
772 PyObject* dict = lookupObject(module, "__builtins__");
721 if (dict) {
773 if (dict) {
722 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
774 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
723 }
775 }
724 }
776 }
725 }
777 }
726
778
727 if (object) {
779 if (object) {
728 if (type == CallOverloads) {
780 if (type == CallOverloads) {
729 if (PythonQtSlotFunction_Check(object)) {
781 if (PythonQtSlotFunction_Check(object)) {
730 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
782 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
731 PythonQtSlotInfo* info = o->m_ml;
783 PythonQtSlotInfo* info = o->m_ml;
732
784
733 while (info) {
785 while (info) {
734 results << info->fullSignature();
786 results << info->fullSignature();
735 info = info->nextInfo();
787 info = info->nextInfo();
736 }
788 }
737 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
789 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
738 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
790 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
739 PythonQtSlotInfo* info = o->classInfo()->constructors();
791 PythonQtSlotInfo* info = o->classInfo()->constructors();
740
792
741 while (info) {
793 while (info) {
742 results << info->fullSignature();
794 results << info->fullSignature();
743 info = info->nextInfo();
795 info = info->nextInfo();
744 }
796 }
745 } else {
797 } else {
746 //TODO: use pydoc!
798 //TODO: use pydoc!
747 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
799 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
748 if (doc) {
800 if (doc) {
749 results << PyString_AsString(doc);
801 results << PyString_AsString(doc);
750 Py_DECREF(doc);
802 Py_DECREF(doc);
751 }
803 }
752 }
804 }
753 } else {
805 } else {
754 PyObject* keys = NULL;
806 PyObject* keys = NULL;
755 bool isDict = false;
807 bool isDict = false;
756 if (PyDict_Check(object)) {
808 if (PyDict_Check(object)) {
757 keys = PyDict_Keys(object);
809 keys = PyDict_Keys(object);
758 isDict = true;
810 isDict = true;
759 } else {
811 } else {
760 keys = PyObject_Dir(object);
812 keys = PyObject_Dir(object);
761 }
813 }
762 if (keys) {
814 if (keys) {
763 int count = PyList_Size(keys);
815 int count = PyList_Size(keys);
764 PyObject* key;
816 PyObject* key;
765 PyObject* value;
817 PyObject* value;
766 QString keystr;
818 QString keystr;
767 for (int i = 0;i<count;i++) {
819 for (int i = 0;i<count;i++) {
768 key = PyList_GetItem(keys,i);
820 key = PyList_GetItem(keys,i);
769 if (isDict) {
821 if (isDict) {
770 value = PyDict_GetItem(object, key);
822 value = PyDict_GetItem(object, key);
771 Py_INCREF(value);
823 Py_INCREF(value);
772 } else {
824 } else {
773 value = PyObject_GetAttr(object, key);
825 value = PyObject_GetAttr(object, key);
774 }
826 }
775 if (!value) continue;
827 if (!value) continue;
776 keystr = PyString_AsString(key);
828 keystr = PyString_AsString(key);
777 static const QString underscoreStr("__tmp");
829 static const QString underscoreStr("__tmp");
778 if (!keystr.startsWith(underscoreStr)) {
830 if (!keystr.startsWith(underscoreStr)) {
779 switch (type) {
831 switch (type) {
780 case Anything:
832 case Anything:
781 results << keystr;
833 results << keystr;
782 break;
834 break;
783 case Class:
835 case Class:
784 if (value->ob_type == &PyClass_Type) {
836 if (value->ob_type == &PyClass_Type) {
785 results << keystr;
837 results << keystr;
786 }
838 }
787 break;
839 break;
788 case Variable:
840 case Variable:
789 if (value->ob_type != &PyClass_Type
841 if (value->ob_type != &PyClass_Type
790 && value->ob_type != &PyCFunction_Type
842 && value->ob_type != &PyCFunction_Type
791 && value->ob_type != &PyFunction_Type
843 && value->ob_type != &PyFunction_Type
792 && value->ob_type != &PyModule_Type
844 && value->ob_type != &PyModule_Type
793 ) {
845 ) {
794 results << keystr;
846 results << keystr;
795 }
847 }
796 break;
848 break;
797 case Function:
849 case Function:
798 if (value->ob_type == &PyFunction_Type ||
850 if (value->ob_type == &PyFunction_Type ||
799 value->ob_type == &PyMethod_Type
851 value->ob_type == &PyMethod_Type
800 ) {
852 ) {
801 results << keystr;
853 results << keystr;
802 }
854 }
803 break;
855 break;
804 case Module:
856 case Module:
805 if (value->ob_type == &PyModule_Type) {
857 if (value->ob_type == &PyModule_Type) {
806 results << keystr;
858 results << keystr;
807 }
859 }
808 break;
860 break;
809 default:
861 default:
810 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
862 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
811 }
863 }
812 }
864 }
813 Py_DECREF(value);
865 Py_DECREF(value);
814 }
866 }
815 Py_DECREF(keys);
867 Py_DECREF(keys);
816 }
868 }
817 }
869 }
818 }
870 }
819 return results;
871 return results;
820 }
872 }
821
873
822 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
874 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
823 {
875 {
824 PythonQtObjectPtr callable = lookupCallable(object, name);
876 PythonQtObjectPtr callable = lookupCallable(object, name);
825 if (callable) {
877 if (callable) {
826 return call(callable, args);
878 return call(callable, args);
827 } else {
879 } else {
828 return QVariant();
880 return QVariant();
829 }
881 }
830 }
882 }
831
883
832 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
884 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
833 {
885 {
834 QVariant r;
886 QVariant r;
835 PythonQtObjectPtr result;
887 PythonQtObjectPtr result;
836 result.setNewRef(callAndReturnPyObject(callable, args));
888 result.setNewRef(callAndReturnPyObject(callable, args));
837 if (result) {
889 if (result) {
838 r = PythonQtConv::PyObjToQVariant(result);
890 r = PythonQtConv::PyObjToQVariant(result);
839 } else {
891 } else {
840 PythonQt::self()->handleError();
892 PythonQt::self()->handleError();
841 }
893 }
842 return r;
894 return r;
843 }
895 }
844
896
845 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
897 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
846 {
898 {
847 PyObject* result = NULL;
899 PyObject* result = NULL;
848 if (callable) {
900 if (callable) {
849 PythonQtObjectPtr pargs;
901 PythonQtObjectPtr pargs;
850 int count = args.size();
902 int count = args.size();
851 if (count>0) {
903 if (count>0) {
852 pargs.setNewRef(PyTuple_New(count));
904 pargs.setNewRef(PyTuple_New(count));
853 }
905 }
854 bool err = false;
906 bool err = false;
855 // transform QVariants to Python
907 // transform QVariants to Python
856 for (int i = 0; i < count; i++) {
908 for (int i = 0; i < count; i++) {
857 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
909 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
858 if (arg) {
910 if (arg) {
859 // steals reference, no unref
911 // steals reference, no unref
860 PyTuple_SetItem(pargs, i,arg);
912 PyTuple_SetItem(pargs, i,arg);
861 } else {
913 } else {
862 err = true;
914 err = true;
863 break;
915 break;
864 }
916 }
865 }
917 }
866
918
867 if (!err) {
919 if (!err) {
868 PyErr_Clear();
920 PyErr_Clear();
869 result = PyObject_CallObject(callable, pargs);
921 result = PyObject_CallObject(callable, pargs);
870 }
922 }
871 }
923 }
872 return result;
924 return result;
873 }
925 }
874
926
875 void PythonQt::addInstanceDecorators(QObject* o)
927 void PythonQt::addInstanceDecorators(QObject* o)
876 {
928 {
877 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
929 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
878 }
930 }
879
931
880 void PythonQt::addClassDecorators(QObject* o)
932 void PythonQt::addClassDecorators(QObject* o)
881 {
933 {
882 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
934 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
883 }
935 }
884
936
885 void PythonQt::addDecorators(QObject* o)
937 void PythonQt::addDecorators(QObject* o)
886 {
938 {
887 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
939 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
888 }
940 }
889
941
890 void PythonQt::registerQObjectClassNames(const QStringList& names)
942 void PythonQt::registerQObjectClassNames(const QStringList& names)
891 {
943 {
892 _p->registerQObjectClassNames(names);
944 _p->registerQObjectClassNames(names);
893 }
945 }
894
946
895 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
947 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
896 {
948 {
897 _p->_importInterface = importInterface;
949 _p->_importInterface = importInterface;
898 PythonQtImport::init();
950 PythonQtImport::init();
899 }
951 }
900
952
901 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
953 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
902 {
954 {
903 _p->_importIgnorePaths = paths;
955 _p->_importIgnorePaths = paths;
904 }
956 }
905
957
906 const QStringList& PythonQt::getImporterIgnorePaths()
958 const QStringList& PythonQt::getImporterIgnorePaths()
907 {
959 {
908 return _p->_importIgnorePaths;
960 return _p->_importIgnorePaths;
909 }
961 }
910
962
911 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
963 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
912 {
964 {
913 _p->_cppWrapperFactories.append(factory);
965 _p->_cppWrapperFactories.append(factory);
914 }
966 }
915
967
916 //---------------------------------------------------------------------------------------------------
968 //---------------------------------------------------------------------------------------------------
917 PythonQtPrivate::PythonQtPrivate()
969 PythonQtPrivate::PythonQtPrivate()
918 {
970 {
919 _importInterface = NULL;
971 _importInterface = NULL;
920 _defaultImporter = new PythonQtQFileImporter;
972 _defaultImporter = new PythonQtQFileImporter;
921 _noLongerWrappedCB = NULL;
973 _noLongerWrappedCB = NULL;
922 _wrappedCB = NULL;
974 _wrappedCB = NULL;
923 _currentClassInfoForClassWrapperCreation = NULL;
975 _currentClassInfoForClassWrapperCreation = NULL;
924 _profilingCB = NULL;
976 _profilingCB = NULL;
925 }
977 }
926
978
927 void PythonQtPrivate::setupSharedLibrarySuffixes()
979 void PythonQtPrivate::setupSharedLibrarySuffixes()
928 {
980 {
929 _sharedLibrarySuffixes.clear();
981 _sharedLibrarySuffixes.clear();
930 PythonQtObjectPtr imp;
982 PythonQtObjectPtr imp;
931 imp.setNewRef(PyImport_ImportModule("imp"));
983 imp.setNewRef(PyImport_ImportModule("imp"));
932 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
984 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
933 QVariant result = imp.call("get_suffixes");
985 QVariant result = imp.call("get_suffixes");
934 #ifdef __linux
986 #ifdef __linux
935 #ifdef _DEBUG
987 #ifdef _DEBUG
936 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
988 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
937 // This is a workaround, because python does not append the '_d' suffix on Linux
989 // This is a workaround, because python does not append the '_d' suffix on Linux
938 // and would always load the release library otherwise.
990 // and would always load the release library otherwise.
939 _sharedLibrarySuffixes << "_d.so";
991 _sharedLibrarySuffixes << "_d.so";
940 #endif
992 #endif
941 #endif
993 #endif
942 foreach (QVariant entry, result.toList()) {
994 foreach (QVariant entry, result.toList()) {
943 QVariantList suffixEntry = entry.toList();
995 QVariantList suffixEntry = entry.toList();
944 if (suffixEntry.count()==3) {
996 if (suffixEntry.count()==3) {
945 int code = suffixEntry.at(2).toInt();
997 int code = suffixEntry.at(2).toInt();
946 if (code == cExtensionCode) {
998 if (code == cExtensionCode) {
947 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
999 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
948 }
1000 }
949 }
1001 }
950 }
1002 }
951 }
1003 }
952
1004
953 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1005 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
954 {
1006 {
955 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1007 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
956 _currentClassInfoForClassWrapperCreation = NULL;
1008 _currentClassInfoForClassWrapperCreation = NULL;
957 return info;
1009 return info;
958 }
1010 }
959
1011
960 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1012 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
961 {
1013 {
962 o->setParent(this);
1014 o->setParent(this);
963 int numMethods = o->metaObject()->methodCount();
1015 int numMethods = o->metaObject()->methodCount();
964 for (int i = 0; i < numMethods; i++) {
1016 for (int i = 0; i < numMethods; i++) {
965 QMetaMethod m = o->metaObject()->method(i);
1017 QMetaMethod m = o->metaObject()->method(i);
966 if ((m.methodType() == QMetaMethod::Method ||
1018 if ((m.methodType() == QMetaMethod::Method ||
967 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1019 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
968 if (qstrncmp(m.signature(), "new_", 4)==0) {
1020 if (qstrncmp(m.signature(), "new_", 4)==0) {
969 if ((decoTypes & ConstructorDecorator) == 0) continue;
1021 if ((decoTypes & ConstructorDecorator) == 0) continue;
970 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1022 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
971 if (info->parameters().at(0).pointerCount == 1) {
1023 if (info->parameters().at(0).pointerCount == 1) {
972 QByteArray signature = m.signature();
1024 QByteArray signature = m.signature();
973 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1025 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
974 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1026 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
975 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1027 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
976 classInfo->addConstructor(newSlot);
1028 classInfo->addConstructor(newSlot);
977 }
1029 }
978 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1030 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
979 if ((decoTypes & DestructorDecorator) == 0) continue;
1031 if ((decoTypes & DestructorDecorator) == 0) continue;
980 QByteArray signature = m.signature();
1032 QByteArray signature = m.signature();
981 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1033 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
982 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1034 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
983 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1035 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
984 classInfo->setDestructor(newSlot);
1036 classInfo->setDestructor(newSlot);
985 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1037 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
986 if ((decoTypes & StaticDecorator) == 0) continue;
1038 if ((decoTypes & StaticDecorator) == 0) continue;
987 QByteArray signature = m.signature();
1039 QByteArray signature = m.signature();
988 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1040 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
989 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1041 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
990 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1042 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
991 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1043 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
992 classInfo->addDecoratorSlot(newSlot);
1044 classInfo->addDecoratorSlot(newSlot);
993 } else {
1045 } else {
994 if ((decoTypes & InstanceDecorator) == 0) continue;
1046 if ((decoTypes & InstanceDecorator) == 0) continue;
995 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1047 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
996 if (info->parameters().count()>1) {
1048 if (info->parameters().count()>1) {
997 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1049 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
998 if (p.pointerCount==1) {
1050 if (p.pointerCount==1) {
999 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1051 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1000 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1052 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1001 classInfo->addDecoratorSlot(newSlot);
1053 classInfo->addDecoratorSlot(newSlot);
1002 }
1054 }
1003 }
1055 }
1004 }
1056 }
1005 }
1057 }
1006 }
1058 }
1007 }
1059 }
1008
1060
1009 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1061 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1010 {
1062 {
1011 foreach(QString name, names) {
1063 foreach(QString name, names) {
1012 _knownQObjectClassNames.insert(name.toLatin1(), true);
1064 _knownQObjectClassNames.insert(name.toLatin1(), true);
1013 }
1065 }
1014 }
1066 }
1015
1067
1016 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1068 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1017 {
1069 {
1018 _signalReceivers.remove(obj);
1070 _signalReceivers.remove(obj);
1019 }
1071 }
1020
1072
1021 bool PythonQt::handleError()
1073 bool PythonQt::handleError()
1022 {
1074 {
1023 bool flag = false;
1075 bool flag = false;
1024 if (PyErr_Occurred()) {
1076 if (PyErr_Occurred()) {
1025
1077
1026 // currently we just print the error and the stderr handler parses the errors
1078 // currently we just print the error and the stderr handler parses the errors
1027 PyErr_Print();
1079 PyErr_Print();
1028
1080
1029 /*
1081 /*
1030 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1082 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1031 PyObject *ptype;
1083 PyObject *ptype;
1032 PyObject *pvalue;
1084 PyObject *pvalue;
1033 PyObject *ptraceback;
1085 PyObject *ptraceback;
1034 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1086 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1035
1087
1036 Py_XDECREF(ptype);
1088 Py_XDECREF(ptype);
1037 Py_XDECREF(pvalue);
1089 Py_XDECREF(pvalue);
1038 Py_XDECREF(ptraceback);
1090 Py_XDECREF(ptraceback);
1039 */
1091 */
1040 PyErr_Clear();
1092 PyErr_Clear();
1041 flag = true;
1093 flag = true;
1042 }
1094 }
1043 return flag;
1095 return flag;
1044 }
1096 }
1045
1097
1046 void PythonQt::addSysPath(const QString& path)
1098 void PythonQt::addSysPath(const QString& path)
1047 {
1099 {
1048 PythonQtObjectPtr sys;
1100 PythonQtObjectPtr sys;
1049 sys.setNewRef(PyImport_ImportModule("sys"));
1101 sys.setNewRef(PyImport_ImportModule("sys"));
1050 PythonQtObjectPtr obj = lookupObject(sys, "path");
1102 PythonQtObjectPtr obj = lookupObject(sys, "path");
1051 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1103 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1052 }
1104 }
1053
1105
1054 void PythonQt::overwriteSysPath(const QStringList& paths)
1106 void PythonQt::overwriteSysPath(const QStringList& paths)
1055 {
1107 {
1056 PythonQtObjectPtr sys;
1108 PythonQtObjectPtr sys;
1057 sys.setNewRef(PyImport_ImportModule("sys"));
1109 sys.setNewRef(PyImport_ImportModule("sys"));
1058 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1110 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1059 }
1111 }
1060
1112
1061 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1113 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1062 {
1114 {
1063 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1115 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1064 }
1116 }
1065
1117
1066 void PythonQt::stdOutRedirectCB(const QString& str)
1118 void PythonQt::stdOutRedirectCB(const QString& str)
1067 {
1119 {
1120 if (!PythonQt::self()) {
1121 std::cout << str.toLatin1().data() << std::endl;
1122 return;
1123 }
1068 emit PythonQt::self()->pythonStdOut(str);
1124 emit PythonQt::self()->pythonStdOut(str);
1069 }
1125 }
1070
1126
1071 void PythonQt::stdErrRedirectCB(const QString& str)
1127 void PythonQt::stdErrRedirectCB(const QString& str)
1072 {
1128 {
1129 if (!PythonQt::self()) {
1130 std::cerr << str.toLatin1().data() << std::endl;
1131 return;
1132 }
1073 emit PythonQt::self()->pythonStdErr(str);
1133 emit PythonQt::self()->pythonStdErr(str);
1074 }
1134 }
1075
1135
1076 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1136 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1077 {
1137 {
1078 _p->_wrappedCB = cb;
1138 _p->_wrappedCB = cb;
1079 }
1139 }
1080
1140
1081 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1141 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1082 {
1142 {
1083 _p->_noLongerWrappedCB = cb;
1143 _p->_noLongerWrappedCB = cb;
1084 }
1144 }
1085
1145
1086 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1146 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1087 {
1147 {
1088 _p->_profilingCB = cb;
1148 _p->_profilingCB = cb;
1089 }
1149 }
1090
1150
1091
1151
1092 static PyMethodDef PythonQtMethods[] = {
1152 static PyMethodDef PythonQtMethods[] = {
1093 {NULL, NULL, 0, NULL}
1153 {NULL, NULL, 0, NULL}
1094 };
1154 };
1095
1155
1096 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1156 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1097 {
1157 {
1098 QByteArray name = "PythonQt";
1158 QByteArray name = "PythonQt";
1099 if (!pythonQtModuleName.isEmpty()) {
1159 if (!pythonQtModuleName.isEmpty()) {
1100 name = pythonQtModuleName;
1160 name = pythonQtModuleName;
1101 }
1161 }
1102 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1162 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1103 _p->_pythonQtModuleName = name;
1163 _p->_pythonQtModuleName = name;
1104
1164
1105 if (redirectStdOut) {
1165 if (redirectStdOut) {
1106 PythonQtObjectPtr sys;
1166 PythonQtObjectPtr sys;
1107 PythonQtObjectPtr out;
1167 PythonQtObjectPtr out;
1108 PythonQtObjectPtr err;
1168 PythonQtObjectPtr err;
1109 sys.setNewRef(PyImport_ImportModule("sys"));
1169 sys.setNewRef(PyImport_ImportModule("sys"));
1110 // create a redirection object for stdout and stderr
1170 // create a redirection object for stdout and stderr
1111 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1171 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1112 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1172 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1113 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1173 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1114 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1174 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1115 // replace the built in file objects with our own objects
1175 // replace the built in file objects with our own objects
1116 PyModule_AddObject(sys, "stdout", out);
1176 PyModule_AddObject(sys, "stdout", out);
1117 PyModule_AddObject(sys, "stderr", err);
1177 PyModule_AddObject(sys, "stderr", err);
1118 }
1178 }
1119 }
1179 }
1120
1180
1121 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1181 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1122 {
1182 {
1123 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1183 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1124 }
1184 }
1125
1185
1126
1186
1127 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1187 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1128 {
1188 {
1129 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1189 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1130 if (!info) {
1190 if (!info) {
1131 info = new PythonQtClassInfo();
1191 info = new PythonQtClassInfo();
1132 info->setupCPPObject(typeName);
1192 info->setupCPPObject(typeName);
1133 _knownClassInfos.insert(typeName, info);
1193 _knownClassInfos.insert(typeName, info);
1134 }
1194 }
1135 return info;
1195 return info;
1136 }
1196 }
1137
1197
1138 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1198 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1139 {
1199 {
1140 _p->addPolymorphicHandler(typeName, cb);
1200 _p->addPolymorphicHandler(typeName, cb);
1141 }
1201 }
1142
1202
1143 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1203 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1144 {
1204 {
1145 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1205 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1146 info->addPolymorphicHandler(cb);
1206 info->addPolymorphicHandler(cb);
1147 }
1207 }
1148
1208
1149 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1209 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1150 {
1210 {
1151 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1211 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1152 }
1212 }
1153
1213
1154 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1214 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1155 {
1215 {
1156 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1216 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1157 if (info) {
1217 if (info) {
1158 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1218 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1159 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1219 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1160 return true;
1220 return true;
1161 } else {
1221 } else {
1162 return false;
1222 return false;
1163 }
1223 }
1164 }
1224 }
1165
1225
1166 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1226 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1167 {
1227 {
1168 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1228 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1169 if (!info->pythonQtClassWrapper()) {
1229 if (!info->pythonQtClassWrapper()) {
1170 info->setTypeSlots(typeSlots);
1230 info->setTypeSlots(typeSlots);
1171 info->setupCPPObject(typeName);
1231 info->setupCPPObject(typeName);
1172 createPythonQtClassWrapper(info, package, module);
1232 createPythonQtClassWrapper(info, package, module);
1173 }
1233 }
1174 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1234 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1175 addParentClass(typeName, parentTypeName, 0);
1235 addParentClass(typeName, parentTypeName, 0);
1176 }
1236 }
1177 if (wrapperCreator) {
1237 if (wrapperCreator) {
1178 info->setDecoratorProvider(wrapperCreator);
1238 info->setDecoratorProvider(wrapperCreator);
1179 }
1239 }
1180 if (shell) {
1240 if (shell) {
1181 info->setShellSetInstanceWrapperCB(shell);
1241 info->setShellSetInstanceWrapperCB(shell);
1182 }
1242 }
1183 }
1243 }
1184
1244
1185 PyObject* PythonQtPrivate::packageByName(const char* name)
1245 PyObject* PythonQtPrivate::packageByName(const char* name)
1186 {
1246 {
1187 if (name==NULL || name[0]==0) {
1247 if (name==NULL || name[0]==0) {
1188 name = "private";
1248 name = "private";
1189 }
1249 }
1190 PyObject* v = _packages.value(name);
1250 PyObject* v = _packages.value(name);
1191 if (!v) {
1251 if (!v) {
1192 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1252 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1193 _packages.insert(name, v);
1253 _packages.insert(name, v);
1194 // AddObject steals the reference, so increment it!
1254 // AddObject steals the reference, so increment it!
1195 Py_INCREF(v);
1255 Py_INCREF(v);
1196 PyModule_AddObject(_pythonQtModule, name, v);
1256 PyModule_AddObject(_pythonQtModule, name, v);
1197 }
1257 }
1198 return v;
1258 return v;
1199 }
1259 }
1200
1260
1201 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1261 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1202 {
1262 {
1203 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1263 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;
1204 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1264 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1205 PythonQt::self()->handleError();
1265 PythonQt::self()->handleError();
1206 }
1266 }
1207
1267
1208 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1268 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1209 {
1269 {
1210 if (_p->_initFlags & ExternalHelp) {
1270 if (_p->_initFlags & ExternalHelp) {
1211 emit pythonHelpRequest(QByteArray(info->className()));
1271 emit pythonHelpRequest(QByteArray(info->className()));
1212 return Py_BuildValue("");
1272 return Py_BuildValue("");
1213 } else {
1273 } else {
1214 return PyString_FromString(info->help().toLatin1().data());
1274 return PyString_FromString(info->help().toLatin1().data());
1215 }
1275 }
1216 }
1276 }
1217
1277
1218 void PythonQt::clearNotFoundCachedMembers()
1278 void PythonQt::clearNotFoundCachedMembers()
1219 {
1279 {
1220 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1280 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1221 info->clearNotFoundCachedMembers();
1281 info->clearNotFoundCachedMembers();
1222 }
1282 }
1223 }
1283 }
1224
1284
1225 void PythonQtPrivate::removeWrapperPointer(void* obj)
1285 void PythonQtPrivate::removeWrapperPointer(void* obj)
1226 {
1286 {
1227 _wrappedObjects.remove(obj);
1287 _wrappedObjects.remove(obj);
1228 }
1288 }
1229
1289
1230 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1290 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1231 {
1291 {
1232 _wrappedObjects.insert(obj, wrapper);
1292 _wrappedObjects.insert(obj, wrapper);
1233 }
1293 }
1234
1294
1235 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1295 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1236 {
1296 {
1237 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1297 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1238 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1298 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1239 // this is a wrapper whose QObject was already removed due to destruction
1299 // this is a wrapper whose QObject was already removed due to destruction
1240 // so the obj pointer has to be a new QObject with the same address...
1300 // so the obj pointer has to be a new QObject with the same address...
1241 // we remove the old one and set the copy to NULL
1301 // we remove the old one and set the copy to NULL
1242 wrap->_objPointerCopy = NULL;
1302 wrap->_objPointerCopy = NULL;
1243 removeWrapperPointer(obj);
1303 removeWrapperPointer(obj);
1244 wrap = NULL;
1304 wrap = NULL;
1245 }
1305 }
1246 return wrap;
1306 return wrap;
1247 }
1307 }
1248
1308
1249 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1309 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1250 {
1310 {
1251 PythonQtObjectPtr result;
1311 PythonQtObjectPtr result;
1252 if (pycode) {
1312 if (pycode) {
1253 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1313 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1254 } else {
1314 } else {
1255 PythonQt::self()->handleError();
1315 PythonQt::self()->handleError();
1256 }
1316 }
1257 return result;
1317 return result;
1258 }
1318 }
@@ -1,656 +1,675
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include "PythonQtStdIn.h"
50 #include <QObject>
51 #include <QObject>
51 #include <QVariant>
52 #include <QVariant>
52 #include <QList>
53 #include <QList>
53 #include <QHash>
54 #include <QHash>
54 #include <QByteArray>
55 #include <QByteArray>
55 #include <QStringList>
56 #include <QStringList>
56 #include <QtDebug>
57 #include <QtDebug>
57 #include <iostream>
58 #include <iostream>
58
59
59
60
60 class PythonQtClassInfo;
61 class PythonQtClassInfo;
61 class PythonQtPrivate;
62 class PythonQtPrivate;
62 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
67 class PythonQtQFileImporter;
67
68
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
72
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
74
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 }
75
78
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
79 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
80 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
81 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
79 }
83 }
80
84
81 //! callback to create a QObject lazily
85 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
86 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
87
84 //! helper template to create a derived QObject class
88 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
89 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
90
87 //! The main interface to the Python Qt binding, realized as a singleton
91 //! The main interface to the Python Qt binding, realized as a singleton
88 /*!
92 /*!
89 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
93 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
90 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
94 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
91 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
95 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
92 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
96 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
93 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
97 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
94 code in the scope of a dict.
98 code in the scope of a dict.
95 */
99 */
96 class PYTHONQT_EXPORT PythonQt : public QObject {
100 class PYTHONQT_EXPORT PythonQt : public QObject {
97
101
98 Q_OBJECT
102 Q_OBJECT
99
103
100 public:
104 public:
101
105
102 //! flags that can be passed to PythonQt::init()
106 //! flags that can be passed to PythonQt::init()
103 enum InitFlags {
107 enum InitFlags {
104 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
108 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
105 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
109 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
106 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
110 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
107 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
111 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
108 };
112 };
109
113
110 //! flags that tell PythonQt which operators to expect on the registered type
114 //! flags that tell PythonQt which operators to expect on the registered type
111 enum TypeSlots {
115 enum TypeSlots {
112 Type_Add = 1,
116 Type_Add = 1,
113 Type_Subtract = 1 << 1,
117 Type_Subtract = 1 << 1,
114 Type_Multiply = 1 << 2,
118 Type_Multiply = 1 << 2,
115 Type_Divide = 1 << 3,
119 Type_Divide = 1 << 3,
116 Type_Mod = 1 << 4,
120 Type_Mod = 1 << 4,
117 Type_And = 1 << 5,
121 Type_And = 1 << 5,
118 Type_Or = 1 << 6,
122 Type_Or = 1 << 6,
119 Type_Xor = 1 << 7,
123 Type_Xor = 1 << 7,
120 Type_LShift = 1 << 8,
124 Type_LShift = 1 << 8,
121 Type_RShift = 1 << 9,
125 Type_RShift = 1 << 9,
122
126
123 Type_InplaceAdd = 1 << 10,
127 Type_InplaceAdd = 1 << 10,
124 Type_InplaceSubtract = 1 << 11,
128 Type_InplaceSubtract = 1 << 11,
125 Type_InplaceMultiply = 1 << 12,
129 Type_InplaceMultiply = 1 << 12,
126 Type_InplaceDivide = 1 << 13,
130 Type_InplaceDivide = 1 << 13,
127 Type_InplaceMod = 1 << 14,
131 Type_InplaceMod = 1 << 14,
128 Type_InplaceAnd = 1 << 15,
132 Type_InplaceAnd = 1 << 15,
129 Type_InplaceOr = 1 << 16,
133 Type_InplaceOr = 1 << 16,
130 Type_InplaceXor = 1 << 17,
134 Type_InplaceXor = 1 << 17,
131 Type_InplaceLShift = 1 << 18,
135 Type_InplaceLShift = 1 << 18,
132 Type_InplaceRShift = 1 << 19,
136 Type_InplaceRShift = 1 << 19,
133
137
134 // Not yet needed/nicely mappable/generated...
138 // Not yet needed/nicely mappable/generated...
135 //Type_Positive = 1 << 29,
139 //Type_Positive = 1 << 29,
136 //Type_Negative = 1 << 29,
140 //Type_Negative = 1 << 29,
137 //Type_Abs = 1 << 29,
141 //Type_Abs = 1 << 29,
138 //Type_Hash = 1 << 29,
142 //Type_Hash = 1 << 29,
139
143
140 Type_Invert = 1 << 29,
144 Type_Invert = 1 << 29,
141 Type_RichCompare = 1 << 30,
145 Type_RichCompare = 1 << 30,
142 Type_NonZero = 1 << 31,
146 Type_NonZero = 1 << 31,
143
147
144 };
148 };
145
149
146 //! enum for profiling callback
150 //! enum for profiling callback
147 enum ProfilingCallbackState {
151 enum ProfilingCallbackState {
148 Enter = 1,
152 Enter = 1,
149 Leave = 2
153 Leave = 2
150 };
154 };
151
155
152 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
156 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
153 //! they are NULL.
157 //! they are NULL.
154 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
158 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
155
159
156 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
157 //! \name Singleton Initialization
161 //! \name Singleton Initialization
158 //@{
162 //@{
159
163
160 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
164 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
161 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
165 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
162 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
166 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
163 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
167 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
164
168
165 //! cleanup of the singleton
169 //! cleanup of the singleton
166 static void cleanup();
170 static void cleanup();
167
171
168 //! get the singleton instance
172 //! get the singleton instance
169 static PythonQt* self() { return _self; }
173 static PythonQt* self();
170
174
171 //@}
175 //@}
172
176
173 //! defines the object types for introspection
177 //! defines the object types for introspection
174 enum ObjectType {
178 enum ObjectType {
175 Class,
179 Class,
176 Function,
180 Function,
177 Variable,
181 Variable,
178 Module,
182 Module,
179 Anything,
183 Anything,
180 CallOverloads
184 CallOverloads
181 };
185 };
182
186
187
188 //---------------------------------------------------------------------------
189 //! \name Standard input handling
190 //@{
191
192 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195
196 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! or 'sys.pythonqt_original_stdin'
198 void setRedirectStdInCallbackEnabled(bool enabled);
199
200 //@}
201
183 //---------------------------------------------------------------------------
202 //---------------------------------------------------------------------------
184 //! \name Modules
203 //! \name Modules
185 //@{
204 //@{
186
205
187 //! get the __main__ module of python
206 //! get the __main__ module of python
188 PythonQtObjectPtr getMainModule();
207 PythonQtObjectPtr getMainModule();
189
208
190 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
209 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
191 //! If a module is already imported, this returns the already imported module.
210 //! If a module is already imported, this returns the already imported module.
192 PythonQtObjectPtr importModule(const QString& name);
211 PythonQtObjectPtr importModule(const QString& name);
193
212
194 //! creates the new module \c name and evaluates the given file in the context of that module
213 //! creates the new module \c name and evaluates the given file in the context of that module
195 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
214 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
196 //! to a module later on.
215 //! to a module later on.
197 //! The user needs to make sure that the \c name is unique in the python module dictionary.
216 //! The user needs to make sure that the \c name is unique in the python module dictionary.
198 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
217 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
199
218
200 //! creates the new module \c name and evaluates the given script in the context of that module.
219 //! creates the new module \c name and evaluates the given script in the context of that module.
201 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
220 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
202 //! to a module later on.
221 //! to a module later on.
203 //! The user needs to make sure that the \c name is unique in the python module dictionary.
222 //! The user needs to make sure that the \c name is unique in the python module dictionary.
204 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
223 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
205
224
206 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
225 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
207 //! script code
226 //! script code
208 PythonQtObjectPtr createUniqueModule();
227 PythonQtObjectPtr createUniqueModule();
209
228
210 //@}
229 //@}
211
230
212 //---------------------------------------------------------------------------
231 //---------------------------------------------------------------------------
213 //! \name Importing/Paths
232 //! \name Importing/Paths
214 //@{
233 //@{
215
234
216 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
235 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
217 void overwriteSysPath(const QStringList& paths);
236 void overwriteSysPath(const QStringList& paths);
218
237
219 //! prepend a path to sys.path to allow importing from it
238 //! prepend a path to sys.path to allow importing from it
220 void addSysPath(const QString& path);
239 void addSysPath(const QString& path);
221
240
222 //! sets the __path__ list of a module to the given list (important for local imports)
241 //! sets the __path__ list of a module to the given list (important for local imports)
223 void setModuleImportPath(PyObject* module, const QStringList& paths);
242 void setModuleImportPath(PyObject* module, const QStringList& paths);
224
243
225 //@}
244 //@}
226
245
227 //---------------------------------------------------------------------------
246 //---------------------------------------------------------------------------
228 //! \name Registering Classes
247 //! \name Registering Classes
229 //@{
248 //@{
230
249
231 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
250 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
232 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
251 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
233 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
252 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
234 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
253 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
235
254
236 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
255 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
237 //! (ownership of wrapper is passed to PythonQt)
256 //! (ownership of wrapper is passed to PythonQt)
238 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
257 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
239
258
240 This will add a wrapper object that is used to make calls to the given classname \c typeName.
259 This will add a wrapper object that is used to make calls to the given classname \c typeName.
241 All slots that take a pointer to typeName as the first argument will be callable from Python on
260 All slots that take a pointer to typeName as the first argument will be callable from Python on
242 a variant object that contains such a type.
261 a variant object that contains such a type.
243 */
262 */
244 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
263 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
245
264
246 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
265 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
247 //! and it will register the classes when it first sees a pointer to such a derived class
266 //! and it will register the classes when it first sees a pointer to such a derived class
248 void registerQObjectClassNames(const QStringList& names);
267 void registerQObjectClassNames(const QStringList& names);
249
268
250 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
269 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
251 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
270 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
252 //! type is really derived from parentType.
271 //! type is really derived from parentType.
253 //! Returns false if the typeName was not yet registered.
272 //! Returns false if the typeName was not yet registered.
254 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
273 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
255
274
256 //! add a handler for polymorphic downcasting
275 //! add a handler for polymorphic downcasting
257 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
276 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
258
277
259 //@}
278 //@}
260
279
261 //---------------------------------------------------------------------------
280 //---------------------------------------------------------------------------
262 //! \name Script Parsing and Evaluation
281 //! \name Script Parsing and Evaluation
263 //@{
282 //@{
264
283
265 //! parses the given file and returns the python code object, this can then be used to call evalCode()
284 //! parses the given file and returns the python code object, this can then be used to call evalCode()
266 PythonQtObjectPtr parseFile(const QString& filename);
285 PythonQtObjectPtr parseFile(const QString& filename);
267
286
268 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
287 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
269 //! If pycode is NULL, a python error is printed.
288 //! If pycode is NULL, a python error is printed.
270 QVariant evalCode(PyObject* object, PyObject* pycode);
289 QVariant evalCode(PyObject* object, PyObject* pycode);
271
290
272 //! evaluates the given script code and returns the result value
291 //! evaluates the given script code and returns the result value
273 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
292 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
274
293
275 //! evaluates the given script code from file
294 //! evaluates the given script code from file
276 void evalFile(PyObject* object, const QString& filename);
295 void evalFile(PyObject* object, const QString& filename);
277
296
278 //@}
297 //@}
279
298
280 //---------------------------------------------------------------------------
299 //---------------------------------------------------------------------------
281 //! \name Signal Handlers
300 //! \name Signal Handlers
282 //@{
301 //@{
283
302
284 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
303 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
285 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
304 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
286
305
287 //! remove a signal handler from the given \c signal of \c obj
306 //! remove a signal handler from the given \c signal of \c obj
288 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
307 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
289
308
290 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
309 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
291 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
310 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
292
311
293 //! remove a signal handler from the given \c signal of \c obj
312 //! remove a signal handler from the given \c signal of \c obj
294 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
313 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
295
314
296 //@}
315 //@}
297
316
298 //---------------------------------------------------------------------------
317 //---------------------------------------------------------------------------
299 //! \name Variable access
318 //! \name Variable access
300 //@{
319 //@{
301
320
302 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
321 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
303 void addObject(PyObject* object, const QString& name, QObject* qObject);
322 void addObject(PyObject* object, const QString& name, QObject* qObject);
304
323
305 //! add the given variable to the object
324 //! add the given variable to the object
306 void addVariable(PyObject* object, const QString& name, const QVariant& v);
325 void addVariable(PyObject* object, const QString& name, const QVariant& v);
307
326
308 //! remove the given variable
327 //! remove the given variable
309 void removeVariable(PyObject* module, const QString& name);
328 void removeVariable(PyObject* module, const QString& name);
310
329
311 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
330 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
312 QVariant getVariable(PyObject* object, const QString& name);
331 QVariant getVariable(PyObject* object, const QString& name);
313
332
314 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
333 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
315 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
334 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
316
335
317 //! returns the found callable object or NULL
336 //! returns the found callable object or NULL
318 //! @return new reference
337 //! @return new reference
319 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
338 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
320
339
321 //@}
340 //@}
322
341
323 //---------------------------------------------------------------------------
342 //---------------------------------------------------------------------------
324 //! \name Calling Python Objects
343 //! \name Calling Python Objects
325 //@{
344 //@{
326
345
327 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
346 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
328 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
347 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
329
348
330 //! call the given python object, returns the result converted to a QVariant
349 //! call the given python object, returns the result converted to a QVariant
331 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
350 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
332
351
333 //! call the given python object, returns the result as new PyObject
352 //! call the given python object, returns the result as new PyObject
334 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
353 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
335
354
336 //@}
355 //@}
337
356
338 //---------------------------------------------------------------------------
357 //---------------------------------------------------------------------------
339 //! \name Decorations, Constructors, Wrappers...
358 //! \name Decorations, Constructors, Wrappers...
340 //@{
359 //@{
341
360
342 //! add an object whose slots will be used as decorator slots for
361 //! add an object whose slots will be used as decorator slots for
343 //! other QObjects or CPP classes. The slots need to follow the
362 //! other QObjects or CPP classes. The slots need to follow the
344 //! convention that the first argument is a pointer to the wrapped object.
363 //! convention that the first argument is a pointer to the wrapped object.
345 //! (ownership is passed to PythonQt)
364 //! (ownership is passed to PythonQt)
346 /*!
365 /*!
347 Example:
366 Example:
348
367
349 A slot with the signature
368 A slot with the signature
350
369
351 \code
370 \code
352 bool doSomething(QWidget* w, int a)
371 bool doSomething(QWidget* w, int a)
353 \endcode
372 \endcode
354
373
355 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
374 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
356 that will be called with the concrete instance as first argument.
375 that will be called with the concrete instance as first argument.
357 So in Python you can now e.g. call
376 So in Python you can now e.g. call
358
377
359 \code
378 \code
360 someWidget.doSomething(12)
379 someWidget.doSomething(12)
361 \endcode
380 \endcode
362
381
363 without QWidget really having this method. This allows to easily make normal methods
382 without QWidget really having this method. This allows to easily make normal methods
364 of Qt classes callable by forwarding them with such decorator slots
383 of Qt classes callable by forwarding them with such decorator slots
365 or to make CPP classes (which are not derived from QObject) callable from Python.
384 or to make CPP classes (which are not derived from QObject) callable from Python.
366 */
385 */
367 void addInstanceDecorators(QObject* o);
386 void addInstanceDecorators(QObject* o);
368
387
369 //! add an object whose slots will be used as decorator slots for
388 //! add an object whose slots will be used as decorator slots for
370 //! class objects (ownership is passed to PythonQt)
389 //! class objects (ownership is passed to PythonQt)
371 /*!
390 /*!
372 The slots need to follow the following convention:
391 The slots need to follow the following convention:
373 - SomeClass* new_SomeClass(...)
392 - SomeClass* new_SomeClass(...)
374 - QVariant new_SomeClass(...)
393 - QVariant new_SomeClass(...)
375 - void delete_SomeClass(SomeClass*)
394 - void delete_SomeClass(SomeClass*)
376 - ... static_SomeClass_someName(...)
395 - ... static_SomeClass_someName(...)
377
396
378 This will add:
397 This will add:
379 - a constructor
398 - a constructor
380 - a constructor which generates a QVariant
399 - a constructor which generates a QVariant
381 - a destructor (only useful for CPP objects)
400 - a destructor (only useful for CPP objects)
382 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
401 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
383
402
384 */
403 */
385 void addClassDecorators(QObject* o);
404 void addClassDecorators(QObject* o);
386
405
387 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
406 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
388 void addDecorators(QObject* o);
407 void addDecorators(QObject* o);
389
408
390 //! add the given factory to PythonQt (ownership stays with caller)
409 //! add the given factory to PythonQt (ownership stays with caller)
391 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
410 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
392
411
393 //@}
412 //@}
394
413
395 //---------------------------------------------------------------------------
414 //---------------------------------------------------------------------------
396 //! \name Custom Importer
415 //! \name Custom Importer
397 //@{
416 //@{
398
417
399 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
418 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
400 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
419 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
401 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
420 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
402 //! This is not reversible, so even setting setImporter(NULL) afterwards will
421 //! This is not reversible, so even setting setImporter(NULL) afterwards will
403 //! keep the custom PythonQt importer with a QFile default import interface.
422 //! keep the custom PythonQt importer with a QFile default import interface.
404 //! Subsequent python import calls will make use of the passed importInterface
423 //! Subsequent python import calls will make use of the passed importInterface
405 //! which forwards all import calls to the given \c importInterface.
424 //! which forwards all import calls to the given \c importInterface.
406 //! Passing NULL will install a default QFile importer.
425 //! Passing NULL will install a default QFile importer.
407 //! (\c importInterface ownership stays with caller)
426 //! (\c importInterface ownership stays with caller)
408 void setImporter(PythonQtImportFileInterface* importInterface);
427 void setImporter(PythonQtImportFileInterface* importInterface);
409
428
410 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
429 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
411 //! (without calling setImporter or installDefaultImporter at least once, the default python import
430 //! (without calling setImporter or installDefaultImporter at least once, the default python import
412 //! mechanism is in place)
431 //! mechanism is in place)
413 //! the default importer allows to import files from anywhere QFile can read from,
432 //! the default importer allows to import files from anywhere QFile can read from,
414 //! including the Qt resource system using ":". Keep in mind that you need to extend
433 //! including the Qt resource system using ":". Keep in mind that you need to extend
415 //! "sys.path" with ":" to be able to import from the Qt resources.
434 //! "sys.path" with ":" to be able to import from the Qt resources.
416 void installDefaultImporter() { setImporter(NULL); }
435 void installDefaultImporter() { setImporter(NULL); }
417
436
418 //! set paths that the importer should ignore
437 //! set paths that the importer should ignore
419 void setImporterIgnorePaths(const QStringList& paths);
438 void setImporterIgnorePaths(const QStringList& paths);
420
439
421 //! get paths that the importer should ignore
440 //! get paths that the importer should ignore
422 const QStringList& getImporterIgnorePaths();
441 const QStringList& getImporterIgnorePaths();
423
442
424 //! get access to the file importer (if set)
443 //! get access to the file importer (if set)
425 static PythonQtImportFileInterface* importInterface();
444 static PythonQtImportFileInterface* importInterface();
426
445
427 //@}
446 //@}
428
447
429 //---------------------------------------------------------------------------
448 //---------------------------------------------------------------------------
430 //! \name Other Stuff
449 //! \name Other Stuff
431 //@{
450 //@{
432
451
433 //! get access to internal data (should not be used on the public API, but is used by some C functions)
452 //! get access to internal data (should not be used on the public API, but is used by some C functions)
434 static PythonQtPrivate* priv() { return _self->_p; }
453 static PythonQtPrivate* priv() { return _self->_p; }
435
454
436 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
455 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
437 //! The error is currently just output to the python stderr, future version might implement better trace printing
456 //! The error is currently just output to the python stderr, future version might implement better trace printing
438 bool handleError();
457 bool handleError();
439
458
440 //! clear all NotFound entries on all class infos, to ensure that
459 //! clear all NotFound entries on all class infos, to ensure that
441 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
460 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
442 void clearNotFoundCachedMembers();
461 void clearNotFoundCachedMembers();
443
462
444 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
463 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
445 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
464 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
446 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
465 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
447 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
466 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
448
467
449 //! call the callback if it is set
468 //! call the callback if it is set
450 static void qObjectNoLongerWrappedCB(QObject* o);
469 static void qObjectNoLongerWrappedCB(QObject* o);
451
470
452 //! called by internal help methods
471 //! called by internal help methods
453 PyObject* helpCalled(PythonQtClassInfo* info);
472 PyObject* helpCalled(PythonQtClassInfo* info);
454
473
455 //! returns the found object or NULL
474 //! returns the found object or NULL
456 //! @return new reference
475 //! @return new reference
457 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
476 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
458
477
459 //! sets a callback that is called before and after function calls for profiling
478 //! sets a callback that is called before and after function calls for profiling
460 void setProfilingCallback(ProfilingCB* cb);
479 void setProfilingCallback(ProfilingCB* cb);
461
480
462 //@}
481 //@}
463
482
464 signals:
483 signals:
465 //! emitted when python outputs something to stdout (and redirection is turned on)
484 //! emitted when python outputs something to stdout (and redirection is turned on)
466 void pythonStdOut(const QString& str);
485 void pythonStdOut(const QString& str);
467 //! emitted when python outputs something to stderr (and redirection is turned on)
486 //! emitted when python outputs something to stderr (and redirection is turned on)
468 void pythonStdErr(const QString& str);
487 void pythonStdErr(const QString& str);
469
488
470 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
489 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
471 void pythonHelpRequest(const QByteArray& cppClassName);
490 void pythonHelpRequest(const QByteArray& cppClassName);
472
491
473 private:
492 private:
474 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
493 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
475
494
476 //! callback for stdout redirection, emits pythonStdOut signal
495 //! callback for stdout redirection, emits pythonStdOut signal
477 static void stdOutRedirectCB(const QString& str);
496 static void stdOutRedirectCB(const QString& str);
478 //! callback for stderr redirection, emits pythonStdErr signal
497 //! callback for stderr redirection, emits pythonStdErr signal
479 static void stdErrRedirectCB(const QString& str);
498 static void stdErrRedirectCB(const QString& str);
480
499
481 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
500 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
482 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
501 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
483
502
484 PythonQt(int flags, const QByteArray& pythonQtModuleName);
503 PythonQt(int flags, const QByteArray& pythonQtModuleName);
485 ~PythonQt();
504 ~PythonQt();
486
505
487 static PythonQt* _self;
506 static PythonQt* _self;
488 static int _uniqueModuleCount;
507 static int _uniqueModuleCount;
489
508
490 PythonQtPrivate* _p;
509 PythonQtPrivate* _p;
491
510
492 };
511 };
493
512
494 //! internal PythonQt details
513 //! internal PythonQt details
495 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
514 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
496
515
497 Q_OBJECT
516 Q_OBJECT
498
517
499 public:
518 public:
500 PythonQtPrivate();
519 PythonQtPrivate();
501 ~PythonQtPrivate();
520 ~PythonQtPrivate();
502
521
503 enum DecoratorTypes {
522 enum DecoratorTypes {
504 StaticDecorator = 1,
523 StaticDecorator = 1,
505 ConstructorDecorator = 2,
524 ConstructorDecorator = 2,
506 DestructorDecorator = 4,
525 DestructorDecorator = 4,
507 InstanceDecorator = 8,
526 InstanceDecorator = 8,
508 AllDecorators = 0xffff
527 AllDecorators = 0xffff
509 };
528 };
510
529
511 //! get the suffixes that are used for shared libraries
530 //! get the suffixes that are used for shared libraries
512 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
531 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
513
532
514 //! returns if the id is the id for PythonQtObjectPtr
533 //! returns if the id is the id for PythonQtObjectPtr
515 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
534 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
516
535
517 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
536 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
518 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
537 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
519 //! remove the wrapper ptr again
538 //! remove the wrapper ptr again
520 void removeWrapperPointer(void* obj);
539 void removeWrapperPointer(void* obj);
521
540
522 //! add parent class relation
541 //! add parent class relation
523 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
542 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
524
543
525 //! add a handler for polymorphic downcasting
544 //! add a handler for polymorphic downcasting
526 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
545 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
527
546
528 //! lookup existing classinfo and return new if not yet present
547 //! lookup existing classinfo and return new if not yet present
529 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
548 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
530
549
531 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
550 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
532 void removeSignalEmitter(QObject* obj);
551 void removeSignalEmitter(QObject* obj);
533
552
534 //! wrap the given QObject into a Python object (or return existing wrapper!)
553 //! wrap the given QObject into a Python object (or return existing wrapper!)
535 PyObject* wrapQObject(QObject* obj);
554 PyObject* wrapQObject(QObject* obj);
536
555
537 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
556 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
538 PyObject* wrapPtr(void* ptr, const QByteArray& name);
557 PyObject* wrapPtr(void* ptr, const QByteArray& name);
539
558
540 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
559 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
541 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
560 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
542 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
561 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
543 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
562 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
544
563
545 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
564 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
546 //! (ownership of wrapper is passed to PythonQt)
565 //! (ownership of wrapper is passed to PythonQt)
547 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
566 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
548
567
549 This will add a wrapper object that is used to make calls to the given classname \c typeName.
568 This will add a wrapper object that is used to make calls to the given classname \c typeName.
550 All slots that take a pointer to typeName as the first argument will be callable from Python on
569 All slots that take a pointer to typeName as the first argument will be callable from Python on
551 a variant object that contains such a type.
570 a variant object that contains such a type.
552 */
571 */
553 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
572 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
554
573
555 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
574 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
556 //! and it will register the classes when it first sees a pointer to such a derived class
575 //! and it will register the classes when it first sees a pointer to such a derived class
557 void registerQObjectClassNames(const QStringList& names);
576 void registerQObjectClassNames(const QStringList& names);
558
577
559 //! add a decorator object
578 //! add a decorator object
560 void addDecorators(QObject* o, int decoTypes);
579 void addDecorators(QObject* o, int decoTypes);
561
580
562 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
581 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
563 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
582 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
564
583
565 //! create a new instance of the given enum type with given value (returns a new reference)
584 //! create a new instance of the given enum type with given value (returns a new reference)
566 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
585 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
567
586
568 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
587 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
569 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
588 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
570
589
571 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
590 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
572 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
591 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
573
592
574 //! get the class info for a meta object (if available)
593 //! get the class info for a meta object (if available)
575 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
594 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
576
595
577 //! get the class info for a meta object (if available)
596 //! get the class info for a meta object (if available)
578 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
597 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
579
598
580 //! creates the new module from the given pycode
599 //! creates the new module from the given pycode
581 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
600 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
582
601
583 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
602 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
584 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
603 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
585
604
586 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
605 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
587 static PyObject* dummyTuple();
606 static PyObject* dummyTuple();
588
607
589 //! called by virtual overloads when a python return value can not be converted to the required Qt type
608 //! called by virtual overloads when a python return value can not be converted to the required Qt type
590 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
609 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
591
610
592 //! get access to the PythonQt module
611 //! get access to the PythonQt module
593 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
612 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
594
613
595 //! returns the profiling callback, which may be NULL
614 //! returns the profiling callback, which may be NULL
596 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
615 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
597
616
598 private:
617 private:
599 //! Setup the shared library suffixes by getting them from the "imp" module.
618 //! Setup the shared library suffixes by getting them from the "imp" module.
600 void setupSharedLibrarySuffixes();
619 void setupSharedLibrarySuffixes();
601
620
602 //! create a new pythonqt class wrapper and place it in the pythonqt module
621 //! create a new pythonqt class wrapper and place it in the pythonqt module
603 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
622 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
604
623
605 //! get/create new package module (the returned object is a borrowed reference)
624 //! get/create new package module (the returned object is a borrowed reference)
606 PyObject* packageByName(const char* name);
625 PyObject* packageByName(const char* name);
607
626
608 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
627 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
609 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
628 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
610
629
611 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
630 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
612 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
631 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
613
632
614 //! stores the meta info of known Qt classes
633 //! stores the meta info of known Qt classes
615 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
634 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
616
635
617 //! names of qobject derived classes that can be casted to qobject savely
636 //! names of qobject derived classes that can be casted to qobject savely
618 QHash<QByteArray, bool> _knownQObjectClassNames;
637 QHash<QByteArray, bool> _knownQObjectClassNames;
619
638
620 //! stores signal receivers for QObjects
639 //! stores signal receivers for QObjects
621 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
640 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
622
641
623 //! the PythonQt python module
642 //! the PythonQt python module
624 PythonQtObjectPtr _pythonQtModule;
643 PythonQtObjectPtr _pythonQtModule;
625
644
626 //! the name of the PythonQt python module
645 //! the name of the PythonQt python module
627 QByteArray _pythonQtModuleName;
646 QByteArray _pythonQtModuleName;
628
647
629 //! the importer interface (if set)
648 //! the importer interface (if set)
630 PythonQtImportFileInterface* _importInterface;
649 PythonQtImportFileInterface* _importInterface;
631
650
632 //! the default importer
651 //! the default importer
633 PythonQtQFileImporter* _defaultImporter;
652 PythonQtQFileImporter* _defaultImporter;
634
653
635 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
654 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
636 PythonQtQObjectWrappedCB* _wrappedCB;
655 PythonQtQObjectWrappedCB* _wrappedCB;
637
656
638 QStringList _importIgnorePaths;
657 QStringList _importIgnorePaths;
639 QStringList _sharedLibrarySuffixes;
658 QStringList _sharedLibrarySuffixes;
640
659
641 //! the cpp object wrapper factories
660 //! the cpp object wrapper factories
642 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
661 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
643
662
644 QHash<QByteArray, PyObject*> _packages;
663 QHash<QByteArray, PyObject*> _packages;
645
664
646 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
665 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
647
666
648 PythonQt::ProfilingCB* _profilingCB;
667 PythonQt::ProfilingCB* _profilingCB;
649
668
650 int _initFlags;
669 int _initFlags;
651 int _PythonQtObjectPtr_metaId;
670 int _PythonQtObjectPtr_metaId;
652
671
653 friend class PythonQt;
672 friend class PythonQt;
654 };
673 };
655
674
656 #endif
675 #endif
@@ -1,77 +1,77
1 #ifndef _PYTHONQTCLASSWRAPPER_H
1 #ifndef _PYTHONQTCLASSWRAPPER_H
2 #define _PYTHONQTCLASSWRAPPER_H
2 #define _PYTHONQTCLASSWRAPPER_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 PythonQtClassWrapper.h
38 // \file PythonQtClassWrapper.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48
48
49 #include "structmember.h"
49 #include "structmember.h"
50 #include "methodobject.h"
50 #include "methodobject.h"
51 #include "compile.h"
51 #include "compile.h"
52 #include "eval.h"
52 #include "eval.h"
53 #include <QString>
53 #include <QString>
54
54
55 class PythonQtClassInfo;
55 class PythonQtClassInfo;
56
56
57 //! the type of the PythonQt class wrapper objects
57 //! the type of the PythonQt class wrapper objects
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtClassWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtClassWrapper_Type;
59
59
60 //---------------------------------------------------------------
60 //---------------------------------------------------------------
61 //! a Python wrapper object for PythonQt wrapped classes
61 //! a Python wrapper object for PythonQt wrapped classes
62 //! which inherits from the Python type object to allow
62 //! which inherits from the Python type object to allow
63 //! deriving of wrapped CPP classes from Python.
63 //! deriving of wrapped CPP classes from Python.
64 typedef struct {
64 typedef struct {
65 PyHeapTypeObject _base;
65 PyHeapTypeObject _base;
66
66
67 //! the additional class information that PythonQt stores for the CPP class
67 //! the additional class information that PythonQt stores for the CPP class
68 PythonQtClassInfo* _classInfo;
68 PythonQtClassInfo* _classInfo;
69
69
70 //! get the class info
70 //! get the class info
71 PythonQtClassInfo* classInfo() { return _classInfo; }
71 PythonQtClassInfo* classInfo() { return _classInfo; }
72
72
73 } PythonQtClassWrapper;
73 } PythonQtClassWrapper;
74
74
75 //---------------------------------------------------------------
75 //---------------------------------------------------------------
76
76
77 #endif
77 #endif
@@ -1,1236 +1,1229
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 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (info.pointerCount==0) {
65 if (info.pointerCount==0) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 if (innerType.endsWith("*")) {
84 if (innerType.endsWith("*")) {
85 innerType.truncate(innerType.length()-1);
85 innerType.truncate(innerType.length()-1);
86 QList<void*>* listPtr = NULL;
86 QList<void*>* listPtr = NULL;
87 if (info.pointerCount == 1) {
87 if (info.pointerCount == 1) {
88 listPtr = *((QList<void*>**)data);
88 listPtr = *((QList<void*>**)data);
89 } else if (info.pointerCount == 0) {
89 } else if (info.pointerCount == 0) {
90 listPtr = (QList<void*>*)data;
90 listPtr = (QList<void*>*)data;
91 }
91 }
92 if (listPtr) {
92 if (listPtr) {
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
94 } else {
94 } else {
95 return NULL;
95 return NULL;
96 }
96 }
97 }
97 }
98 }
98 }
99
99
100 if (info.typeId >= QMetaType::User) {
100 if (info.typeId >= QMetaType::User) {
101 // if a converter is registered, we use is:
101 // if a converter is registered, we use is:
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
103 if (converter) {
103 if (converter) {
104 return (*converter)(data, info.typeId);
104 return (*converter)(data, info.typeId);
105 }
105 }
106 }
106 }
107
107
108 // special handling did not match, so we convert the usual way (either pointer or value version):
108 // special handling did not match, so we convert the usual way (either pointer or value version):
109 if (info.pointerCount == 1) {
109 if (info.pointerCount == 1) {
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
112 } else if (info.pointerCount == 0) {
112 } else if (info.pointerCount == 0) {
113 // handle values that are not yet handled and not pointers
113 // handle values that are not yet handled and not pointers
114 return ConvertQtValueToPythonInternal(info.typeId, data);
114 return ConvertQtValueToPythonInternal(info.typeId, data);
115 } else {
115 } else {
116 return NULL;
116 return NULL;
117 }
117 }
118 }
118 }
119
119
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
121 switch (type) {
121 switch (type) {
122 case QMetaType::Void:
122 case QMetaType::Void:
123 Py_INCREF(Py_None);
123 Py_INCREF(Py_None);
124 return Py_None;
124 return Py_None;
125 case QMetaType::Char:
125 case QMetaType::Char:
126 return PyInt_FromLong(*((char*)data));
126 return PyInt_FromLong(*((char*)data));
127 case QMetaType::UChar:
127 case QMetaType::UChar:
128 return PyInt_FromLong(*((unsigned char*)data));
128 return PyInt_FromLong(*((unsigned char*)data));
129 case QMetaType::Short:
129 case QMetaType::Short:
130 return PyInt_FromLong(*((short*)data));
130 return PyInt_FromLong(*((short*)data));
131 case QMetaType::UShort:
131 case QMetaType::UShort:
132 return PyInt_FromLong(*((unsigned short*)data));
132 return PyInt_FromLong(*((unsigned short*)data));
133 case QMetaType::Long:
133 case QMetaType::Long:
134 return PyInt_FromLong(*((long*)data));
134 return PyInt_FromLong(*((long*)data));
135 case QMetaType::ULong:
135 case QMetaType::ULong:
136 // does not fit into simple int of python
136 // does not fit into simple int of python
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
138 case QMetaType::Bool:
138 case QMetaType::Bool:
139 return PythonQtConv::GetPyBool(*((bool*)data));
139 return PythonQtConv::GetPyBool(*((bool*)data));
140 case QMetaType::Int:
140 case QMetaType::Int:
141 return PyInt_FromLong(*((int*)data));
141 return PyInt_FromLong(*((int*)data));
142 case QMetaType::UInt:
142 case QMetaType::UInt:
143 // does not fit into simple int of python
143 // does not fit into simple int of python
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
145 case QMetaType::QChar:
145 case QMetaType::QChar:
146 return PyInt_FromLong(*((short*)data));
146 return PyInt_FromLong(*((short*)data));
147 case QMetaType::Float:
147 case QMetaType::Float:
148 return PyFloat_FromDouble(*((float*)data));
148 return PyFloat_FromDouble(*((float*)data));
149 case QMetaType::Double:
149 case QMetaType::Double:
150 return PyFloat_FromDouble(*((double*)data));
150 return PyFloat_FromDouble(*((double*)data));
151 case QMetaType::LongLong:
151 case QMetaType::LongLong:
152 return PyLong_FromLongLong(*((qint64*)data));
152 return PyLong_FromLongLong(*((qint64*)data));
153 case QMetaType::ULongLong:
153 case QMetaType::ULongLong:
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
155 // implicit conversion from QByteArray to str has been removed:
155 // implicit conversion from QByteArray to str has been removed:
156 //case QMetaType::QByteArray: {
156 //case QMetaType::QByteArray: {
157 // QByteArray* v = (QByteArray*) data;
157 // QByteArray* v = (QByteArray*) data;
158 // return PyString_FromStringAndSize(*v, v->size());
158 // return PyString_FromStringAndSize(*v, v->size());
159 // }
159 // }
160 case QMetaType::QVariantMap:
160 case QMetaType::QVariantMap:
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
162 case QMetaType::QVariantList:
162 case QMetaType::QVariantList:
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
164 case QMetaType::QString:
164 case QMetaType::QString:
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
166 case QMetaType::QStringList:
166 case QMetaType::QStringList:
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
168
168
169 case PythonQtMethodInfo::Variant:
169 case PythonQtMethodInfo::Variant:
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
171 case QMetaType::QObjectStar:
171 case QMetaType::QObjectStar:
172 case QMetaType::QWidgetStar:
172 case QMetaType::QWidgetStar:
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
174
174
175 default:
175 default:
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
179 Py_INCREF(o);
179 Py_INCREF(o);
180 return o;
180 return o;
181 } else {
181 } else {
182 if (type > 0) {
182 if (type > 0) {
183 // if the type is known, we can construct it via QMetaType::construct
183 // if the type is known, we can construct it via QMetaType::construct
184 void* newCPPObject = QMetaType::construct(type, data);
184 void* newCPPObject = QMetaType::construct(type, data);
185 // XXX this could be optimized by using metatypeid directly
185 // XXX this could be optimized by using metatypeid directly
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
187 wrap->_ownedByPythonQt = true;
187 wrap->_ownedByPythonQt = true;
188 wrap->_useQMetaTypeDestroy = true;
188 wrap->_useQMetaTypeDestroy = true;
189 return (PyObject*)wrap;
189 return (PyObject*)wrap;
190 }
190 }
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
192 }
192 }
193 }
193 }
194 Py_INCREF(Py_None);
194 Py_INCREF(Py_None);
195 return Py_None;
195 return Py_None;
196 }
196 }
197
197
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
199 void* ptr = NULL;
199 void* ptr = NULL;
200 if (info.pointerCount>1) {
200 if (info.pointerCount>1) {
201 return NULL;
201 return NULL;
202 } else if (info.pointerCount==1) {
202 } else if (info.pointerCount==1) {
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
204 } else if (info.enumWrapper) {
204 } else if (info.enumWrapper) {
205 // create enum return value
205 // create enum return value
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
207 } else {
207 } else {
208 switch (info.typeId) {
208 switch (info.typeId) {
209 case QMetaType::Char:
209 case QMetaType::Char:
210 case QMetaType::UChar:
210 case QMetaType::UChar:
211 case QMetaType::Short:
211 case QMetaType::Short:
212 case QMetaType::UShort:
212 case QMetaType::UShort:
213 case QMetaType::Long:
213 case QMetaType::Long:
214 case QMetaType::ULong:
214 case QMetaType::ULong:
215 case QMetaType::Bool:
215 case QMetaType::Bool:
216 case QMetaType::Int:
216 case QMetaType::Int:
217 case QMetaType::UInt:
217 case QMetaType::UInt:
218 case QMetaType::QChar:
218 case QMetaType::QChar:
219 case QMetaType::Float:
219 case QMetaType::Float:
220 case QMetaType::Double:
220 case QMetaType::Double:
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
222 break;
222 break;
223 case PythonQtMethodInfo::Variant:
223 case PythonQtMethodInfo::Variant:
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
225 // return the ptr to the variant
225 // return the ptr to the variant
226 break;
226 break;
227 default:
227 default:
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
230 if (info.name.startsWith("QList<")) {
230 if (info.name.startsWith("QList<")) {
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
232 if (innerType.endsWith("*")) {
232 if (innerType.endsWith("*")) {
233 static int id = QMetaType::type("QList<void*>");
233 static int id = QMetaType::type("QList<void*>");
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
235 // return the constData pointer that will be filled with the result value later on
235 // return the constData pointer that will be filled with the result value later on
236 ptr = (void*)((QVariant*)ptr)->constData();
236 ptr = (void*)((QVariant*)ptr)->constData();
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
242 // everything else is stored in a QVariant, if we know the meta type...
242 // everything else is stored in a QVariant, if we know the meta type...
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
244 // return the constData pointer that will be filled with the result value later on
244 // return the constData pointer that will be filled with the result value later on
245 ptr = (void*)((QVariant*)ptr)->constData();
245 ptr = (void*)((QVariant*)ptr)->constData();
246 }
246 }
247 }
247 }
248 }
248 }
249 return ptr;
249 return ptr;
250 }
250 }
251
251
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
253 {
253 {
254 void* object;
254 void* object;
255 if (wrapper->classInfo()->isCPPWrapper()) {
255 if (wrapper->classInfo()->isCPPWrapper()) {
256 object = wrapper->_wrappedPtr;
256 object = wrapper->_wrappedPtr;
257 } else {
257 } else {
258 QObject* tmp = wrapper->_obj;
258 QObject* tmp = wrapper->_obj;
259 object = tmp;
259 object = tmp;
260 }
260 }
261 if (object) {
261 if (object) {
262 // if we can be upcasted to the given name, we pass the casted pointer in:
262 // if we can be upcasted to the given name, we pass the casted pointer in:
263 object = wrapper->classInfo()->castTo(object, className);
263 object = wrapper->classInfo()->castTo(object, className);
264 ok = object!=NULL;
264 ok = object!=NULL;
265 } else {
265 } else {
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
267 ok = wrapper->classInfo()->inherits(className);
267 ok = wrapper->classInfo()->inherits(className);
268 }
268 }
269 return object;
269 return object;
270 }
270 }
271
271
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
273 {
273 {
274 void* ptr = alreadyAllocatedCPPObject;
274 void* ptr = alreadyAllocatedCPPObject;
275
275
276 static int penId = QMetaType::type("QPen");
276 static int penId = QMetaType::type("QPen");
277 static int brushId = QMetaType::type("QBrush");
277 static int brushId = QMetaType::type("QBrush");
278 static int cursorId = QMetaType::type("QCursor");
278 static int cursorId = QMetaType::type("QCursor");
279 static int colorId = QMetaType::type("QColor");
279 static int colorId = QMetaType::type("QColor");
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
281 if (typeId == cursorId) {
281 if (typeId == cursorId) {
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
285 if (!ptr) {
285 if (!ptr) {
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
287 ptr = (void*)((QVariant*)ptr)->constData();
287 ptr = (void*)((QVariant*)ptr)->constData();
288 }
288 }
289 *((QCursor*)ptr) = QCursor(val);
289 *((QCursor*)ptr) = QCursor(val);
290 return ptr;
290 return ptr;
291 }
291 }
292 } else if (typeId == penId) {
292 } else if (typeId == penId) {
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
297 if (!ptr) {
297 if (!ptr) {
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
299 ptr = (void*)((QVariant*)ptr)->constData();
299 ptr = (void*)((QVariant*)ptr)->constData();
300 }
300 }
301 *((QPen*)ptr) = QPen(QColor(val));
301 *((QPen*)ptr) = QPen(QColor(val));
302 return ptr;
302 return ptr;
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
304 if (!ptr) {
304 if (!ptr) {
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
306 ptr = (void*)((QVariant*)ptr)->constData();
306 ptr = (void*)((QVariant*)ptr)->constData();
307 }
307 }
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
309 return ptr;
309 return ptr;
310 }
310 }
311 } else if (typeId == brushId) {
311 } else if (typeId == brushId) {
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
316 if (!ptr) {
316 if (!ptr) {
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
318 ptr = (void*)((QVariant*)ptr)->constData();
318 ptr = (void*)((QVariant*)ptr)->constData();
319 }
319 }
320 *((QBrush*)ptr) = QBrush(QColor(val));
320 *((QBrush*)ptr) = QBrush(QColor(val));
321 return ptr;
321 return ptr;
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
323 if (!ptr) {
323 if (!ptr) {
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
325 ptr = (void*)((QVariant*)ptr)->constData();
325 ptr = (void*)((QVariant*)ptr)->constData();
326 }
326 }
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
328 return ptr;
328 return ptr;
329 }
329 }
330 } else if (typeId == colorId) {
330 } else if (typeId == colorId) {
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
334 if (!ptr) {
334 if (!ptr) {
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
336 ptr = (void*)((QVariant*)ptr)->constData();
336 ptr = (void*)((QVariant*)ptr)->constData();
337 }
337 }
338 *((QColor*)ptr) = QColor(val);
338 *((QColor*)ptr) = QColor(val);
339 return ptr;
339 return ptr;
340 }
340 }
341 }
341 }
342 return NULL;
342 return NULL;
343 }
343 }
344
344
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
346 {
346 {
347 bool ok = false;
347 bool ok = false;
348 void* ptr = NULL;
348 void* ptr = NULL;
349
349
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
351 if (info.pointerCount==0 && !strict) {
351 if (info.pointerCount==0 && !strict) {
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
353 if (ptr) {
353 if (ptr) {
354 return ptr;
354 return ptr;
355 }
355 }
356 }
356 }
357
357
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
360 // (the Variant case is handled below in a switch)
360 // (the Variant case is handled below in a switch)
361
361
362 // a C++ wrapper (can be passed as pointer or reference)
362 // a C++ wrapper (can be passed as pointer or reference)
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
364 void* object = castWrapperTo(wrap, info.name, ok);
364 void* object = castWrapperTo(wrap, info.name, ok);
365 if (ok) {
365 if (ok) {
366 if (info.pointerCount==1) {
366 if (info.pointerCount==1) {
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
369 } else if (info.pointerCount==0) {
369 } else if (info.pointerCount==0) {
370 // store the wrapped pointer directly, since we are a reference
370 // store the wrapped pointer directly, since we are a reference
371 ptr = object;
371 ptr = object;
372 }
372 }
373 } else {
373 } else {
374 // not matching
374 // not matching
375 }
375 }
376 } else if (info.pointerCount == 1) {
376 } else if (info.pointerCount == 1) {
377 // a pointer
377 // a pointer
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
379 {
379 {
380 QString str = PyObjGetString(obj, strict, ok);
380 QString str = PyObjGetString(obj, strict, ok);
381 if (ok) {
381 if (ok) {
382 void* ptr2 = NULL;
382 void* ptr2 = NULL;
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
385 }
385 }
386 } else if (info.name == "PyObject") {
386 } else if (info.name == "PyObject") {
387 // handle low level PyObject directly
387 // handle low level PyObject directly
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
389 } else if (obj == Py_None) {
389 }
390 // TODO XXX: pass obj and name and add when it returns a pointer
391 else if (obj == Py_None) {
390 // None is treated as a NULL ptr
392 // None is treated as a NULL ptr
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
392 } else {
394 } else {
393 // if we are not strict, we try if we are passed a 0 integer
395 // if we are not strict, we try if we are passed a 0 integer
394 if (!strict) {
396 if (!strict) {
395 bool ok;
397 bool ok;
396 int value = PyObjGetInt(obj, true, ok);
398 int value = PyObjGetInt(obj, true, ok);
397 if (ok && value==0) {
399 if (ok && value==0) {
398 // TODOXXX is this wise? or should it be expected from the programmer to use None?
400 // TODOXXX is this wise? or should it be expected from the programmer to use None?
399 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
400 }
402 }
401 }
403 }
402 }
404 }
403 } else if (info.pointerCount == 0) {
405 } else if (info.pointerCount == 0) {
404 // not a pointer
406 // not a pointer
405 switch (info.typeId) {
407 switch (info.typeId) {
406 case QMetaType::Char:
408 case QMetaType::Char:
407 {
409 {
408 int val = PyObjGetInt(obj, strict, ok);
410 int val = PyObjGetInt(obj, strict, ok);
409 if (ok) {
411 if (ok) {
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
412 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
411 }
413 }
412 }
414 }
413 break;
415 break;
414 case QMetaType::UChar:
416 case QMetaType::UChar:
415 {
417 {
416 int val = PyObjGetInt(obj, strict, ok);
418 int val = PyObjGetInt(obj, strict, ok);
417 if (ok) {
419 if (ok) {
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
419 }
421 }
420 }
422 }
421 break;
423 break;
422 case QMetaType::Short:
424 case QMetaType::Short:
423 {
425 {
424 int val = PyObjGetInt(obj, strict, ok);
426 int val = PyObjGetInt(obj, strict, ok);
425 if (ok) {
427 if (ok) {
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
428 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
427 }
429 }
428 }
430 }
429 break;
431 break;
430 case QMetaType::UShort:
432 case QMetaType::UShort:
431 {
433 {
432 int val = PyObjGetInt(obj, strict, ok);
434 int val = PyObjGetInt(obj, strict, ok);
433 if (ok) {
435 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
436 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
435 }
437 }
436 }
438 }
437 break;
439 break;
438 case QMetaType::Long:
440 case QMetaType::Long:
439 {
441 {
440 long val = (long)PyObjGetLongLong(obj, strict, ok);
442 long val = (long)PyObjGetLongLong(obj, strict, ok);
441 if (ok) {
443 if (ok) {
442 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
443 }
445 }
444 }
446 }
445 break;
447 break;
446 case QMetaType::ULong:
448 case QMetaType::ULong:
447 {
449 {
448 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
450 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
449 if (ok) {
451 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
452 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
451 }
453 }
452 }
454 }
453 break;
455 break;
454 case QMetaType::Bool:
456 case QMetaType::Bool:
455 {
457 {
456 bool val = PyObjGetBool(obj, strict, ok);
458 bool val = PyObjGetBool(obj, strict, ok);
457 if (ok) {
459 if (ok) {
458 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
460 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
459 }
461 }
460 }
462 }
461 break;
463 break;
462 case QMetaType::Int:
464 case QMetaType::Int:
463 {
465 {
464 int val = PyObjGetInt(obj, strict, ok);
466 int val = PyObjGetInt(obj, strict, ok);
465 if (ok) {
467 if (ok) {
466 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
468 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
467 }
469 }
468 }
470 }
469 break;
471 break;
470 case QMetaType::UInt:
472 case QMetaType::UInt:
471 {
473 {
472 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
474 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
473 if (ok) {
475 if (ok) {
474 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
476 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
475 }
477 }
476 }
478 }
477 break;
479 break;
478 case QMetaType::QChar:
480 case QMetaType::QChar:
479 {
481 {
480 int val = PyObjGetInt(obj, strict, ok);
482 int val = PyObjGetInt(obj, strict, ok);
481 if (ok) {
483 if (ok) {
482 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
484 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
483 }
485 }
484 }
486 }
485 break;
487 break;
486 case QMetaType::Float:
488 case QMetaType::Float:
487 {
489 {
488 float val = (float)PyObjGetDouble(obj, strict, ok);
490 float val = (float)PyObjGetDouble(obj, strict, ok);
489 if (ok) {
491 if (ok) {
490 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
492 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
491 }
493 }
492 }
494 }
493 break;
495 break;
494 case QMetaType::Double:
496 case QMetaType::Double:
495 {
497 {
496 double val = (double)PyObjGetDouble(obj, strict, ok);
498 double val = (double)PyObjGetDouble(obj, strict, ok);
497 if (ok) {
499 if (ok) {
498 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
500 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
499 }
501 }
500 }
502 }
501 break;
503 break;
502 case QMetaType::LongLong:
504 case QMetaType::LongLong:
503 {
505 {
504 qint64 val = PyObjGetLongLong(obj, strict, ok);
506 qint64 val = PyObjGetLongLong(obj, strict, ok);
505 if (ok) {
507 if (ok) {
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
507 }
509 }
508 }
510 }
509 break;
511 break;
510 case QMetaType::ULongLong:
512 case QMetaType::ULongLong:
511 {
513 {
512 quint64 val = PyObjGetULongLong(obj, strict, ok);
514 quint64 val = PyObjGetULongLong(obj, strict, ok);
513 if (ok) {
515 if (ok) {
514 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
515 }
517 }
516 }
518 }
517 break;
519 break;
518 case QMetaType::QByteArray:
520 case QMetaType::QByteArray:
519 {
521 {
520 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
522 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
521 if (ok) {
523 if (ok) {
522 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
524 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
523 ptr = (void*)((QVariant*)ptr)->constData();
525 ptr = (void*)((QVariant*)ptr)->constData();
524 }
526 }
525 }
527 }
526 break;
528 break;
527 case QMetaType::QString:
529 case QMetaType::QString:
528 {
530 {
529 QString str = PyObjGetString(obj, strict, ok);
531 QString str = PyObjGetString(obj, strict, ok);
530 if (ok) {
532 if (ok) {
531 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
533 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
532 ptr = (void*)((QVariant*)ptr)->constData();
534 ptr = (void*)((QVariant*)ptr)->constData();
533 }
535 }
534 }
536 }
535 break;
537 break;
536 case QMetaType::QStringList:
538 case QMetaType::QStringList:
537 {
539 {
538 QStringList l = PyObjToStringList(obj, strict, ok);
540 QStringList l = PyObjToStringList(obj, strict, ok);
539 if (ok) {
541 if (ok) {
540 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
542 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
541 ptr = (void*)((QVariant*)ptr)->constData();
543 ptr = (void*)((QVariant*)ptr)->constData();
542 }
544 }
543 }
545 }
544 break;
546 break;
545
547
546 case PythonQtMethodInfo::Variant:
548 case PythonQtMethodInfo::Variant:
547 {
549 {
548 QVariant v = PyObjToQVariant(obj);
550 QVariant v = PyObjToQVariant(obj);
549 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
551 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
550 // so we do not check v.isValid() here
552 // so we do not check v.isValid() here
551 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
553 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
552 }
554 }
553 break;
555 break;
554 default:
556 default:
555 {
557 {
556 // check for enum case
558 // check for enum case
557 if (info.enumWrapper) {
559 if (info.enumWrapper) {
558 unsigned int val;
560 unsigned int val;
559 ok = false;
561 ok = false;
560 if ((PyObject*)obj->ob_type == info.enumWrapper) {
562 if ((PyObject*)obj->ob_type == info.enumWrapper) {
561 // we have a exact enum type match:
563 // we have a exact enum type match:
562 val = PyInt_AS_LONG(obj);
564 val = PyInt_AS_LONG(obj);
563 ok = true;
565 ok = true;
564 } else if (!strict) {
566 } else if (!strict) {
565 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
567 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
566 // we want an integer overload to be taken first!
568 // we want an integer overload to be taken first!
567 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
569 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
568 }
570 }
569 if (ok) {
571 if (ok) {
570 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
572 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
571 return ptr;
573 return ptr;
572 } else {
574 } else {
573 return NULL;
575 return NULL;
574 }
576 }
575 }
577 }
576
578
577 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
579 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
578 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
580 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
579 if (info.name.startsWith("QList<")) {
581 if (info.name.startsWith("QList<")) {
580 QByteArray innerType = info.name.mid(6,info.name.length()-7);
582 QByteArray innerType = info.name.mid(6,info.name.length()-7);
581 if (innerType.endsWith("*")) {
583 if (innerType.endsWith("*")) {
582 innerType.truncate(innerType.length()-1);
584 innerType.truncate(innerType.length()-1);
583 static int id = QMetaType::type("QList<void*>");
585 static int id = QMetaType::type("QList<void*>");
584 if (!alreadyAllocatedCPPObject) {
586 if (!alreadyAllocatedCPPObject) {
585 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
587 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
586 ptr = (void*)((QVariant*)ptr)->constData();
588 ptr = (void*)((QVariant*)ptr)->constData();
587 } else {
589 } else {
588 ptr = alreadyAllocatedCPPObject;
590 ptr = alreadyAllocatedCPPObject;
589 }
591 }
590 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
592 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
591 if (ok) {
593 if (ok) {
592 return ptr;
594 return ptr;
593 } else {
595 } else {
594 return NULL;
596 return NULL;
595 }
597 }
596 }
598 }
597 }
599 }
598 }
600 }
599
601
600 // We only do this for registered type > QMetaType::User for performance reasons.
602 // We only do this for registered type > QMetaType::User for performance reasons.
601 if (info.typeId >= QMetaType::User) {
603 if (info.typeId >= QMetaType::User) {
602 // Maybe we have a special converter that is registered for that type:
604 // Maybe we have a special converter that is registered for that type:
603 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
605 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
604 if (converter) {
606 if (converter) {
605 if (!alreadyAllocatedCPPObject) {
607 if (!alreadyAllocatedCPPObject) {
606 // create a new empty variant of concrete type:
608 // create a new empty variant of concrete type:
607 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
609 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
608 ptr = (void*)((QVariant*)ptr)->constData();
610 ptr = (void*)((QVariant*)ptr)->constData();
609 } else {
611 } else {
610 ptr = alreadyAllocatedCPPObject;
612 ptr = alreadyAllocatedCPPObject;
611 }
613 }
612 // now call the converter, passing the internal object of the variant
614 // now call the converter, passing the internal object of the variant
613 ok = (*converter)(obj, ptr, info.typeId, strict);
615 ok = (*converter)(obj, ptr, info.typeId, strict);
614 if (ok) {
616 if (ok) {
615 return ptr;
617 return ptr;
616 } else {
618 } else {
617 return NULL;
619 return NULL;
618 }
620 }
619 }
621 }
620 }
622 }
621 // if no type id is available, conversion to a QVariant makes no sense/is not possible
623 // if no type id is available, conversion to a QVariant makes no sense/is not possible
622 if (info.typeId != PythonQtMethodInfo::Unknown) {
624 if (info.typeId != PythonQtMethodInfo::Unknown) {
623 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
625 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
624 QVariant v = PyObjToQVariant(obj, info.typeId);
626 QVariant v = PyObjToQVariant(obj, info.typeId);
625 if (v.isValid()) {
627 if (v.isValid()) {
626 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
628 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
627 ptr = (void*)((QVariant*)ptr)->constData();
629 ptr = (void*)((QVariant*)ptr)->constData();
628 }
630 }
629 }
631 }
630 }
632 }
631 }
633 }
632 }
634 }
633 return ptr;
635 return ptr;
634 }
636 }
635
637
636
638
637 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
639 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
638 QStringList v;
640 QStringList v;
639 ok = false;
641 ok = false;
640 // if we are strict, we do not want to convert a string to a stringlist
642 // if we are strict, we do not want to convert a string to a stringlist
641 // (strings in python are detected to be sequences)
643 // (strings in python are detected to be sequences)
642 if (strict &&
644 if (strict &&
643 (val->ob_type == &PyString_Type ||
645 (val->ob_type == &PyString_Type ||
644 PyUnicode_Check(val))) {
646 PyUnicode_Check(val))) {
645 ok = false;
647 ok = false;
646 return v;
648 return v;
647 }
649 }
648 if (PySequence_Check(val)) {
650 if (PySequence_Check(val)) {
649 int count = PySequence_Size(val);
651 int count = PySequence_Size(val);
650 for (int i = 0;i<count;i++) {
652 for (int i = 0;i<count;i++) {
651 PyObject* value = PySequence_GetItem(val,i);
653 PyObject* value = PySequence_GetItem(val,i);
652 v.append(PyObjGetString(value,false,ok));
654 v.append(PyObjGetString(value,false,ok));
653 }
655 }
654 ok = true;
656 ok = true;
655 }
657 }
656 return v;
658 return v;
657 }
659 }
658
660
659 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
661 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
660 {
662 {
661 QString r;
663 QString r;
662 PyObject* str = PyObject_Repr(val);
664 PyObject* str = PyObject_Repr(val);
663 if (str) {
665 if (str) {
664 r = QString(PyString_AS_STRING(str));
666 r = QString(PyString_AS_STRING(str));
665 Py_DECREF(str);
667 Py_DECREF(str);
666 }
668 }
667 return r;
669 return r;
668 }
670 }
669
671
670 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
672 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
671 QString r;
673 QString r;
672 ok = true;
674 ok = true;
673 if (val->ob_type == &PyString_Type) {
675 if (val->ob_type == &PyString_Type) {
674 r = QString(PyString_AS_STRING(val));
676 r = QString(PyString_AS_STRING(val));
675 } else if (PyUnicode_Check(val)) {
677 } else if (PyUnicode_Check(val)) {
676 #ifdef WIN32
677 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
678 #else
679 PyObject *ptmp = PyUnicode_AsUTF8String(val);
678 PyObject *ptmp = PyUnicode_AsUTF8String(val);
680 if(ptmp) {
679 if(ptmp) {
681 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
680 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
682 Py_DECREF(ptmp);
681 Py_DECREF(ptmp);
683 }
682 }
684 #endif
685 } else if (!strict) {
683 } else if (!strict) {
686 // EXTRA: could also use _Unicode, but why should we?
684 // EXTRA: could also use _Unicode, but why should we?
687 PyObject* str = PyObject_Str(val);
685 PyObject* str = PyObject_Str(val);
688 if (str) {
686 if (str) {
689 r = QString(PyString_AS_STRING(str));
687 r = QString(PyString_AS_STRING(str));
690 Py_DECREF(str);
688 Py_DECREF(str);
691 } else {
689 } else {
692 ok = false;
690 ok = false;
693 }
691 }
694 } else {
692 } else {
695 ok = false;
693 ok = false;
696 }
694 }
697 return r;
695 return r;
698 }
696 }
699
697
700 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
698 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
701 // TODO: support buffer objects in general
699 // TODO: support buffer objects in general
702 QByteArray r;
700 QByteArray r;
703 ok = true;
701 ok = true;
704 if (val->ob_type == &PyString_Type) {
702 if (val->ob_type == &PyString_Type) {
705 long size = PyString_GET_SIZE(val);
703 long size = PyString_GET_SIZE(val);
706 r = QByteArray(PyString_AS_STRING(val), size);
704 r = QByteArray(PyString_AS_STRING(val), size);
707 } else {
705 } else {
708 ok = false;
706 ok = false;
709 }
707 }
710 return r;
708 return r;
711 }
709 }
712
710
713 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
711 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
714 bool d = false;
712 bool d = false;
715 ok = false;
713 ok = false;
716 if (val == Py_False) {
714 if (val == Py_False) {
717 d = false;
715 d = false;
718 ok = true;
716 ok = true;
719 } else if (val == Py_True) {
717 } else if (val == Py_True) {
720 d = true;
718 d = true;
721 ok = true;
719 ok = true;
722 } else if (!strict) {
720 } else if (!strict) {
723 d = PyObjGetInt(val, false, ok)!=0;
721 d = PyObjGetInt(val, false, ok)!=0;
724 ok = true;
722 ok = true;
725 }
723 }
726 return d;
724 return d;
727 }
725 }
728
726
729 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
727 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
730 int d = 0;
728 int d = 0;
731 ok = true;
729 ok = true;
732 if (val->ob_type == &PyInt_Type) {
730 if (val->ob_type == &PyInt_Type) {
733 d = PyInt_AS_LONG(val);
731 d = PyInt_AS_LONG(val);
734 } else if (!strict) {
732 } else if (!strict) {
735 if (PyObject_TypeCheck(val, &PyInt_Type)) {
733 if (PyObject_TypeCheck(val, &PyInt_Type)) {
736 // support for derived int classes, e.g. for our enums
734 // support for derived int classes, e.g. for our enums
737 d = PyInt_AS_LONG(val);
735 d = PyInt_AS_LONG(val);
738 } else if (val->ob_type == &PyFloat_Type) {
736 } else if (val->ob_type == &PyFloat_Type) {
739 d = floor(PyFloat_AS_DOUBLE(val));
737 d = floor(PyFloat_AS_DOUBLE(val));
740 } else if (val->ob_type == &PyLong_Type) {
738 } else if (val->ob_type == &PyLong_Type) {
741 // handle error on overflow!
739 // handle error on overflow!
742 d = PyLong_AsLong(val);
740 d = PyLong_AsLong(val);
743 } else if (val == Py_False) {
741 } else if (val == Py_False) {
744 d = 0;
742 d = 0;
745 } else if (val == Py_True) {
743 } else if (val == Py_True) {
746 d = 1;
744 d = 1;
747 } else {
745 } else {
748 ok = false;
746 ok = false;
749 }
747 }
750 } else {
748 } else {
751 ok = false;
749 ok = false;
752 }
750 }
753 return d;
751 return d;
754 }
752 }
755
753
756 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
754 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
757 qint64 d = 0;
755 qint64 d = 0;
758 ok = true;
756 ok = true;
759 if (val->ob_type == &PyInt_Type) {
757 if (val->ob_type == &PyInt_Type) {
760 d = PyInt_AS_LONG(val);
758 d = PyInt_AS_LONG(val);
761 } else if (val->ob_type == &PyLong_Type) {
759 } else if (val->ob_type == &PyLong_Type) {
762 d = PyLong_AsLongLong(val);
760 d = PyLong_AsLongLong(val);
763 } else if (!strict) {
761 } else if (!strict) {
764 if (PyObject_TypeCheck(val, &PyInt_Type)) {
762 if (PyObject_TypeCheck(val, &PyInt_Type)) {
765 // support for derived int classes, e.g. for our enums
763 // support for derived int classes, e.g. for our enums
766 d = PyInt_AS_LONG(val);
764 d = PyInt_AS_LONG(val);
767 } else if (val->ob_type == &PyFloat_Type) {
765 } else if (val->ob_type == &PyFloat_Type) {
768 d = floor(PyFloat_AS_DOUBLE(val));
766 d = floor(PyFloat_AS_DOUBLE(val));
769 } else if (val == Py_False) {
767 } else if (val == Py_False) {
770 d = 0;
768 d = 0;
771 } else if (val == Py_True) {
769 } else if (val == Py_True) {
772 d = 1;
770 d = 1;
773 } else {
771 } else {
774 ok = false;
772 ok = false;
775 }
773 }
776 } else {
774 } else {
777 ok = false;
775 ok = false;
778 }
776 }
779 return d;
777 return d;
780 }
778 }
781
779
782 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
780 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
783 quint64 d = 0;
781 quint64 d = 0;
784 ok = true;
782 ok = true;
785 if (PyObject_TypeCheck(val, &PyInt_Type)) {
783 if (PyObject_TypeCheck(val, &PyInt_Type)) {
786 d = PyInt_AS_LONG(val);
784 d = PyInt_AS_LONG(val);
787 } else if (val->ob_type == &PyLong_Type) {
785 } else if (val->ob_type == &PyLong_Type) {
788 d = PyLong_AsLongLong(val);
786 d = PyLong_AsLongLong(val);
789 } else if (!strict) {
787 } else if (!strict) {
790 if (PyObject_TypeCheck(val, &PyInt_Type)) {
788 if (PyObject_TypeCheck(val, &PyInt_Type)) {
791 // support for derived int classes, e.g. for our enums
789 // support for derived int classes, e.g. for our enums
792 d = PyInt_AS_LONG(val);
790 d = PyInt_AS_LONG(val);
793 } else if (val->ob_type == &PyFloat_Type) {
791 } else if (val->ob_type == &PyFloat_Type) {
794 d = floor(PyFloat_AS_DOUBLE(val));
792 d = floor(PyFloat_AS_DOUBLE(val));
795 } else if (val == Py_False) {
793 } else if (val == Py_False) {
796 d = 0;
794 d = 0;
797 } else if (val == Py_True) {
795 } else if (val == Py_True) {
798 d = 1;
796 d = 1;
799 } else {
797 } else {
800 ok = false;
798 ok = false;
801 }
799 }
802 } else {
800 } else {
803 ok = false;
801 ok = false;
804 }
802 }
805 return d;
803 return d;
806 }
804 }
807
805
808 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
806 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
809 double d = 0;
807 double d = 0;
810 ok = true;
808 ok = true;
811 if (val->ob_type == &PyFloat_Type) {
809 if (val->ob_type == &PyFloat_Type) {
812 d = PyFloat_AS_DOUBLE(val);
810 d = PyFloat_AS_DOUBLE(val);
813 } else if (!strict) {
811 } else if (!strict) {
814 if (PyObject_TypeCheck(val, &PyInt_Type)) {
812 if (PyObject_TypeCheck(val, &PyInt_Type)) {
815 d = PyInt_AS_LONG(val);
813 d = PyInt_AS_LONG(val);
816 } else if (val->ob_type == &PyLong_Type) {
814 } else if (val->ob_type == &PyLong_Type) {
817 d = PyLong_AsLong(val);
815 d = PyLong_AsLong(val);
818 } else if (val == Py_False) {
816 } else if (val == Py_False) {
819 d = 0;
817 d = 0;
820 } else if (val == Py_True) {
818 } else if (val == Py_True) {
821 d = 1;
819 d = 1;
822 } else {
820 } else {
823 ok = false;
821 ok = false;
824 }
822 }
825 } else {
823 } else {
826 ok = false;
824 ok = false;
827 }
825 }
828 return d;
826 return d;
829 }
827 }
830
828
831 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
829 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
832 {
830 {
833 QVariant v;
831 QVariant v;
834 bool ok = true;
832 bool ok = true;
835
833
836 if (type==-1) {
834 if (type==-1) {
837 // no special type requested
835 // no special type requested
838 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
836 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
839 type = QVariant::String;
837 type = QVariant::String;
840 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
838 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
841 type = QVariant::Int;
839 type = QVariant::Int;
842 } else if (val->ob_type==&PyLong_Type) {
840 } else if (val->ob_type==&PyLong_Type) {
843 type = QVariant::LongLong;
841 type = QVariant::LongLong;
844 } else if (val->ob_type==&PyFloat_Type) {
842 } else if (val->ob_type==&PyFloat_Type) {
845 type = QVariant::Double;
843 type = QVariant::Double;
846 } else if (val == Py_False || val == Py_True) {
844 } else if (val == Py_False || val == Py_True) {
847 type = QVariant::Bool;
845 type = QVariant::Bool;
848 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
846 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
849 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
847 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
850 // c++ wrapper, check if the class names of the c++ objects match
848 // c++ wrapper, check if the class names of the c++ objects match
851 if (wrap->classInfo()->isCPPWrapper()) {
849 if (wrap->classInfo()->isCPPWrapper()) {
852 if (wrap->classInfo()->metaTypeId()>0) {
850 if (wrap->classInfo()->metaTypeId()>0) {
853 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
851 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
854 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
852 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
855 } else {
853 } else {
856 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
854 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
857 // the pointer here...
855 // the pointer here...
858 // is this worth anything? we loose the knowledge of the cpp object type
856 // is this worth anything? we loose the knowledge of the cpp object type
859 v = qVariantFromValue(wrap->_wrappedPtr);
857 v = qVariantFromValue(wrap->_wrappedPtr);
860 }
858 }
861 } else {
859 } else {
862 // this gives us a QObject pointer
860 // this gives us a QObject pointer
863 QObject* myObject = wrap->_obj;
861 QObject* myObject = wrap->_obj;
864 v = qVariantFromValue(myObject);
862 v = qVariantFromValue(myObject);
865 }
863 }
866 return v;
864 return v;
867 } else if (val->ob_type==&PyDict_Type) {
865 } else if (val->ob_type==&PyDict_Type) {
868 type = QVariant::Map;
866 type = QVariant::Map;
869 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
867 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
870 type = QVariant::List;
868 type = QVariant::List;
871 } else if (val == Py_None) {
869 } else if (val == Py_None) {
872 // none is invalid
870 // none is invalid
873 type = QVariant::Invalid;
871 type = QVariant::Invalid;
874 } else {
872 } else {
875 // this used to be:
873 // this used to be:
876 // type = QVariant::String;
874 // type = QVariant::String;
877 // but now we want to transport the Python Objects directly:
875 // but now we want to transport the Python Objects directly:
878 PythonQtObjectPtr o(val);
876 PythonQtObjectPtr o(val);
879 v = qVariantFromValue(o);
877 v = qVariantFromValue(o);
880 return v;
878 return v;
881 }
879 }
882 }
880 }
883 // special type request:
881 // special type request:
884 switch (type) {
882 switch (type) {
885 case QVariant::Invalid:
883 case QVariant::Invalid:
886 return v;
884 return v;
887 break;
885 break;
888 case QVariant::Int:
886 case QVariant::Int:
889 {
887 {
890 int d = PyObjGetInt(val, false, ok);
888 int d = PyObjGetInt(val, false, ok);
891 if (ok) return QVariant(d);
889 if (ok) return QVariant(d);
892 }
890 }
893 break;
891 break;
894 case QVariant::UInt:
892 case QVariant::UInt:
895 {
893 {
896 int d = PyObjGetInt(val, false,ok);
894 int d = PyObjGetInt(val, false,ok);
897 if (ok) v = QVariant((unsigned int)d);
895 if (ok) v = QVariant((unsigned int)d);
898 }
896 }
899 break;
897 break;
900 case QVariant::Bool:
898 case QVariant::Bool:
901 {
899 {
902 int d = PyObjGetBool(val,false,ok);
900 int d = PyObjGetBool(val,false,ok);
903 if (ok) v = QVariant((bool)(d!=0));
901 if (ok) v = QVariant((bool)(d!=0));
904 }
902 }
905 break;
903 break;
906 case QVariant::Double:
904 case QVariant::Double:
907 {
905 {
908 double d = PyObjGetDouble(val,false,ok);
906 double d = PyObjGetDouble(val,false,ok);
909 if (ok) v = QVariant(d);
907 if (ok) v = QVariant(d);
910 break;
908 break;
911 }
909 }
912 case QMetaType::Float:
910 case QMetaType::Float:
913 {
911 {
914 float d = (float) PyObjGetDouble(val,false,ok);
912 float d = (float) PyObjGetDouble(val,false,ok);
915 if (ok) v = qVariantFromValue(d);
913 if (ok) v = qVariantFromValue(d);
916 break;
914 break;
917 }
915 }
918 case QMetaType::Long:
916 case QMetaType::Long:
919 {
917 {
920 long d = (long) PyObjGetLongLong(val,false,ok);
918 long d = (long) PyObjGetLongLong(val,false,ok);
921 if (ok) v = qVariantFromValue(d);
919 if (ok) v = qVariantFromValue(d);
922 break;
920 break;
923 }
921 }
924 case QMetaType::ULong:
922 case QMetaType::ULong:
925 {
923 {
926 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
924 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
927 if (ok) v = qVariantFromValue(d);
925 if (ok) v = qVariantFromValue(d);
928 break;
926 break;
929 }
927 }
930 case QMetaType::LongLong:
928 case QMetaType::LongLong:
931 {
929 {
932 qint64 d = PyObjGetLongLong(val, false, ok);
930 qint64 d = PyObjGetLongLong(val, false, ok);
933 if (ok) v = qVariantFromValue(d);
931 if (ok) v = qVariantFromValue(d);
934 }
932 }
935 break;
933 break;
936 case QMetaType::ULongLong:
934 case QMetaType::ULongLong:
937 {
935 {
938 quint64 d = PyObjGetULongLong(val, false, ok);
936 quint64 d = PyObjGetULongLong(val, false, ok);
939 if (ok) v = qVariantFromValue(d);
937 if (ok) v = qVariantFromValue(d);
940 }
938 }
941 break;
939 break;
942 case QMetaType::Short:
940 case QMetaType::Short:
943 {
941 {
944 short d = (short) PyObjGetInt(val,false,ok);
942 short d = (short) PyObjGetInt(val,false,ok);
945 if (ok) v = qVariantFromValue(d);
943 if (ok) v = qVariantFromValue(d);
946 break;
944 break;
947 }
945 }
948 case QMetaType::UShort:
946 case QMetaType::UShort:
949 {
947 {
950 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
948 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
951 if (ok) v = qVariantFromValue(d);
949 if (ok) v = qVariantFromValue(d);
952 break;
950 break;
953 }
951 }
954 case QMetaType::Char:
952 case QMetaType::Char:
955 {
953 {
956 char d = (char) PyObjGetInt(val,false,ok);
954 char d = (char) PyObjGetInt(val,false,ok);
957 if (ok) v = qVariantFromValue(d);
955 if (ok) v = qVariantFromValue(d);
958 break;
956 break;
959 }
957 }
960 case QMetaType::UChar:
958 case QMetaType::UChar:
961 {
959 {
962 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
960 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
963 if (ok) v = qVariantFromValue(d);
961 if (ok) v = qVariantFromValue(d);
964 break;
962 break;
965 }
963 }
966
964
967 case QVariant::ByteArray:
965 case QVariant::ByteArray:
968 case QVariant::String:
966 case QVariant::String:
969 {
967 {
970 bool ok;
968 bool ok;
971 v = QVariant(PyObjGetString(val, false, ok));
969 v = QVariant(PyObjGetString(val, false, ok));
972 }
970 }
973 break;
971 break;
974
972
975 // these are important for MeVisLab
973 // these are important for MeVisLab
976 case QVariant::Map:
974 case QVariant::Map:
977 {
975 {
978 if (PyMapping_Check(val)) {
976 if (PyMapping_Check(val)) {
979 QMap<QString,QVariant> map;
977 QMap<QString,QVariant> map;
980 PyObject* items = PyMapping_Items(val);
978 PyObject* items = PyMapping_Items(val);
981 if (items) {
979 if (items) {
982 int count = PyList_Size(items);
980 int count = PyList_Size(items);
983 PyObject* value;
981 PyObject* value;
984 PyObject* key;
982 PyObject* key;
985 PyObject* tuple;
983 PyObject* tuple;
986 for (int i = 0;i<count;i++) {
984 for (int i = 0;i<count;i++) {
987 tuple = PyList_GetItem(items,i);
985 tuple = PyList_GetItem(items,i);
988 key = PyTuple_GetItem(tuple, 0);
986 key = PyTuple_GetItem(tuple, 0);
989 value = PyTuple_GetItem(tuple, 1);
987 value = PyTuple_GetItem(tuple, 1);
990 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
988 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
991 }
989 }
992 Py_DECREF(items);
990 Py_DECREF(items);
993 v = map;
991 v = map;
994 }
992 }
995 }
993 }
996 }
994 }
997 break;
995 break;
998 case QVariant::List:
996 case QVariant::List:
999 if (PySequence_Check(val)) {
997 if (PySequence_Check(val)) {
1000 QVariantList list;
998 QVariantList list;
1001 int count = PySequence_Size(val);
999 int count = PySequence_Size(val);
1002 PyObject* value;
1000 PyObject* value;
1003 for (int i = 0;i<count;i++) {
1001 for (int i = 0;i<count;i++) {
1004 value = PySequence_GetItem(val,i);
1002 value = PySequence_GetItem(val,i);
1005 list.append(PyObjToQVariant(value, -1));
1003 list.append(PyObjToQVariant(value, -1));
1006 }
1004 }
1007 v = list;
1005 v = list;
1008 }
1006 }
1009 break;
1007 break;
1010 case QVariant::StringList:
1008 case QVariant::StringList:
1011 {
1009 {
1012 bool ok;
1010 bool ok;
1013 QStringList l = PyObjToStringList(val, false, ok);
1011 QStringList l = PyObjToStringList(val, false, ok);
1014 if (ok) {
1012 if (ok) {
1015 v = l;
1013 v = l;
1016 }
1014 }
1017 }
1015 }
1018 break;
1016 break;
1019
1017
1020 default:
1018 default:
1021 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1019 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1022 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1020 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1023 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1021 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1024 // construct a new variant from the C++ object if it has the same meta type
1022 // construct a new variant from the C++ object if it has the same meta type
1025 v = QVariant(type, wrap->_wrappedPtr);
1023 v = QVariant(type, wrap->_wrappedPtr);
1026 } else {
1024 } else {
1027 v = QVariant();
1025 v = QVariant();
1028 }
1026 }
1029 } else {
1027 } else {
1030 v = QVariant();
1028 v = QVariant();
1031 }
1029 }
1032 }
1030 }
1033 return v;
1031 return v;
1034 }
1032 }
1035
1033
1036 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1034 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1037 {
1035 {
1038 if (str.isNull()) {
1036 if (str.isNull()) {
1039 return PyString_FromString("");
1037 return PyString_FromString("");
1040 } else {
1038 } else {
1041 #ifdef WIN32
1042 // return PyString_FromString(str.toLatin1().data());
1043 return PyUnicode_FromUnicode(str.utf16(), str.length());
1044 #else
1045 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1039 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1046 #endif
1047 }
1040 }
1048 }
1041 }
1049
1042
1050 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1043 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1051 {
1044 {
1052 PyObject* result = PyTuple_New(list.count());
1045 PyObject* result = PyTuple_New(list.count());
1053 int i = 0;
1046 int i = 0;
1054 QString str;
1047 QString str;
1055 foreach (str, list) {
1048 foreach (str, list) {
1056 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1049 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1057 i++;
1050 i++;
1058 }
1051 }
1059 // why is the error state bad after this?
1052 // why is the error state bad after this?
1060 PyErr_Clear();
1053 PyErr_Clear();
1061 return result;
1054 return result;
1062 }
1055 }
1063
1056
1064 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1057 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1065 {
1058 {
1066 PyObject* result = PyList_New(list.count());
1059 PyObject* result = PyList_New(list.count());
1067 int i = 0;
1060 int i = 0;
1068 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1061 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1069 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1062 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1070 i++;
1063 i++;
1071 }
1064 }
1072 return result;
1065 return result;
1073 }
1066 }
1074
1067
1075 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1068 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1076 {
1069 {
1077 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1070 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1078 }
1071 }
1079
1072
1080 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1073 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1081 PyObject* result = PyDict_New();
1074 PyObject* result = PyDict_New();
1082 QVariantMap::const_iterator t = m.constBegin();
1075 QVariantMap::const_iterator t = m.constBegin();
1083 PyObject* key;
1076 PyObject* key;
1084 PyObject* val;
1077 PyObject* val;
1085 for (;t!=m.end();t++) {
1078 for (;t!=m.end();t++) {
1086 key = QStringToPyObject(t.key());
1079 key = QStringToPyObject(t.key());
1087 val = QVariantToPyObject(t.value());
1080 val = QVariantToPyObject(t.value());
1088 PyDict_SetItem(result, key, val);
1081 PyDict_SetItem(result, key, val);
1089 Py_DECREF(key);
1082 Py_DECREF(key);
1090 Py_DECREF(val);
1083 Py_DECREF(val);
1091 }
1084 }
1092 return result;
1085 return result;
1093 }
1086 }
1094
1087
1095 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1088 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1096 PyObject* result = PyTuple_New(l.count());
1089 PyObject* result = PyTuple_New(l.count());
1097 int i = 0;
1090 int i = 0;
1098 QVariant v;
1091 QVariant v;
1099 foreach (v, l) {
1092 foreach (v, l) {
1100 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1093 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1101 i++;
1094 i++;
1102 }
1095 }
1103 // why is the error state bad after this?
1096 // why is the error state bad after this?
1104 PyErr_Clear();
1097 PyErr_Clear();
1105 return result;
1098 return result;
1106 }
1099 }
1107
1100
1108 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1101 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1109 {
1102 {
1110 PyObject* result = PyTuple_New(list->count());
1103 PyObject* result = PyTuple_New(list->count());
1111 int i = 0;
1104 int i = 0;
1112 foreach (void* value, *list) {
1105 foreach (void* value, *list) {
1113 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1106 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1114 i++;
1107 i++;
1115 }
1108 }
1116 return result;
1109 return result;
1117 }
1110 }
1118
1111
1119 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1112 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1120 {
1113 {
1121 bool result = false;
1114 bool result = false;
1122 if (PySequence_Check(obj)) {
1115 if (PySequence_Check(obj)) {
1123 result = true;
1116 result = true;
1124 int count = PySequence_Size(obj);
1117 int count = PySequence_Size(obj);
1125 PyObject* value;
1118 PyObject* value;
1126 for (int i = 0;i<count;i++) {
1119 for (int i = 0;i<count;i++) {
1127 value = PySequence_GetItem(obj,i);
1120 value = PySequence_GetItem(obj,i);
1128 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1121 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1129 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1122 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1130 bool ok;
1123 bool ok;
1131 void* object = castWrapperTo(wrap, type, ok);
1124 void* object = castWrapperTo(wrap, type, ok);
1132 if (ok) {
1125 if (ok) {
1133 list->append(object);
1126 list->append(object);
1134 } else {
1127 } else {
1135 result = false;
1128 result = false;
1136 break;
1129 break;
1137 }
1130 }
1138 }
1131 }
1139 }
1132 }
1140 }
1133 }
1141 return result;
1134 return result;
1142 }
1135 }
1143
1136
1144 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1137 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1145 {
1138 {
1146 int idx = typeName.indexOf("<");
1139 int idx = typeName.indexOf("<");
1147 if (idx>0) {
1140 if (idx>0) {
1148 int idx2 = typeName.indexOf(">");
1141 int idx2 = typeName.indexOf(">");
1149 if (idx2>0) {
1142 if (idx2>0) {
1150 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1143 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1151 return QMetaType::type(innerType.constData());
1144 return QMetaType::type(innerType.constData());
1152 }
1145 }
1153 }
1146 }
1154 return QMetaType::Void;
1147 return QMetaType::Void;
1155 }
1148 }
1156
1149
1157
1150
1158 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1151 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1159 QString r;
1152 QString r;
1160 switch (type) {
1153 switch (type) {
1161 case QVariant::Size: {
1154 case QVariant::Size: {
1162 const QSize* s = static_cast<const QSize*>(data);
1155 const QSize* s = static_cast<const QSize*>(data);
1163 r = QString::number(s->width()) + ", " + QString::number(s->height());
1156 r = QString::number(s->width()) + ", " + QString::number(s->height());
1164 }
1157 }
1165 break;
1158 break;
1166 case QVariant::SizeF: {
1159 case QVariant::SizeF: {
1167 const QSizeF* s = static_cast<const QSizeF*>(data);
1160 const QSizeF* s = static_cast<const QSizeF*>(data);
1168 r = QString::number(s->width()) + ", " + QString::number(s->height());
1161 r = QString::number(s->width()) + ", " + QString::number(s->height());
1169 }
1162 }
1170 break;
1163 break;
1171 case QVariant::Point: {
1164 case QVariant::Point: {
1172 const QPoint* s = static_cast<const QPoint*>(data);
1165 const QPoint* s = static_cast<const QPoint*>(data);
1173 r = QString::number(s->x()) + ", " + QString::number(s->y());
1166 r = QString::number(s->x()) + ", " + QString::number(s->y());
1174 }
1167 }
1175 break;
1168 break;
1176 case QVariant::PointF: {
1169 case QVariant::PointF: {
1177 const QPointF* s = static_cast<const QPointF*>(data);
1170 const QPointF* s = static_cast<const QPointF*>(data);
1178 r = QString::number(s->x()) + ", " + QString::number(s->y());
1171 r = QString::number(s->x()) + ", " + QString::number(s->y());
1179 }
1172 }
1180 break;
1173 break;
1181 case QVariant::Rect: {
1174 case QVariant::Rect: {
1182 const QRect* s = static_cast<const QRect*>(data);
1175 const QRect* s = static_cast<const QRect*>(data);
1183 r = QString::number(s->x()) + ", " + QString::number(s->y());
1176 r = QString::number(s->x()) + ", " + QString::number(s->y());
1184 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1177 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1185 }
1178 }
1186 break;
1179 break;
1187 case QVariant::RectF: {
1180 case QVariant::RectF: {
1188 const QRectF* s = static_cast<const QRectF*>(data);
1181 const QRectF* s = static_cast<const QRectF*>(data);
1189 r = QString::number(s->x()) + ", " + QString::number(s->y());
1182 r = QString::number(s->x()) + ", " + QString::number(s->y());
1190 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1183 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1191 }
1184 }
1192 break;
1185 break;
1193 case QVariant::Date: {
1186 case QVariant::Date: {
1194 const QDate* s = static_cast<const QDate*>(data);
1187 const QDate* s = static_cast<const QDate*>(data);
1195 r = s->toString(Qt::ISODate);
1188 r = s->toString(Qt::ISODate);
1196 }
1189 }
1197 break;
1190 break;
1198 case QVariant::DateTime: {
1191 case QVariant::DateTime: {
1199 const QDateTime* s = static_cast<const QDateTime*>(data);
1192 const QDateTime* s = static_cast<const QDateTime*>(data);
1200 r = s->toString(Qt::ISODate);
1193 r = s->toString(Qt::ISODate);
1201 }
1194 }
1202 break;
1195 break;
1203 case QVariant::Time: {
1196 case QVariant::Time: {
1204 const QTime* s = static_cast<const QTime*>(data);
1197 const QTime* s = static_cast<const QTime*>(data);
1205 r = s->toString(Qt::ISODate);
1198 r = s->toString(Qt::ISODate);
1206 }
1199 }
1207 break;
1200 break;
1208 case QVariant::Pixmap:
1201 case QVariant::Pixmap:
1209 {
1202 {
1210 const QPixmap* s = static_cast<const QPixmap*>(data);
1203 const QPixmap* s = static_cast<const QPixmap*>(data);
1211 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1204 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1212 }
1205 }
1213 break;
1206 break;
1214 case QVariant::Image:
1207 case QVariant::Image:
1215 {
1208 {
1216 const QImage* s = static_cast<const QImage*>(data);
1209 const QImage* s = static_cast<const QImage*>(data);
1217 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1210 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1218 }
1211 }
1219 break;
1212 break;
1220 case QVariant::Url:
1213 case QVariant::Url:
1221 {
1214 {
1222 const QUrl* s = static_cast<const QUrl*>(data);
1215 const QUrl* s = static_cast<const QUrl*>(data);
1223 r = s->toString();
1216 r = s->toString();
1224 }
1217 }
1225 break;
1218 break;
1226 //TODO: add more printing for other variant types
1219 //TODO: add more printing for other variant types
1227 default:
1220 default:
1228 // this creates a copy, but that should not be expensive for typical simple variants
1221 // this creates a copy, but that should not be expensive for typical simple variants
1229 // (but we do not want to do this for our won user types!
1222 // (but we do not want to do this for our won user types!
1230 if (type>0 && type < (int)QVariant::UserType) {
1223 if (type>0 && type < (int)QVariant::UserType) {
1231 QVariant v(type, data);
1224 QVariant v(type, data);
1232 r = v.toString();
1225 r = v.toString();
1233 }
1226 }
1234 }
1227 }
1235 return r;
1228 return r;
1236 }
1229 }
@@ -1,822 +1,822
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtImporter.h
35 // \file PythonQtImporter.h
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51 #include <QFile>
51 #include <QFile>
52 #include <QFileInfo>
52 #include <QFileInfo>
53
53
54 #define IS_SOURCE 0x0
54 #define IS_SOURCE 0x0
55 #define IS_BYTECODE 0x1
55 #define IS_BYTECODE 0x1
56 #define IS_PACKAGE 0x2
56 #define IS_PACKAGE 0x2
57
57
58 struct st_mlab_searchorder {
58 struct st_mlab_searchorder {
59 char suffix[14];
59 char suffix[14];
60 int type;
60 int type;
61 };
61 };
62
62
63 /* mlab_searchorder defines how we search for a module in the Zip
63 /* mlab_searchorder defines how we search for a module in the Zip
64 archive: we first search for a package __init__, then for
64 archive: we first search for a package __init__, then for
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
66 are swapped by initmlabimport() if we run in optimized mode. Also,
66 are swapped by initmlabimport() if we run in optimized mode. Also,
67 '/' is replaced by SEP there. */
67 '/' is replaced by SEP there. */
68 struct st_mlab_searchorder mlab_searchorder[] = {
68 struct st_mlab_searchorder mlab_searchorder[] = {
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
72 {".pyc", IS_BYTECODE},
72 {".pyc", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
74 {".py", IS_SOURCE},
74 {".py", IS_SOURCE},
75 {"", 0}
75 {"", 0}
76 };
76 };
77
77
78 extern PyTypeObject PythonQtImporter_Type;
78 extern PyTypeObject PythonQtImporter_Type;
79 PyObject *PythonQtImportError;
79 PyObject *PythonQtImportError;
80
80
81 QString PythonQtImport::getSubName(const QString& str)
81 QString PythonQtImport::getSubName(const QString& str)
82 {
82 {
83 int idx = str.lastIndexOf('.');
83 int idx = str.lastIndexOf('.');
84 if (idx!=-1) {
84 if (idx!=-1) {
85 return str.mid(idx+1);
85 return str.mid(idx+1);
86 } else {
86 } else {
87 return str;
87 return str;
88 }
88 }
89 }
89 }
90
90
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
92 {
92 {
93 ModuleInfo info;
93 ModuleInfo info;
94 QString subname;
94 QString subname;
95 struct st_mlab_searchorder *zso;
95 struct st_mlab_searchorder *zso;
96
96
97 subname = getSubName(fullname);
97 subname = getSubName(fullname);
98 QString path = *self->_path + "/" + subname;
98 QString path = *self->_path + "/" + subname;
99
99
100 QString test;
100 QString test;
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
102 test = path + zso->suffix;
102 test = path + zso->suffix;
103 if (PythonQt::importInterface()->exists(test)) {
103 if (PythonQt::importInterface()->exists(test)) {
104 info.fullPath = test;
104 info.fullPath = test;
105 info.moduleName = subname;
105 info.moduleName = subname;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
107 return info;
107 return info;
108 }
108 }
109 }
109 }
110 // test if it is a shared library
110 // test if it is a shared library
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
111 foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
112 test = path+suffix;
112 test = path+suffix;
113 if (PythonQt::importInterface()->exists(test)) {
113 if (PythonQt::importInterface()->exists(test)) {
114 info.fullPath = test;
114 info.fullPath = test;
115 info.moduleName = subname;
115 info.moduleName = subname;
116 info.type = MI_SHAREDLIBRARY;
116 info.type = MI_SHAREDLIBRARY;
117 return info;
117 return info;
118 }
118 }
119 }
119 }
120 return info;
120 return info;
121 }
121 }
122
122
123
123
124 /* PythonQtImporter.__init__
124 /* PythonQtImporter.__init__
125 Just store the path argument (or reject if it is in the ignorePaths list
125 Just store the path argument (or reject if it is in the ignorePaths list
126 */
126 */
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
128 {
128 {
129 self->_path = NULL;
129 self->_path = NULL;
130
130
131 const char* cpath;
131 const char* cpath;
132 if (!PyArg_ParseTuple(args, "s",
132 if (!PyArg_ParseTuple(args, "s",
133 &cpath))
133 &cpath))
134 return -1;
134 return -1;
135
135
136 QString path(cpath);
136 QString path(cpath);
137 if (PythonQt::importInterface()->exists(path)) {
137 if (PythonQt::importInterface()->exists(path)) {
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
139 foreach(QString ignorePath, ignorePaths) {
139 foreach(QString ignorePath, ignorePaths) {
140 if (path.startsWith(ignorePath)) {
140 if (path.startsWith(ignorePath)) {
141 PyErr_SetString(PythonQtImportError,
141 PyErr_SetString(PythonQtImportError,
142 "path ignored");
142 "path ignored");
143 return -1;
143 return -1;
144 }
144 }
145 }
145 }
146
146
147 self->_path = new QString(path);
147 self->_path = new QString(path);
148 return 0;
148 return 0;
149 } else {
149 } else {
150 PyErr_SetString(PythonQtImportError,
150 PyErr_SetString(PythonQtImportError,
151 "path does not exist error");
151 "path does not exist error");
152 return -1;
152 return -1;
153 }
153 }
154 }
154 }
155
155
156 void
156 void
157 PythonQtImporter_dealloc(PythonQtImporter *self)
157 PythonQtImporter_dealloc(PythonQtImporter *self)
158 {
158 {
159 // free the stored path
159 // free the stored path
160 if (self->_path) delete self->_path;
160 if (self->_path) delete self->_path;
161 // free ourself
161 // free ourself
162 self->ob_type->tp_free((PyObject *)self);
162 self->ob_type->tp_free((PyObject *)self);
163 }
163 }
164
164
165
165
166 /* Check whether we can satisfy the import of the module named by
166 /* Check whether we can satisfy the import of the module named by
167 'fullname'. Return self if we can, None if we can't. */
167 'fullname'. Return self if we can, None if we can't. */
168 PyObject *
168 PyObject *
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
170 {
170 {
171 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PythonQtImporter *self = (PythonQtImporter *)obj;
172 PyObject *path = NULL;
172 PyObject *path = NULL;
173 char *fullname;
173 char *fullname;
174
174
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
176 &fullname, &path))
176 &fullname, &path))
177 return NULL;
177 return NULL;
178
178
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
180
180
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
183 Py_INCREF(self);
183 Py_INCREF(self);
184 return (PyObject *)self;
184 return (PyObject *)self;
185 } else {
185 } else {
186 Py_INCREF(Py_None);
186 Py_INCREF(Py_None);
187 return Py_None;
187 return Py_None;
188 }
188 }
189 }
189 }
190
190
191 /* Load and return the module named by 'fullname'. */
191 /* Load and return the module named by 'fullname'. */
192 PyObject *
192 PyObject *
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
194 {
194 {
195 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PythonQtImporter *self = (PythonQtImporter *)obj;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
197 char *fullname;
197 char *fullname;
198
198
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
200 &fullname))
200 &fullname))
201 return NULL;
201 return NULL;
202
202
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
205 return NULL;
205 return NULL;
206 }
206 }
207
207
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
209 QString fullPath;
209 QString fullPath;
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
211 if (code == NULL) {
211 if (code == NULL) {
212 return NULL;
212 return NULL;
213 }
213 }
214
214
215 mod = PyImport_AddModule(fullname);
215 mod = PyImport_AddModule(fullname);
216 if (mod == NULL) {
216 if (mod == NULL) {
217 Py_DECREF(code);
217 Py_DECREF(code);
218 return NULL;
218 return NULL;
219 }
219 }
220 dict = PyModule_GetDict(mod);
220 dict = PyModule_GetDict(mod);
221
221
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
223 Py_DECREF(code);
223 Py_DECREF(code);
224 Py_DECREF(mod);
224 Py_DECREF(mod);
225 return NULL;
225 return NULL;
226 }
226 }
227
227
228 if (info.type == PythonQtImport::MI_PACKAGE) {
228 if (info.type == PythonQtImport::MI_PACKAGE) {
229 PyObject *pkgpath, *fullpath;
229 PyObject *pkgpath, *fullpath;
230 QString subname = info.moduleName;
230 QString subname = info.moduleName;
231 int err;
231 int err;
232
232
233 fullpath = PyString_FromFormat("%s%c%s",
233 fullpath = PyString_FromFormat("%s%c%s",
234 self->_path->toLatin1().constData(),
234 self->_path->toLatin1().constData(),
235 SEP,
235 SEP,
236 subname.toLatin1().constData());
236 subname.toLatin1().constData());
237 if (fullpath == NULL) {
237 if (fullpath == NULL) {
238 Py_DECREF(code);
238 Py_DECREF(code);
239 Py_DECREF(mod);
239 Py_DECREF(mod);
240 return NULL;
240 return NULL;
241 }
241 }
242
242
243 pkgpath = Py_BuildValue("[O]", fullpath);
243 pkgpath = Py_BuildValue("[O]", fullpath);
244 Py_DECREF(fullpath);
244 Py_DECREF(fullpath);
245 if (pkgpath == NULL) {
245 if (pkgpath == NULL) {
246 Py_DECREF(code);
246 Py_DECREF(code);
247 Py_DECREF(mod);
247 Py_DECREF(mod);
248 return NULL;
248 return NULL;
249 }
249 }
250 err = PyDict_SetItemString(dict, "__path__", pkgpath);
250 err = PyDict_SetItemString(dict, "__path__", pkgpath);
251 Py_DECREF(pkgpath);
251 Py_DECREF(pkgpath);
252 if (err != 0) {
252 if (err != 0) {
253 Py_DECREF(code);
253 Py_DECREF(code);
254 Py_DECREF(mod);
254 Py_DECREF(mod);
255 return NULL;
255 return NULL;
256 }
256 }
257 }
257 }
258 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
258 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
259 Py_DECREF(code);
259 Py_DECREF(code);
260 if (Py_VerboseFlag) {
260 if (Py_VerboseFlag) {
261 PySys_WriteStderr("import %s # loaded from %s\n",
261 PySys_WriteStderr("import %s # loaded from %s\n",
262 fullname, fullPath.toLatin1().constData());
262 fullname, fullPath.toLatin1().constData());
263 }
263 }
264 } else {
264 } else {
265 PythonQtObjectPtr imp;
265 PythonQtObjectPtr imp;
266 imp.setNewRef(PyImport_ImportModule("imp"));
266 imp.setNewRef(PyImport_ImportModule("imp"));
267
267
268 // Create a PyList with the current path as its single element,
268 // Create a PyList with the current path as its single element,
269 // which is required for find_module (it won't accept a tuple...)
269 // which is required for find_module (it won't accept a tuple...)
270 PythonQtObjectPtr pathList;
270 PythonQtObjectPtr pathList;
271 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
271 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
272
272
273 QVariantList args;
273 QVariantList args;
274 // Pass the module name without the package prefix
274 // Pass the module name without the package prefix
275 args.append(info.moduleName);
275 args.append(info.moduleName);
276 // And the path where we know that the shared library is
276 // And the path where we know that the shared library is
277 args.append(QVariant::fromValue(pathList));
277 args.append(QVariant::fromValue(pathList));
278 QVariant result = imp.call("find_module", args);
278 QVariant result = imp.call("find_module", args);
279 if (result.isValid()) {
279 if (result.isValid()) {
280 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
280 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
281 QVariantList list = result.toList();
281 QVariantList list = result.toList();
282 if (list.count()==3) {
282 if (list.count()==3) {
283 // We prepend the full module name (including package prefix)
283 // We prepend the full module name (including package prefix)
284 list.prepend(fullname);
284 list.prepend(fullname);
285 #ifdef __linux
285 #ifdef __linux
286 #ifdef _DEBUG
286 #ifdef _DEBUG
287 // imp_find_module() does not respect the debug suffix '_d' on Linux,
287 // imp_find_module() does not respect the debug suffix '_d' on Linux,
288 // so it does not return the correct file path and we correct it now
288 // so it does not return the correct file path and we correct it now
289 // find_module opened a file to the release library, but that file handle is
289 // find_module opened a file to the release library, but that file handle is
290 // ignored on Linux and Windows, maybe on MacOS also.
290 // ignored on Linux and Windows, maybe on MacOS also.
291 list[2] = info.fullPath;
291 list[2] = info.fullPath;
292 #endif
292 #endif
293 #endif
293 #endif
294 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
294 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
295 PythonQtObjectPtr module = imp.call("load_module", list);
295 PythonQtObjectPtr module = imp.call("load_module", list);
296 mod = module.object();
296 mod = module.object();
297 if (mod) {
297 if (mod) {
298 Py_INCREF(mod);
298 Py_INCREF(mod);
299 }
299 }
300
300
301 // Finally, we need to close the file again, which find_module opened for us
301 // Finally, we need to close the file again, which find_module opened for us
302 PythonQtObjectPtr file = list.at(1);
302 PythonQtObjectPtr file = list.at(1);
303 file.call("close");
303 file.call("close");
304 }
304 }
305 }
305 }
306 }
306 }
307 return mod;
307 return mod;
308 }
308 }
309
309
310
310
311 PyObject *
311 PyObject *
312 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
312 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
313 {
313 {
314 // EXTRA, NOT YET IMPLEMENTED
314 // EXTRA, NOT YET IMPLEMENTED
315 return NULL;
315 return NULL;
316 }
316 }
317
317
318 PyObject *
318 PyObject *
319 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
319 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
320 {
320 {
321 PythonQtImporter *self = (PythonQtImporter *)obj;
321 PythonQtImporter *self = (PythonQtImporter *)obj;
322 char *fullname;
322 char *fullname;
323
323
324 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
324 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
325 return NULL;
325 return NULL;
326
326
327 QString notused;
327 QString notused;
328 return PythonQtImport::getModuleCode(self, fullname, notused);
328 return PythonQtImport::getModuleCode(self, fullname, notused);
329 }
329 }
330
330
331 PyObject *
331 PyObject *
332 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
332 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
333 {
333 {
334 // EXTRA, NOT YET IMPLEMENTED
334 // EXTRA, NOT YET IMPLEMENTED
335 return NULL;
335 return NULL;
336 }
336 }
337
337
338 PyDoc_STRVAR(doc_find_module,
338 PyDoc_STRVAR(doc_find_module,
339 "find_module(fullname, path=None) -> self or None.\n\
339 "find_module(fullname, path=None) -> self or None.\n\
340 \n\
340 \n\
341 Search for a module specified by 'fullname'. 'fullname' must be the\n\
341 Search for a module specified by 'fullname'. 'fullname' must be the\n\
342 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
342 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
343 instance itself if the module was found, or None if it wasn't.\n\
343 instance itself if the module was found, or None if it wasn't.\n\
344 The optional 'path' argument is ignored -- it's there for compatibility\n\
344 The optional 'path' argument is ignored -- it's there for compatibility\n\
345 with the importer protocol.");
345 with the importer protocol.");
346
346
347 PyDoc_STRVAR(doc_load_module,
347 PyDoc_STRVAR(doc_load_module,
348 "load_module(fullname) -> module.\n\
348 "load_module(fullname) -> module.\n\
349 \n\
349 \n\
350 Load the module specified by 'fullname'. 'fullname' must be the\n\
350 Load the module specified by 'fullname'. 'fullname' must be the\n\
351 fully qualified (dotted) module name. It returns the imported\n\
351 fully qualified (dotted) module name. It returns the imported\n\
352 module, or raises PythonQtImportError if it wasn't found.");
352 module, or raises PythonQtImportError if it wasn't found.");
353
353
354 PyDoc_STRVAR(doc_get_data,
354 PyDoc_STRVAR(doc_get_data,
355 "get_data(pathname) -> string with file data.\n\
355 "get_data(pathname) -> string with file data.\n\
356 \n\
356 \n\
357 Return the data associated with 'pathname'. Raise IOError if\n\
357 Return the data associated with 'pathname'. Raise IOError if\n\
358 the file wasn't found.");
358 the file wasn't found.");
359
359
360 PyDoc_STRVAR(doc_get_code,
360 PyDoc_STRVAR(doc_get_code,
361 "get_code(fullname) -> code object.\n\
361 "get_code(fullname) -> code object.\n\
362 \n\
362 \n\
363 Return the code object for the specified module. Raise PythonQtImportError\n\
363 Return the code object for the specified module. Raise PythonQtImportError\n\
364 is the module couldn't be found.");
364 is the module couldn't be found.");
365
365
366 PyDoc_STRVAR(doc_get_source,
366 PyDoc_STRVAR(doc_get_source,
367 "get_source(fullname) -> source string.\n\
367 "get_source(fullname) -> source string.\n\
368 \n\
368 \n\
369 Return the source code for the specified module. Raise PythonQtImportError\n\
369 Return the source code for the specified module. Raise PythonQtImportError\n\
370 is the module couldn't be found, return None if the archive does\n\
370 is the module couldn't be found, return None if the archive does\n\
371 contain the module, but has no source for it.");
371 contain the module, but has no source for it.");
372
372
373 PyMethodDef PythonQtImporter_methods[] = {
373 PyMethodDef PythonQtImporter_methods[] = {
374 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
374 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
375 doc_find_module},
375 doc_find_module},
376 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
376 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
377 doc_load_module},
377 doc_load_module},
378 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
378 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
379 doc_get_data},
379 doc_get_data},
380 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
380 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
381 doc_get_code},
381 doc_get_code},
382 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
382 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
383 doc_get_source},
383 doc_get_source},
384 {NULL, NULL, 0 , NULL} /* sentinel */
384 {NULL, NULL, 0 , NULL} /* sentinel */
385 };
385 };
386
386
387
387
388 PyDoc_STRVAR(PythonQtImporter_doc,
388 PyDoc_STRVAR(PythonQtImporter_doc,
389 "PythonQtImporter(path) -> PythonQtImporter object\n\
389 "PythonQtImporter(path) -> PythonQtImporter object\n\
390 \n\
390 \n\
391 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
391 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
392 . Every path is accepted.");
392 . Every path is accepted.");
393
393
394 #define DEFERRED_ADDRESS(ADDR) 0
394 #define DEFERRED_ADDRESS(ADDR) 0
395
395
396 PyTypeObject PythonQtImporter_Type = {
396 PyTypeObject PythonQtImporter_Type = {
397 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
397 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
398 0,
398 0,
399 "PythonQtImport.PythonQtImporter",
399 "PythonQtImport.PythonQtImporter",
400 sizeof(PythonQtImporter),
400 sizeof(PythonQtImporter),
401 0, /* tp_itemsize */
401 0, /* tp_itemsize */
402 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
402 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
403 0, /* tp_print */
403 0, /* tp_print */
404 0, /* tp_getattr */
404 0, /* tp_getattr */
405 0, /* tp_setattr */
405 0, /* tp_setattr */
406 0, /* tp_compare */
406 0, /* tp_compare */
407 0, /* tp_repr */
407 0, /* tp_repr */
408 0, /* tp_as_number */
408 0, /* tp_as_number */
409 0, /* tp_as_sequence */
409 0, /* tp_as_sequence */
410 0, /* tp_as_mapping */
410 0, /* tp_as_mapping */
411 0, /* tp_hash */
411 0, /* tp_hash */
412 0, /* tp_call */
412 0, /* tp_call */
413 0, /* tp_str */
413 0, /* tp_str */
414 PyObject_GenericGetAttr, /* tp_getattro */
414 PyObject_GenericGetAttr, /* tp_getattro */
415 0, /* tp_setattro */
415 0, /* tp_setattro */
416 0, /* tp_as_buffer */
416 0, /* tp_as_buffer */
417 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
417 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
418 PythonQtImporter_doc, /* tp_doc */
418 PythonQtImporter_doc, /* tp_doc */
419 0, /* tp_traverse */
419 0, /* tp_traverse */
420 0, /* tp_clear */
420 0, /* tp_clear */
421 0, /* tp_richcompare */
421 0, /* tp_richcompare */
422 0, /* tp_weaklistoffset */
422 0, /* tp_weaklistoffset */
423 0, /* tp_iter */
423 0, /* tp_iter */
424 0, /* tp_iternext */
424 0, /* tp_iternext */
425 PythonQtImporter_methods, /* tp_methods */
425 PythonQtImporter_methods, /* tp_methods */
426 0, /* tp_members */
426 0, /* tp_members */
427 0, /* tp_getset */
427 0, /* tp_getset */
428 0, /* tp_base */
428 0, /* tp_base */
429 0, /* tp_dict */
429 0, /* tp_dict */
430 0, /* tp_descr_get */
430 0, /* tp_descr_get */
431 0, /* tp_descr_set */
431 0, /* tp_descr_set */
432 0, /* tp_dictoffset */
432 0, /* tp_dictoffset */
433 (initproc)PythonQtImporter_init, /* tp_init */
433 (initproc)PythonQtImporter_init, /* tp_init */
434 PyType_GenericAlloc, /* tp_alloc */
434 PyType_GenericAlloc, /* tp_alloc */
435 PyType_GenericNew, /* tp_new */
435 PyType_GenericNew, /* tp_new */
436 PyObject_Del, /* tp_free */
436 PyObject_Del, /* tp_free */
437 };
437 };
438
438
439
439
440 /* Given a buffer, return the long that is represented by the first
440 /* Given a buffer, return the long that is represented by the first
441 4 bytes, encoded as little endian. This partially reimplements
441 4 bytes, encoded as little endian. This partially reimplements
442 marshal.c:r_long() */
442 marshal.c:r_long() */
443 long
443 long
444 PythonQtImport::getLong(unsigned char *buf)
444 PythonQtImport::getLong(unsigned char *buf)
445 {
445 {
446 long x;
446 long x;
447 x = buf[0];
447 x = buf[0];
448 x |= (long)buf[1] << 8;
448 x |= (long)buf[1] << 8;
449 x |= (long)buf[2] << 16;
449 x |= (long)buf[2] << 16;
450 x |= (long)buf[3] << 24;
450 x |= (long)buf[3] << 24;
451 #if SIZEOF_LONG > 4
451 #if SIZEOF_LONG > 4
452 /* Sign extension for 64-bit machines */
452 /* Sign extension for 64-bit machines */
453 x |= -(x & 0x80000000L);
453 x |= -(x & 0x80000000L);
454 #endif
454 #endif
455 return x;
455 return x;
456 }
456 }
457
457
458 FILE *
458 FILE *
459 open_exclusive(const QString& filename)
459 open_exclusive(const QString& filename)
460 {
460 {
461 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
461 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
462 /* Use O_EXCL to avoid a race condition when another process tries to
462 /* Use O_EXCL to avoid a race condition when another process tries to
463 write the same file. When that happens, our open() call fails,
463 write the same file. When that happens, our open() call fails,
464 which is just fine (since it's only a cache).
464 which is just fine (since it's only a cache).
465 XXX If the file exists and is writable but the directory is not
465 XXX If the file exists and is writable but the directory is not
466 writable, the file will never be written. Oh well.
466 writable, the file will never be written. Oh well.
467 */
467 */
468 QFile::remove(filename);
468 QFile::remove(filename);
469
469
470 int fd;
470 int fd;
471 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
471 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
472 #ifdef O_BINARY
472 #ifdef O_BINARY
473 flags |= O_BINARY; /* necessary for Windows */
473 flags |= O_BINARY; /* necessary for Windows */
474 #endif
474 #endif
475 #ifdef WIN32
475 #ifdef WIN32
476 fd = _wopen(filename.ucs2(), flags, 0666);
476 fd = _wopen(filename.ucs2(), flags, 0666);
477 #else
477 #else
478 fd = open(filename.local8Bit(), flags, 0666);
478 fd = open(filename.local8Bit(), flags, 0666);
479 #endif
479 #endif
480 if (fd < 0)
480 if (fd < 0)
481 return NULL;
481 return NULL;
482 return fdopen(fd, "wb");
482 return fdopen(fd, "wb");
483 #else
483 #else
484 /* Best we can do -- on Windows this can't happen anyway */
484 /* Best we can do -- on Windows this can't happen anyway */
485 return fopen(filename.toLocal8Bit().constData(), "wb");
485 return fopen(filename.toLocal8Bit().constData(), "wb");
486 #endif
486 #endif
487 }
487 }
488
488
489
489
490 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
490 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
491 {
491 {
492 FILE *fp;
492 FILE *fp;
493 // we do not want to write Qt resources to disk, do we?
493 // we do not want to write Qt resources to disk, do we?
494 if (filename.startsWith(":")) {
494 if (filename.startsWith(":")) {
495 return;
495 return;
496 }
496 }
497 fp = open_exclusive(filename);
497 fp = open_exclusive(filename);
498 if (fp == NULL) {
498 if (fp == NULL) {
499 if (Py_VerboseFlag)
499 if (Py_VerboseFlag)
500 PySys_WriteStderr(
500 PySys_WriteStderr(
501 "# can't create %s\n", filename.toLatin1().constData());
501 "# can't create %s\n", filename.toLatin1().constData());
502 return;
502 return;
503 }
503 }
504 #if PY_VERSION_HEX < 0x02040000
504 #if PY_VERSION_HEX < 0x02040000
505 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
505 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
506 #else
506 #else
507 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
507 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
508 #endif
508 #endif
509 /* First write a 0 for mtime */
509 /* First write a 0 for mtime */
510 #if PY_VERSION_HEX < 0x02040000
510 #if PY_VERSION_HEX < 0x02040000
511 PyMarshal_WriteLongToFile(0L, fp);
511 PyMarshal_WriteLongToFile(0L, fp);
512 #else
512 #else
513 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
513 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
514 #endif
514 #endif
515 #if PY_VERSION_HEX < 0x02040000
515 #if PY_VERSION_HEX < 0x02040000
516 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
516 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
517 #else
517 #else
518 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
518 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
519 #endif
519 #endif
520 if (ferror(fp)) {
520 if (ferror(fp)) {
521 if (Py_VerboseFlag)
521 if (Py_VerboseFlag)
522 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
522 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
523 /* Don't keep partial file */
523 /* Don't keep partial file */
524 fclose(fp);
524 fclose(fp);
525 QFile::remove(filename);
525 QFile::remove(filename);
526 return;
526 return;
527 }
527 }
528 /* Now write the true mtime */
528 /* Now write the true mtime */
529 fseek(fp, 4L, 0);
529 fseek(fp, 4L, 0);
530 #if PY_VERSION_HEX < 0x02040000
530 #if PY_VERSION_HEX < 0x02040000
531 PyMarshal_WriteLongToFile(mtime, fp);
531 PyMarshal_WriteLongToFile(mtime, fp);
532 #else
532 #else
533 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
533 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
534 #endif
534 #endif
535 fflush(fp);
535 fflush(fp);
536 fclose(fp);
536 fclose(fp);
537 if (Py_VerboseFlag)
537 if (Py_VerboseFlag)
538 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
538 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
539 //#ifdef macintosh
539 //#ifdef macintosh
540 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
540 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
541 //#endif
541 //#endif
542 }
542 }
543
543
544 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
544 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
545 and return the code object. Return None if it the magic word doesn't
545 and return the code object. Return None if it the magic word doesn't
546 match (we do this instead of raising an exception as we fall back
546 match (we do this instead of raising an exception as we fall back
547 to .py if available and we don't want to mask other errors).
547 to .py if available and we don't want to mask other errors).
548 Returns a new reference. */
548 Returns a new reference. */
549 PyObject *
549 PyObject *
550 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
550 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
551 {
551 {
552 PyObject *code;
552 PyObject *code;
553 // ugly cast, but Python API is not const safe
553 // ugly cast, but Python API is not const safe
554 char *buf = (char*) data.constData();
554 char *buf = (char*) data.constData();
555 int size = data.size();
555 int size = data.size();
556
556
557 if (size <= 9) {
557 if (size <= 9) {
558 PySys_WriteStderr("# %s has bad pyc data\n",
558 PySys_WriteStderr("# %s has bad pyc data\n",
559 path.toLatin1().constData());
559 path.toLatin1().constData());
560 Py_INCREF(Py_None);
560 Py_INCREF(Py_None);
561 return Py_None;
561 return Py_None;
562 }
562 }
563
563
564 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
564 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
565 if (Py_VerboseFlag)
565 if (Py_VerboseFlag)
566 PySys_WriteStderr("# %s has bad magic\n",
566 PySys_WriteStderr("# %s has bad magic\n",
567 path.toLatin1().constData());
567 path.toLatin1().constData());
568 Py_INCREF(Py_None);
568 Py_INCREF(Py_None);
569 return Py_None;
569 return Py_None;
570 }
570 }
571
571
572 if (mtime != 0) {
572 if (mtime != 0) {
573 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
573 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
574 if (timeDiff<0) { timeDiff = -timeDiff; }
574 if (timeDiff<0) { timeDiff = -timeDiff; }
575 if (timeDiff > 1) {
575 if (timeDiff > 1) {
576 if (Py_VerboseFlag)
576 if (Py_VerboseFlag)
577 PySys_WriteStderr("# %s has bad mtime\n",
577 PySys_WriteStderr("# %s has bad mtime\n",
578 path.toLatin1().constData());
578 path.toLatin1().constData());
579 Py_INCREF(Py_None);
579 Py_INCREF(Py_None);
580 return Py_None;
580 return Py_None;
581 }
581 }
582 }
582 }
583
583
584 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
584 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
585 if (code == NULL)
585 if (code == NULL)
586 return NULL;
586 return NULL;
587 if (!PyCode_Check(code)) {
587 if (!PyCode_Check(code)) {
588 Py_DECREF(code);
588 Py_DECREF(code);
589 PyErr_Format(PyExc_TypeError,
589 PyErr_Format(PyExc_TypeError,
590 "compiled module %.200s is not a code object",
590 "compiled module %.200s is not a code object",
591 path.toLatin1().constData());
591 path.toLatin1().constData());
592 return NULL;
592 return NULL;
593 }
593 }
594 return code;
594 return code;
595 }
595 }
596
596
597
597
598 /* Given a string buffer containing Python source code, compile it
598 /* Given a string buffer containing Python source code, compile it
599 return and return a code object as a new reference. */
599 return and return a code object as a new reference. */
600 PyObject *
600 PyObject *
601 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
601 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
602 {
602 {
603 PyObject *code;
603 PyObject *code;
604 QByteArray data1 = data;
604 QByteArray data1 = data;
605 // in qt4, data is null terminated
605 // in qt4, data is null terminated
606 // data1.resize(data.size()+1);
606 // data1.resize(data.size()+1);
607 // data1.data()[data.size()-1] = 0;
607 // data1.data()[data.size()-1] = 0;
608 code = Py_CompileString(data.data(), path.toLatin1().constData(),
608 code = Py_CompileString(data.data(), path.toLatin1().constData(),
609 Py_file_input);
609 Py_file_input);
610 return code;
610 return code;
611 }
611 }
612
612
613
613
614 /* Return the code object for the module named by 'fullname' from the
614 /* Return the code object for the module named by 'fullname' from the
615 Zip archive as a new reference. */
615 Zip archive as a new reference. */
616 PyObject *
616 PyObject *
617 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
617 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
618 {
618 {
619 PyObject *code;
619 PyObject *code;
620
620
621 QByteArray qdata;
621 QByteArray qdata;
622 if (!isbytecode) {
622 if (!isbytecode) {
623 // mlabDebugConst("MLABPython", "reading source " << path);
623 // mlabDebugConst("MLABPython", "reading source " << path);
624 bool ok;
624 bool ok;
625 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
625 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
626 if (!ok) {
626 if (!ok) {
627 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
627 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
628 return NULL;
628 return NULL;
629 }
629 }
630 if (qdata == " ") {
630 if (qdata == " ") {
631 qdata.clear();
631 qdata.clear();
632 }
632 }
633 } else {
633 } else {
634 qdata = PythonQt::importInterface()->readFileAsBytes(path);
634 qdata = PythonQt::importInterface()->readFileAsBytes(path);
635 }
635 }
636
636
637 if (isbytecode) {
637 if (isbytecode) {
638 // mlabDebugConst("MLABPython", "reading bytecode " << path);
638 // mlabDebugConst("MLABPython", "reading bytecode " << path);
639 code = unmarshalCode(path, qdata, mtime);
639 code = unmarshalCode(path, qdata, mtime);
640 }
640 }
641 else {
641 else {
642 // mlabDebugConst("MLABPython", "compiling source " << path);
642 // mlabDebugConst("MLABPython", "compiling source " << path);
643 code = compileSource(path, qdata);
643 code = compileSource(path, qdata);
644 if (code) {
644 if (code) {
645 // save a pyc file if possible
645 // save a pyc file if possible
646 QDateTime time;
646 QDateTime time;
647 time = PythonQt::importInterface()->lastModifiedDate(path);
647 time = PythonQt::importInterface()->lastModifiedDate(path);
648 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
648 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
649 }
649 }
650 }
650 }
651 return code;
651 return code;
652 }
652 }
653
653
654 time_t
654 time_t
655 PythonQtImport::getMTimeOfSource(const QString& path)
655 PythonQtImport::getMTimeOfSource(const QString& path)
656 {
656 {
657 time_t mtime = 0;
657 time_t mtime = 0;
658 QString path2 = path;
658 QString path2 = path;
659 path2.truncate(path.length()-1);
659 path2.truncate(path.length()-1);
660
660
661 if (PythonQt::importInterface()->exists(path2)) {
661 if (PythonQt::importInterface()->exists(path2)) {
662 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
662 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
663 if (t.isValid()) {
663 if (t.isValid()) {
664 mtime = t.toTime_t();
664 mtime = t.toTime_t();
665 }
665 }
666 }
666 }
667
667
668 return mtime;
668 return mtime;
669 }
669 }
670
670
671 /* Get the code object associated with the module specified by
671 /* Get the code object associated with the module specified by
672 'fullname'. */
672 'fullname'. */
673 PyObject *
673 PyObject *
674 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
674 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
675 {
675 {
676 QString subname;
676 QString subname;
677 struct st_mlab_searchorder *zso;
677 struct st_mlab_searchorder *zso;
678
678
679 subname = getSubName(fullname);
679 subname = getSubName(fullname);
680 QString path = *self->_path + "/" + subname;
680 QString path = *self->_path + "/" + subname;
681
681
682 QString test;
682 QString test;
683 for (zso = mlab_searchorder; *zso->suffix; zso++) {
683 for (zso = mlab_searchorder; *zso->suffix; zso++) {
684 PyObject *code = NULL;
684 PyObject *code = NULL;
685 test = path + zso->suffix;
685 test = path + zso->suffix;
686
686
687 if (Py_VerboseFlag > 1)
687 if (Py_VerboseFlag > 1)
688 PySys_WriteStderr("# trying %s\n",
688 PySys_WriteStderr("# trying %s\n",
689 test.toLatin1().constData());
689 test.toLatin1().constData());
690 if (PythonQt::importInterface()->exists(test)) {
690 if (PythonQt::importInterface()->exists(test)) {
691 time_t mtime = 0;
691 time_t mtime = 0;
692 int ispackage = zso->type & IS_PACKAGE;
692 int ispackage = zso->type & IS_PACKAGE;
693 int isbytecode = zso->type & IS_BYTECODE;
693 int isbytecode = zso->type & IS_BYTECODE;
694
694
695 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
695 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
696 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
696 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
697 // even if a newer *.py file exists. This is a release optimization where
697 // even if a newer *.py file exists. This is a release optimization where
698 // typically only *.pyc files are delivered without *.py files and reading file
698 // typically only *.pyc files are delivered without *.py files and reading file
699 // modification time is slow.
699 // modification time is slow.
700 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
700 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
701 mtime = getMTimeOfSource(test);
701 mtime = getMTimeOfSource(test);
702 }
702 }
703 code = getCodeFromData(test, isbytecode, ispackage, mtime);
703 code = getCodeFromData(test, isbytecode, ispackage, mtime);
704 if (code == Py_None) {
704 if (code == Py_None) {
705 Py_DECREF(code);
705 Py_DECREF(code);
706 continue;
706 continue;
707 }
707 }
708 if (code != NULL) {
708 if (code != NULL) {
709 modpath = test;
709 modpath = test;
710 }
710 }
711 return code;
711 return code;
712 }
712 }
713 }
713 }
714 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
714 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
715
715
716 return NULL;
716 return NULL;
717 }
717 }
718
718
719 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
719 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
720 {
720 {
721 QString r;
721 QString r;
722 int i = str.lastIndexOf('.');
722 int i = str.lastIndexOf('.');
723 if (i!=-1) {
723 if (i!=-1) {
724 r = str.mid(0,i) + "." + ext;
724 r = str.mid(0,i) + "." + ext;
725 } else {
725 } else {
726 r = str + "." + ext;
726 r = str + "." + ext;
727 }
727 }
728 return r;
728 return r;
729 }
729 }
730
730
731 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
731 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
732 {
732 {
733 PyObject* code;
733 PyObject* code;
734 const static QString pycStr("pyc");
734 const static QString pycStr("pyc");
735 QString pyc = replaceExtension(file, pycStr);
735 QString pyc = replaceExtension(file, pycStr);
736 if (PythonQt::importInterface()->exists(pyc)) {
736 if (PythonQt::importInterface()->exists(pyc)) {
737 time_t mtime = 0;
737 time_t mtime = 0;
738 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
738 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
739 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
739 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
740 // even if a newer *.py file exists. This is a release optimization where
740 // even if a newer *.py file exists. This is a release optimization where
741 // typically only *.pyc files are delivered without *.py files and reading file
741 // typically only *.pyc files are delivered without *.py files and reading file
742 // modification time is slow.
742 // modification time is slow.
743 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
743 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
744 mtime = getMTimeOfSource(pyc);
744 mtime = getMTimeOfSource(pyc);
745 }
745 }
746 code = getCodeFromData(pyc, true, false, mtime);
746 code = getCodeFromData(pyc, true, false, mtime);
747 if (code != Py_None && code != NULL) {
747 if (code != Py_None && code != NULL) {
748 return code;
748 return code;
749 }
749 }
750 if (code) {
750 if (code) {
751 Py_DECREF(code);
751 Py_DECREF(code);
752 }
752 }
753 }
753 }
754 code = getCodeFromData(file,false,false,0);
754 code = getCodeFromData(file,false,false,0);
755 return code;
755 return code;
756 }
756 }
757
757
758 /* Module init */
758 /* Module init */
759
759
760 PyDoc_STRVAR(mlabimport_doc,
760 PyDoc_STRVAR(mlabimport_doc,
761 "Imports python files into PythonQt, completely replaces internal python import");
761 "Imports python files into PythonQt, completely replaces internal python import");
762
762
763 void PythonQtImport::init()
763 void PythonQtImport::init()
764 {
764 {
765 static bool first = true;
765 static bool first = true;
766 if (!first) {
766 if (!first) {
767 return;
767 return;
768 }
768 }
769 first = false;
769 first = false;
770
770
771 PyObject *mod;
771 PyObject *mod;
772
772
773 if (PyType_Ready(&PythonQtImporter_Type) < 0)
773 if (PyType_Ready(&PythonQtImporter_Type) < 0)
774 return;
774 return;
775
775
776 /* Correct directory separator */
776 /* Correct directory separator */
777 mlab_searchorder[0].suffix[0] = SEP;
777 mlab_searchorder[0].suffix[0] = SEP;
778 mlab_searchorder[1].suffix[0] = SEP;
778 mlab_searchorder[1].suffix[0] = SEP;
779 mlab_searchorder[2].suffix[0] = SEP;
779 mlab_searchorder[2].suffix[0] = SEP;
780 if (Py_OptimizeFlag) {
780 if (Py_OptimizeFlag) {
781 /* Reverse *.pyc and *.pyo */
781 /* Reverse *.pyc and *.pyo */
782 struct st_mlab_searchorder tmp;
782 struct st_mlab_searchorder tmp;
783 tmp = mlab_searchorder[0];
783 tmp = mlab_searchorder[0];
784 mlab_searchorder[0] = mlab_searchorder[1];
784 mlab_searchorder[0] = mlab_searchorder[1];
785 mlab_searchorder[1] = tmp;
785 mlab_searchorder[1] = tmp;
786 tmp = mlab_searchorder[3];
786 tmp = mlab_searchorder[3];
787 mlab_searchorder[3] = mlab_searchorder[4];
787 mlab_searchorder[3] = mlab_searchorder[4];
788 mlab_searchorder[4] = tmp;
788 mlab_searchorder[4] = tmp;
789 }
789 }
790
790
791 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
791 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
792 NULL, PYTHON_API_VERSION);
792 NULL, PYTHON_API_VERSION);
793
793
794 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
794 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
795 PyExc_ImportError, NULL);
795 PyExc_ImportError, NULL);
796 if (PythonQtImportError == NULL)
796 if (PythonQtImportError == NULL)
797 return;
797 return;
798
798
799 Py_INCREF(PythonQtImportError);
799 Py_INCREF(PythonQtImportError);
800 if (PyModule_AddObject(mod, "PythonQtImportError",
800 if (PyModule_AddObject(mod, "PythonQtImportError",
801 PythonQtImportError) < 0)
801 PythonQtImportError) < 0)
802 return;
802 return;
803
803
804 Py_INCREF(&PythonQtImporter_Type);
804 Py_INCREF(&PythonQtImporter_Type);
805 if (PyModule_AddObject(mod, "PythonQtImporter",
805 if (PyModule_AddObject(mod, "PythonQtImporter",
806 (PyObject *)&PythonQtImporter_Type) < 0)
806 (PyObject *)&PythonQtImporter_Type) < 0)
807 return;
807 return;
808
808
809 // set our importer into the path_hooks to handle all path on sys.path
809 // set our importer into the path_hooks to handle all path on sys.path
810 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
810 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
811 PyObject* path_hooks = PySys_GetObject("path_hooks");
811 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
812 PyList_Append(path_hooks, classobj);
812 PyList_Append(path_hooks, classobj);
813
813
814 #ifndef WIN32
814 #ifndef WIN32
815 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
815 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
816 PyObject* modules = PyImport_GetModuleDict();
816 PyObject* modules = PyImport_GetModuleDict();
817 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
817 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
818 if (encodingsModule != NULL) {
818 if (encodingsModule != NULL) {
819 PyImport_ReloadModule(encodingsModule);
819 PyImport_ReloadModule(encodingsModule);
820 }
820 }
821 #endif
821 #endif
822 }
822 }
@@ -1,137 +1,138
1 #ifndef _PYTHONQTIMPORTER_
1 #ifndef _PYTHONQTIMPORTER_
2 #define _PYTHONQTIMPORTER_
2 #define _PYTHONQTIMPORTER_
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 PythonQtImporter.h
38 // \file PythonQtImporter.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: stk $
40 // \author Last changed by $Author: stk $
41 // \date 2004-06
41 // \date 2004-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "Python.h"
45 #include "PythonQtPythonInclude.h"
46
46 #include "structmember.h"
47 #include "structmember.h"
47 #include "osdefs.h"
48 #include "osdefs.h"
48 #include "marshal.h"
49 #include "marshal.h"
49 #include "compile.h"
50 #include "compile.h"
50 #include <time.h>
51 #include <time.h>
51
52
52 #include <qobject.h>
53 #include <qobject.h>
53 #include <qstring.h>
54 #include <qstring.h>
54
55
55
56
56 //! defines a python object that stores a Qt slot info
57 //! defines a python object that stores a Qt slot info
57 typedef struct _PythonQtImporter {
58 typedef struct _PythonQtImporter {
58 PyObject_HEAD
59 PyObject_HEAD
59 QString* _path;
60 QString* _path;
60 } PythonQtImporter;
61 } PythonQtImporter;
61
62
62
63
63 //! implements importing of python files into PythonQt
64 //! implements importing of python files into PythonQt
64 /*! also compiles/marshalls/unmarshalls py/pyc files and handles time stamps correctly
65 /*! also compiles/marshalls/unmarshalls py/pyc files and handles time stamps correctly
65 */
66 */
66 class PythonQtImport
67 class PythonQtImport
67 {
68 {
68 public:
69 public:
69
70
70 enum ModuleType {
71 enum ModuleType {
71 MI_NOT_FOUND,
72 MI_NOT_FOUND,
72 MI_MODULE,
73 MI_MODULE,
73 MI_PACKAGE,
74 MI_PACKAGE,
74 MI_SHAREDLIBRARY
75 MI_SHAREDLIBRARY
75 };
76 };
76
77
77 struct ModuleInfo {
78 struct ModuleInfo {
78 ModuleInfo() {
79 ModuleInfo() {
79 type = MI_NOT_FOUND;
80 type = MI_NOT_FOUND;
80 }
81 }
81 QString fullPath; //!< the full path to the found file
82 QString fullPath; //!< the full path to the found file
82 QString moduleName; //!< the module name without the package prefix
83 QString moduleName; //!< the module name without the package prefix
83 ModuleType type;
84 ModuleType type;
84 };
85 };
85
86
86 //! initialize
87 //! initialize
87 static void init();
88 static void init();
88
89
89 //! writes the python code to disk, marshalling and writing the time stamp
90 //! writes the python code to disk, marshalling and writing the time stamp
90 static void writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime);
91 static void writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime);
91
92
92 /*! Given the contents of a .py[co] file in a buffer, unmarshal the data
93 /*! Given the contents of a .py[co] file in a buffer, unmarshal the data
93 and return the code object. Return None if it the magic word doesn't
94 and return the code object. Return None if it the magic word doesn't
94 match (we do this instead of raising an exception as we fall back
95 match (we do this instead of raising an exception as we fall back
95 to .py if available and we don't want to mask other errors).
96 to .py if available and we don't want to mask other errors).
96 Returns a new reference. */
97 Returns a new reference. */
97 static PyObject *unmarshalCode(const QString& path, const QByteArray& data, time_t mtime);
98 static PyObject *unmarshalCode(const QString& path, const QByteArray& data, time_t mtime);
98
99
99 //! Given a string buffer containing Python source code, compile it
100 //! Given a string buffer containing Python source code, compile it
100 //! return and return a code object as a new reference.
101 //! return and return a code object as a new reference.
101 static PyObject *compileSource(const QString& path, const QByteArray& data);
102 static PyObject *compileSource(const QString& path, const QByteArray& data);
102
103
103 //! Return the code object for the module named by 'fullname' from the
104 //! Return the code object for the module named by 'fullname' from the
104 //! Zip archive as a new reference.
105 //! Zip archive as a new reference.
105 static PyObject *getCodeFromData(const QString& path, int isbytecode = 0, int ispackage = 0,
106 static PyObject *getCodeFromData(const QString& path, int isbytecode = 0, int ispackage = 0,
106 time_t mtime = 0);
107 time_t mtime = 0);
107
108
108 //! Get the code object associated with the module specified by
109 //! Get the code object associated with the module specified by
109 //! 'fullname'.
110 //! 'fullname'.
110 static PyObject * getModuleCode(PythonQtImporter *self,
111 static PyObject * getModuleCode(PythonQtImporter *self,
111 const char* fullname, QString& modpath);
112 const char* fullname, QString& modpath);
112
113
113
114
114 //! gets the compiled code for the given *.py file if there is a valid pyc file, otherwise compiles the file and writes the pyc
115 //! gets the compiled code for the given *.py file if there is a valid pyc file, otherwise compiles the file and writes the pyc
115 static PyObject* getCodeFromPyc(const QString& file);
116 static PyObject* getCodeFromPyc(const QString& file);
116
117
117 //! Return if module exists and is a package or a module
118 //! Return if module exists and is a package or a module
118 static ModuleInfo getModuleInfo(PythonQtImporter* self, const QString& fullname);
119 static ModuleInfo getModuleInfo(PythonQtImporter* self, const QString& fullname);
119
120
120 //! get the last name of a dot chain (first.second.last)
121 //! get the last name of a dot chain (first.second.last)
121 static QString getSubName(const QString& str);
122 static QString getSubName(const QString& str);
122
123
123 //! Given a buffer, return the long that is represented by the first
124 //! Given a buffer, return the long that is represented by the first
124 //! 4 bytes, encoded as little endian. This partially reimplements
125 //! 4 bytes, encoded as little endian. This partially reimplements
125 //! marshal.c:r_long()
126 //! marshal.c:r_long()
126 static long getLong(unsigned char *buf);
127 static long getLong(unsigned char *buf);
127
128
128 //! get time stamp of file
129 //! get time stamp of file
129 static time_t getMTimeOfSource(const QString& path);
130 static time_t getMTimeOfSource(const QString& path);
130
131
131 //! replace extension of file
132 //! replace extension of file
132 static QString replaceExtension(const QString& str, const QString& ext);
133 static QString replaceExtension(const QString& str, const QString& ext);
133
134
134 };
135 };
135
136
136 #endif
137 #endif
137
138
@@ -1,100 +1,101
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
1 #ifndef _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_H
2 #define _PYTHONQTINSTANCEWRAPPER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtInstanceWrapper.h
38 // \file PythonQtInstanceWrapper.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include <QPointer>
48 #include <QPointer>
49
49
50 #include "structmember.h"
50 #include "structmember.h"
51 #include "methodobject.h"
51 #include "methodobject.h"
52 #include "compile.h"
52 #include "compile.h"
53 #include "eval.h"
53 #include "eval.h"
54
54
55 class PythonQtClassInfo;
55 class PythonQtClassInfo;
56 class QObject;
56 class QObject;
57
57
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
59
59
60 //---------------------------------------------------------------
60 //---------------------------------------------------------------
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
62 typedef struct PythonQtInstanceWrapperStruct {
62 typedef struct PythonQtInstanceWrapperStruct {
63 PyObject_HEAD
63 PyObject_HEAD
64
64
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
66 PythonQtClassInfo* classInfo();
66 PythonQtClassInfo* classInfo();
67
67
68 //! set the QObject pointer
68 //! set the QObject pointer
69 void setQObject(QObject* object) {
69 void setQObject(QObject* object) {
70 _obj = object;
70 _obj = object;
71 _objPointerCopy = object;
71 _objPointerCopy = object;
72 }
72 }
73
73
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
74 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
75 QPointer<QObject> _obj;
75 QPointer<QObject> _obj;
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
76 //! a copy of the _obj pointer, which is required because the wrapper needs to
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
77 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
78 void* _objPointerCopy;
78 void* _objPointerCopy;
79
79
80 //! optional C++ object Ptr that is wrapped by the above _obj
80 //! optional C++ object Ptr that is wrapped by the above _obj
81 void* _wrappedPtr;
81 void* _wrappedPtr;
82
82
83 // TODO xxx: put booleans into int that holds flags
83 // TODO xxx: put booleans into int that holds flags
84
84
85 //! flag that stores if the object is owned by pythonQt
85 //! flag that stores if the object is owned by pythonQt
86 bool _ownedByPythonQt;
86 bool _ownedByPythonQt;
87
87
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
88 //! stores that the owned object should be destroyed using QMetaType::destroy()
89 bool _useQMetaTypeDestroy;
89 bool _useQMetaTypeDestroy;
90
90
91 //! stores if the object is a shell instance
91 //! stores if the object is a shell instance
92 bool _isShellInstance;
92 bool _isShellInstance;
93
93
94 } PythonQtInstanceWrapper;
94 } PythonQtInstanceWrapper;
95
95
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
96 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds);
97
97
98 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self);
98 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self);
99
99
100 #endif
100 #endif
101
@@ -1,101 +1,128
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 PythonQtObjectPtr.cpp
35 // \file PythonQtObjectPtr.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
43
44 PythonQtObjectPtr::PythonQtObjectPtr(PyObject* o)
45 {
46 _object = o;
47 if (o) Py_INCREF(_object);
48 }
49
50 PythonQtObjectPtr::~PythonQtObjectPtr()
51 {
52 if (_object) Py_DECREF(_object);
53 }
54
55 void PythonQtObjectPtr::setNewRef(PyObject* o)
56 {
57 if (o != _object) {
58 if (_object) Py_DECREF(_object);
59 _object = o;
60 }
61 }
62
44 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
63 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
45 {
64 {
46 return PythonQt::self()->evalScript(_object, script, start);
65 return PythonQt::self()->evalScript(_object, script, start);
47 }
66 }
48
67
49 void PythonQtObjectPtr::evalFile(const QString& file)
68 void PythonQtObjectPtr::evalFile(const QString& file)
50 {
69 {
51 PythonQt::self()->evalFile(_object, file);
70 PythonQt::self()->evalFile(_object, file);
52 }
71 }
53
72
54 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
73 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
55 {
74 {
56 return PythonQt::self()->evalCode(_object, pycode);
75 return PythonQt::self()->evalCode(_object, pycode);
57 }
76 }
58
77
59 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
78 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
60 {
79 {
61 PythonQt::self()->addObject(_object, name, object);
80 PythonQt::self()->addObject(_object, name, object);
62 }
81 }
63
82
64 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
83 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
65 {
84 {
66 PythonQt::self()->addVariable(_object, name, v);
85 PythonQt::self()->addVariable(_object, name, v);
67 }
86 }
68
87
69 void PythonQtObjectPtr::removeVariable(const QString& name)
88 void PythonQtObjectPtr::removeVariable(const QString& name)
70 {
89 {
71 PythonQt::self()->removeVariable(_object, name);
90 PythonQt::self()->removeVariable(_object, name);
72 }
91 }
73
92
74 QVariant PythonQtObjectPtr::getVariable(const QString& name)
93 QVariant PythonQtObjectPtr::getVariable(const QString& name)
75 {
94 {
76 return PythonQt::self()->getVariable(_object, name);
95 return PythonQt::self()->getVariable(_object, name);
77 }
96 }
78
97
79
98
80 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
99 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
81 {
100 {
82 return PythonQt::self()->call(_object, callable, args);
101 return PythonQt::self()->call(_object, callable, args);
83 }
102 }
84
103
85 QVariant PythonQtObjectPtr::call(const QVariantList& args)
104 QVariant PythonQtObjectPtr::call(const QVariantList& args)
86 {
105 {
87 return PythonQt::self()->call(_object, args);
106 return PythonQt::self()->call(_object, args);
88 }
107 }
89
108
90 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
109 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
91 {
110 {
92 if (!variant.isNull()) {
111 if (!variant.isNull()) {
93 setObject(qVariantValue<PythonQtObjectPtr>(variant));
112 setObject(qVariantValue<PythonQtObjectPtr>(variant));
94 return true;
113 return true;
95 }
114 }
96 else {
115 else {
97 setObject(0);
116 setObject(0);
98 return false;
117 return false;
99 }
118 }
119 }
100
120
121 void PythonQtObjectPtr::setObject(PyObject* o)
122 {
123 if (o != _object) {
124 if (_object) Py_DECREF(_object);
125 _object = o;
126 if (_object) Py_INCREF(_object);
127 }
101 }
128 }
@@ -1,174 +1,163
1 #ifndef _PYTHONQTOBJECTPTR_H
1 #ifndef _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtObjectPtr.h
38 // \file PythonQtObjectPtr.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include "PythonQtPythonInclude.h"
46
46 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
47 #include <QVariant>
48 #include <QVariant>
48 #include <QVariantList>
49 #include <QVariantList>
49
50
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
51 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
51 class PYTHONQT_EXPORT PythonQtObjectPtr
52 class PYTHONQT_EXPORT PythonQtObjectPtr
52 {
53 {
53 public:
54 public:
54 PythonQtObjectPtr():_object(NULL) {}
55 PythonQtObjectPtr():_object(NULL) {}
55
56
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
57 PythonQtObjectPtr(const PythonQtObjectPtr &p)
58 :_object(NULL) {
57 setObject(p.object());
59 setObject(p.object());
58 }
60 }
59
61
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
62 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
63 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
62 fromVariant(variant);
64 fromVariant(variant);
63 }
65 }
64
66
65 PythonQtObjectPtr(PyObject* o) {
67 PythonQtObjectPtr(PyObject* o);
66 _object = o;
67 if (o) Py_INCREF(_object);
68 }
69
68
70 ~PythonQtObjectPtr() { if (_object) { Py_DECREF(_object); } }
69 ~PythonQtObjectPtr();
71
70
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
71 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
73 bool fromVariant(const QVariant& variant);
72 bool fromVariant(const QVariant& variant);
74
73
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
74 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
76 setObject(p.object());
75 setObject(p.object());
77 return *this;
76 return *this;
78 }
77 }
79
78
80 PythonQtObjectPtr &operator=(PyObject* o) {
79 PythonQtObjectPtr &operator=(PyObject* o) {
81 setObject(o);
80 setObject(o);
82 return *this;
81 return *this;
83 }
82 }
84
83
85
84
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
85 PythonQtObjectPtr &operator=(const QVariant& variant) {
87 fromVariant(variant);
86 fromVariant(variant);
88 return *this;
87 return *this;
89 }
88 }
90
89
91
90
92 bool operator==( const PythonQtObjectPtr &p ) const {
91 bool operator==( const PythonQtObjectPtr &p ) const {
93 return object() == p.object();
92 return object() == p.object();
94 }
93 }
95
94
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
95 bool operator!= ( const PythonQtObjectPtr& p ) const {
97 return !( *this == p );
96 return !( *this == p );
98 }
97 }
99
98
100 bool operator==( PyObject* p ) const {
99 bool operator==( PyObject* p ) const {
101 return object() == p;
100 return object() == p;
102 }
101 }
103
102
104 bool operator!= ( PyObject* p ) const {
103 bool operator!= ( PyObject* p ) const {
105 return object() != p;
104 return object() != p;
106 }
105 }
107
106
108 bool isNull() const { return !object(); }
107 bool isNull() const { return !object(); }
109
108
110 PyObject* operator->() const { return object(); }
109 PyObject* operator->() const { return object(); }
111
110
112 PyObject& operator*() const { return *( object() ); }
111 PyObject& operator*() const { return *( object() ); }
113
112
114 operator PyObject*() const { return object(); }
113 operator PyObject*() const { return object(); }
115
114
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
115 //! sets the object and passes the ownership (stealing the reference, in Python slang)
117 void setNewRef(PyObject* o) {
116 void setNewRef(PyObject* o);
118 if (o != _object) {
119 if (_object) { Py_DECREF(_object); }
120 _object = o;
121 }
122 }
123
117
124 PyObject* object() const {
118 PyObject* object() const {
125 return _object;
119 return _object;
126 }
120 }
127
121
128 //! evaluates the given script code in the context of this object and returns the result value
122 //! evaluates the given script code in the context of this object and returns the result value
129 QVariant evalScript(const QString& script, int start = Py_file_input);
123 QVariant evalScript(const QString& script, int start = Py_file_input);
130
124
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
125 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
132 //! If pycode is NULL, a python error is printed.
126 //! If pycode is NULL, a python error is printed.
133 QVariant evalCode(PyObject* pycode);
127 QVariant evalCode(PyObject* pycode);
134
128
135 //! evaluates the given code in the context
129 //! evaluates the given code in the context
136 void evalFile(const QString& filename);
130 void evalFile(const QString& filename);
137
131
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
132 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
139 void addObject(const QString& name, QObject* object);
133 void addObject(const QString& name, QObject* object);
140
134
141 //! add the given variable to the module
135 //! add the given variable to the module
142 void addVariable(const QString& name, const QVariant& v);
136 void addVariable(const QString& name, const QVariant& v);
143
137
144 //! remove the given variable
138 //! remove the given variable
145 void removeVariable(const QString& name);
139 void removeVariable(const QString& name);
146
140
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
141 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
148 QVariant getVariable(const QString& name);
142 QVariant getVariable(const QString& name);
149
143
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
144 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
145 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
152
146
153 //! call the contained python object directly, returns the result converted to a QVariant
147 //! call the contained python object directly, returns the result converted to a QVariant
154 QVariant call(const QVariantList& args = QVariantList());
148 QVariant call(const QVariantList& args = QVariantList());
155
149
156 protected:
150 protected:
157
151
158 void setObject(PyObject* o) {
152 void setObject(PyObject* o);
159 if (o != _object) {
160 if (_object) { Py_DECREF(_object); }
161 _object = o;
162 if (_object) { Py_INCREF(_object); }
163 }
164 }
165
153
166 private:
154 private:
167 PyObject* _object;
155 PyObject* _object;
168 };
156 };
169
157
170
158
171 // register it to the meta type system
159 // register it to the meta type system
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
160 Q_DECLARE_METATYPE(PythonQtObjectPtr)
173
161
174 #endif
162 #endif
163
@@ -1,141 +1,142
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSignalReceiver.h
38 // \file PythonQtSignalReceiver.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include "PythonQtPythonInclude.h"
46
46 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
47 #include "PythonQtObjectPtr.h"
48 #include "PythonQtObjectPtr.h"
48
49
49 class PythonQtMethodInfo;
50 class PythonQtMethodInfo;
50 class PythonQtClassInfo;
51 class PythonQtClassInfo;
51
52
52 //! stores information about a signal target
53 //! stores information about a signal target
53 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 */
55 */
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 public:
57 public:
57 PythonQtSignalTarget() {
58 PythonQtSignalTarget() {
58 _signalId = -1;
59 _signalId = -1;
59 _methodInfo = NULL;
60 _methodInfo = NULL;
60 _slotId = -1;
61 _slotId = -1;
61 }
62 }
62
63
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 {
65 {
65 _signalId = signalId;
66 _signalId = signalId;
66 _slotId = slotId;
67 _slotId = slotId;
67 _methodInfo = methodInfo;
68 _methodInfo = methodInfo;
68 _callable = callable;
69 _callable = callable;
69 };
70 };
70
71
71 ~PythonQtSignalTarget() {
72 ~PythonQtSignalTarget() {
72 };
73 };
73
74
74 //! get the id of the original signal
75 //! get the id of the original signal
75 int signalId() const { return _signalId; }
76 int signalId() const { return _signalId; }
76
77
77 //! get the id that was assigned to this simulated slot
78 //! get the id that was assigned to this simulated slot
78 int slotId() const { return _slotId; }
79 int slotId() const { return _slotId; }
79
80
80 //! get the signals parameter info
81 //! get the signals parameter info
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82
83
83 //! call the python callable with the given arguments (as defined in methodInfo)
84 //! call the python callable with the given arguments (as defined in methodInfo)
84 void call(void **arguments) const;
85 void call(void **arguments) const;
85
86
86 //! check if it is the same signal target
87 //! check if it is the same signal target
87 bool isSame(int signalId, PyObject* callable) const;
88 bool isSame(int signalId, PyObject* callable) const;
88
89
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91
92
92 private:
93 private:
93 int _signalId;
94 int _signalId;
94 int _slotId;
95 int _slotId;
95 const PythonQtMethodInfo* _methodInfo;
96 const PythonQtMethodInfo* _methodInfo;
96 PythonQtObjectPtr _callable;
97 PythonQtObjectPtr _callable;
97 };
98 };
98
99
99 //! base class for signal receivers
100 //! base class for signal receivers
100 /*!
101 /*!
101 */
102 */
102 class PythonQtSignalReceiverBase : public QObject {
103 class PythonQtSignalReceiverBase : public QObject {
103 Q_OBJECT
104 Q_OBJECT
104 public:
105 public:
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 };
107 };
107
108
108 //! receives all signals for one QObject
109 //! receives all signals for one QObject
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 */
111 */
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112
113
113 public:
114 public:
114 PythonQtSignalReceiver(QObject* obj);
115 PythonQtSignalReceiver(QObject* obj);
115 ~PythonQtSignalReceiver();
116 ~PythonQtSignalReceiver();
116
117
117 //! add a signal handler
118 //! add a signal handler
118 bool addSignalHandler(const char* signal, PyObject* callable);
119 bool addSignalHandler(const char* signal, PyObject* callable);
119
120
120 //! remove a signal handler
121 //! remove a signal handler
121 bool removeSignalHandler(const char* signal, PyObject* callable);
122 bool removeSignalHandler(const char* signal, PyObject* callable);
122
123
123 //! remove all signal handlers
124 //! remove all signal handlers
124 void removeSignalHandlers();
125 void removeSignalHandlers();
125
126
126 //! we implement this method to simulate a number of slots that match the ids in _targets
127 //! we implement this method to simulate a number of slots that match the ids in _targets
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
128 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
128
129
129 private:
130 private:
130 //! get the index of the signal
131 //! get the index of the signal
131 int getSignalIndex(const char* signal);
132 int getSignalIndex(const char* signal);
132
133
133 QObject* _obj;
134 QObject* _obj;
134 PythonQtClassInfo* _objClassInfo;
135 PythonQtClassInfo* _objClassInfo;
135 int _slotCount;
136 int _slotCount;
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
137 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
137 QList<PythonQtSignalTarget> _targets;
138 QList<PythonQtSignalTarget> _targets;
138 };
139 };
139
140
140
141
141 #endif
142 #endif
@@ -1,556 +1,556
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #include <exception>
50 #include <exception>
51 #include <stdexcept>
51 #include <stdexcept>
52
52
53 #define PYTHONQT_MAX_ARGS 32
53 #define PYTHONQT_MAX_ARGS 32
54
54
55
55
56 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
56 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
57 {
57 {
58 static unsigned int recursiveEntry = 0;
58 static unsigned int recursiveEntry = 0;
59
59
60 if (directReturnValuePointer) {
60 if (directReturnValuePointer) {
61 *directReturnValuePointer = NULL;
61 *directReturnValuePointer = NULL;
62 }
62 }
63 // store the current storage position, so that we can get back to this state after a slot is called
63 // store the current storage position, so that we can get back to this state after a slot is called
64 // (do this locally, so that we have all positions on the stack
64 // (do this locally, so that we have all positions on the stack
65 PythonQtValueStoragePosition globalValueStoragePos;
65 PythonQtValueStoragePosition globalValueStoragePos;
66 PythonQtValueStoragePosition globalPtrStoragePos;
66 PythonQtValueStoragePosition globalPtrStoragePos;
67 PythonQtValueStoragePosition globalVariantStoragePos;
67 PythonQtValueStoragePosition globalVariantStoragePos;
68 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
68 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
69 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
69 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
70 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
70 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
71
71
72 recursiveEntry++;
72 recursiveEntry++;
73
73
74 // the arguments that are passed to qt_metacall
74 // the arguments that are passed to qt_metacall
75 void* argList[PYTHONQT_MAX_ARGS];
75 void* argList[PYTHONQT_MAX_ARGS];
76 PyObject* result = NULL;
76 PyObject* result = NULL;
77 int argc = info->parameterCount();
77 int argc = info->parameterCount();
78 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
78 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
79
79
80 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
80 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
81 // set return argument to NULL
81 // set return argument to NULL
82 argList[0] = NULL;
82 argList[0] = NULL;
83
83
84 bool ok = true;
84 bool ok = true;
85 bool skipFirst = false;
85 bool skipFirst = false;
86 if (info->isInstanceDecorator()) {
86 if (info->isInstanceDecorator()) {
87 skipFirst = true;
87 skipFirst = true;
88
88
89 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
89 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
90 void* arg1 = firstArgument;
90 void* arg1 = firstArgument;
91 if (!arg1) {
91 if (!arg1) {
92 arg1 = objectToCall;
92 arg1 = objectToCall;
93 }
93 }
94 if (arg1) {
94 if (arg1) {
95 // upcast to correct parent class
95 // upcast to correct parent class
96 arg1 = ((char*)arg1)+info->upcastingOffset();
96 arg1 = ((char*)arg1)+info->upcastingOffset();
97 }
97 }
98
98
99 argList[1] = &arg1;
99 argList[1] = &arg1;
100 if (ok) {
100 if (ok) {
101 for (int i = 2; i<argc && ok; i++) {
101 for (int i = 2; i<argc && ok; i++) {
102 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
102 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
103 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
103 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
104 if (argList[i]==NULL) {
104 if (argList[i]==NULL) {
105 ok = false;
105 ok = false;
106 break;
106 break;
107 }
107 }
108 }
108 }
109 }
109 }
110 } else {
110 } else {
111 for (int i = 1; i<argc && ok; i++) {
111 for (int i = 1; i<argc && ok; i++) {
112 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
112 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
113 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
113 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
114 if (argList[i]==NULL) {
114 if (argList[i]==NULL) {
115 ok = false;
115 ok = false;
116 break;
116 break;
117 }
117 }
118 }
118 }
119 }
119 }
120
120
121 if (ok) {
121 if (ok) {
122 // parameters are ok, now create the qt return value which is assigned to by metacall
122 // parameters are ok, now create the qt return value which is assigned to by metacall
123 if (returnValueParam.typeId != QMetaType::Void) {
123 if (returnValueParam.typeId != QMetaType::Void) {
124 // create empty default value for the return value
124 // create empty default value for the return value
125 if (!directReturnValuePointer) {
125 if (!directReturnValuePointer) {
126 // create empty default value for the return value
126 // create empty default value for the return value
127 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
127 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
128 if (argList[0]==NULL) {
128 if (argList[0]==NULL) {
129 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
129 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
130 // pass its internal pointer
130 // pass its internal pointer
131 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
131 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
132 if (info && info->pythonQtClassWrapper()) {
132 if (info && info->pythonQtClassWrapper()) {
133 PyObject* emptyTuple = PyTuple_New(0);
133 PyObject* emptyTuple = PyTuple_New(0);
134 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
134 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
135 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
135 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
136 if (result) {
136 if (result) {
137 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
137 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
138 }
138 }
139 Py_DECREF(emptyTuple);
139 Py_DECREF(emptyTuple);
140 }
140 }
141 }
141 }
142 } else {
142 } else {
143 // we can use our pointer directly!
143 // we can use our pointer directly!
144 argList[0] = directReturnValuePointer;
144 argList[0] = directReturnValuePointer;
145 }
145 }
146 }
146 }
147
147
148
148
149 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
149 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
150 if (profilingCB) {
150 if (profilingCB) {
151 const char* className = NULL;
151 const char* className = NULL;
152 if (info->decorator()) {
152 if (info->decorator()) {
153 className = info->decorator()->metaObject()->className();
153 className = info->decorator()->metaObject()->className();
154 } else {
154 } else {
155 className = objectToCall->metaObject()->className();
155 className = objectToCall->metaObject()->className();
156 }
156 }
157
157
158 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
158 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
159 }
159 }
160
160
161 // invoke the slot via metacall
161 // invoke the slot via metacall
162 bool hadException = false;
162 bool hadException = false;
163 try {
163 try {
164 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
164 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
165 } catch (std::bad_alloc & e) {
165 } catch (std::bad_alloc & e) {
166 hadException = true;
166 hadException = true;
167 QByteArray what("std::bad_alloc: ");
167 QByteArray what("std::bad_alloc: ");
168 what += e.what();
168 what += e.what();
169 PyErr_SetString(PyExc_MemoryError, what.constData());
169 PyErr_SetString(PyExc_MemoryError, what.constData());
170 } catch (std::runtime_error & e) {
170 } catch (std::runtime_error & e) {
171 hadException = true;
171 hadException = true;
172 QByteArray what("std::runtime_error: ");
172 QByteArray what("std::runtime_error: ");
173 what += e.what();
173 what += e.what();
174 PyErr_SetString(PyExc_RuntimeError, what.constData());
174 PyErr_SetString(PyExc_RuntimeError, what.constData());
175 } catch (std::logic_error & e) {
175 } catch (std::logic_error & e) {
176 hadException = true;
176 hadException = true;
177 QByteArray what("std::logic_error: ");
177 QByteArray what("std::logic_error: ");
178 what += e.what();
178 what += e.what();
179 PyErr_SetString(PyExc_RuntimeError, what.constData());
179 PyErr_SetString(PyExc_RuntimeError, what.constData());
180 } catch (std::exception& e) {
180 } catch (std::exception& e) {
181 hadException = true;
181 hadException = true;
182 QByteArray what("std::exception: ");
182 QByteArray what("std::exception: ");
183 what += e.what();
183 what += e.what();
184 PyErr_SetString(PyExc_StandardError, what.constData());
184 PyErr_SetString(PyExc_StandardError, what.constData());
185 }
185 }
186
186
187 if (profilingCB) {
187 if (profilingCB) {
188 profilingCB(PythonQt::Leave, NULL, NULL);
188 profilingCB(PythonQt::Leave, NULL, NULL);
189 }
189 }
190
190
191 // handle the return value (which in most cases still needs to be converted to a Python object)
191 // handle the return value (which in most cases still needs to be converted to a Python object)
192 if (!hadException) {
192 if (!hadException) {
193 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
193 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
194 if (directReturnValuePointer) {
194 if (directReturnValuePointer) {
195 result = NULL;
195 result = NULL;
196 } else {
196 } else {
197 // the resulting object maybe present already, because we created it above at 1)...
197 // the resulting object maybe present already, because we created it above at 1)...
198 if (!result) {
198 if (!result) {
199 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
199 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
200 }
200 }
201 }
201 }
202 } else {
202 } else {
203 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
203 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
204 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
204 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
205 result = NULL;
205 result = NULL;
206 }
206 }
207 } else {
207 } else {
208 result = NULL;
208 result = NULL;
209 }
209 }
210 }
210 }
211 recursiveEntry--;
211 recursiveEntry--;
212
212
213 // reset the parameter storage position to the stored pos to "pop" the parameter stack
213 // reset the parameter storage position to the stored pos to "pop" the parameter stack
214 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
214 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
215 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
215 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
216 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
216 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
217
217
218 *pythonReturnValue = result;
218 *pythonReturnValue = result;
219 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
219 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
220 return result || (directReturnValuePointer && *directReturnValuePointer);
220 return result || (directReturnValuePointer && *directReturnValuePointer);
221 }
221 }
222
222
223 //-----------------------------------------------------------------------------------
223 //-----------------------------------------------------------------------------------
224
224
225 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
225 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
226
226
227 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
227 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
228 {
228 {
229 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
229 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
230 PythonQtSlotInfo* info = f->m_ml;
230 PythonQtSlotInfo* info = f->m_ml;
231 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
231 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
232 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
232 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
233 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
233 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
234 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
234 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
235 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
235 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
236 return NULL;
236 return NULL;
237 } else {
237 } else {
238 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
238 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
239 }
239 }
240 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
240 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
241 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
241 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
242 if (info->isClassDecorator()) {
242 if (info->isClassDecorator()) {
243 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
243 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
244 } else {
244 } else {
245 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
245 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
246 Py_ssize_t argc = PyTuple_Size(args);
246 Py_ssize_t argc = PyTuple_Size(args);
247 if (argc>0) {
247 if (argc>0) {
248 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
248 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
249 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
249 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
250 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
250 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
251 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
251 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
252 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
252 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
253 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
253 QString error = QString("Trying to call '") + f->m_ml->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
254 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
254 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
255 return NULL;
255 return NULL;
256 }
256 }
257 // strip the first argument...
257 // strip the first argument...
258 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
258 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
259 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
259 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
260 Py_DECREF(newargs);
260 Py_DECREF(newargs);
261 return result;
261 return result;
262 } else {
262 } else {
263 // first arg is not of correct type!
263 // first arg is not of correct type!
264 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
264 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
265 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
265 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
266 return NULL;
266 return NULL;
267 }
267 }
268 } else {
268 } else {
269 // wrong number of args
269 // wrong number of args
270 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
270 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
271 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
271 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
272 return NULL;
272 return NULL;
273 }
273 }
274 }
274 }
275 }
275 }
276 return NULL;
276 return NULL;
277 }
277 }
278
278
279 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
279 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
280 {
280 {
281 int argc = args?PyTuple_Size(args):0;
281 int argc = args?PyTuple_Size(args):0;
282
282
283 #ifdef PYTHONQT_DEBUG
283 #ifdef PYTHONQT_DEBUG
284 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
284 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
285 #endif
285 #endif
286
286
287 PyObject* r = NULL;
287 PyObject* r = NULL;
288 bool ok = false;
288 bool ok = false;
289 if (directReturnValuePointer) {
289 if (directReturnValuePointer) {
290 *directReturnValuePointer = NULL;
290 *directReturnValuePointer = NULL;
291 }
291 }
292 if (info->nextInfo()) {
292 if (info->nextInfo()) {
293 // overloaded slot call, try on all slots with strict conversion first
293 // overloaded slot call, try on all slots with strict conversion first
294 bool strict = true;
294 bool strict = true;
295 PythonQtSlotInfo* i = info;
295 PythonQtSlotInfo* i = info;
296 while (i) {
296 while (i) {
297 bool skipFirst = i->isInstanceDecorator();
297 bool skipFirst = i->isInstanceDecorator();
298 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
298 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
299 PyErr_Clear();
299 PyErr_Clear();
300 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
300 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
301 if (PyErr_Occurred() || ok) break;
301 if (PyErr_Occurred() || ok) break;
302 }
302 }
303 i = i->nextInfo();
303 i = i->nextInfo();
304 if (!i) {
304 if (!i) {
305 if (strict) {
305 if (strict) {
306 // one more run without being strict
306 // one more run without being strict
307 strict = false;
307 strict = false;
308 i = info;
308 i = info;
309 }
309 }
310 }
310 }
311 }
311 }
312 if (!ok && !PyErr_Occurred()) {
312 if (!ok && !PyErr_Occurred()) {
313 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
313 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
314 PythonQtSlotInfo* i = info;
314 PythonQtSlotInfo* i = info;
315 while (i) {
315 while (i) {
316 e += QString(i->fullSignature()) + "\n";
316 e += QString(i->fullSignature()) + "\n";
317 i = i->nextInfo();
317 i = i->nextInfo();
318 }
318 }
319 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
319 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
320 }
320 }
321 } else {
321 } else {
322 // simple (non-overloaded) slot call
322 // simple (non-overloaded) slot call
323 bool skipFirst = info->isInstanceDecorator();
323 bool skipFirst = info->isInstanceDecorator();
324 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
324 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
325 PyErr_Clear();
325 PyErr_Clear();
326 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
326 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
327 if (!ok && !PyErr_Occurred()) {
327 if (!ok && !PyErr_Occurred()) {
328 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
328 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
329 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
329 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
330 }
330 }
331 } else {
331 } else {
332 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
332 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
333 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
333 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
334 }
334 }
335 }
335 }
336
336
337 return r;
337 return r;
338 }
338 }
339
339
340 PyObject *
340 PyObject *
341 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
341 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
342 {
342 {
343 PythonQtSlotFunctionObject *op;
343 PythonQtSlotFunctionObject *op;
344 op = pythonqtslot_free_list;
344 op = pythonqtslot_free_list;
345 if (op != NULL) {
345 if (op != NULL) {
346 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
346 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
347 PyObject_INIT(op, &PythonQtSlotFunction_Type);
347 PyObject_INIT(op, &PythonQtSlotFunction_Type);
348 }
348 }
349 else {
349 else {
350 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
350 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
351 if (op == NULL)
351 if (op == NULL)
352 return NULL;
352 return NULL;
353 }
353 }
354 op->m_ml = ml;
354 op->m_ml = ml;
355 Py_XINCREF(self);
355 Py_XINCREF(self);
356 op->m_self = self;
356 op->m_self = self;
357 Py_XINCREF(module);
357 Py_XINCREF(module);
358 op->m_module = module;
358 op->m_module = module;
359 PyObject_GC_Track(op);
359 PyObject_GC_Track(op);
360 return (PyObject *)op;
360 return (PyObject *)op;
361 }
361 }
362
362
363 PythonQtSlotInfo*
363 PythonQtSlotInfo*
364 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
364 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
365 {
365 {
366 if (!PythonQtSlotFunction_Check(op)) {
366 if (!PythonQtSlotFunction_Check(op)) {
367 PyErr_BadInternalCall();
367 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
368 return NULL;
368 return NULL;
369 }
369 }
370 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
370 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
371 }
371 }
372
372
373 PyObject *
373 PyObject *
374 PythonQtSlotFunction_GetSelf(PyObject *op)
374 PythonQtSlotFunction_GetSelf(PyObject *op)
375 {
375 {
376 if (!PythonQtSlotFunction_Check(op)) {
376 if (!PythonQtSlotFunction_Check(op)) {
377 PyErr_BadInternalCall();
377 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
378 return NULL;
378 return NULL;
379 }
379 }
380 return ((PythonQtSlotFunctionObject *)op) -> m_self;
380 return ((PythonQtSlotFunctionObject *)op) -> m_self;
381 }
381 }
382
382
383 /* Methods (the standard built-in methods, that is) */
383 /* Methods (the standard built-in methods, that is) */
384
384
385 static void
385 static void
386 meth_dealloc(PythonQtSlotFunctionObject *m)
386 meth_dealloc(PythonQtSlotFunctionObject *m)
387 {
387 {
388 PyObject_GC_UnTrack(m);
388 PyObject_GC_UnTrack(m);
389 Py_XDECREF(m->m_self);
389 Py_XDECREF(m->m_self);
390 Py_XDECREF(m->m_module);
390 Py_XDECREF(m->m_module);
391 m->m_self = (PyObject *)pythonqtslot_free_list;
391 m->m_self = (PyObject *)pythonqtslot_free_list;
392 pythonqtslot_free_list = m;
392 pythonqtslot_free_list = m;
393 }
393 }
394
394
395 static PyObject *
395 static PyObject *
396 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
396 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
397 {
397 {
398 Py_INCREF(Py_None);
398 Py_INCREF(Py_None);
399 return Py_None;
399 return Py_None;
400 }
400 }
401
401
402 static PyObject *
402 static PyObject *
403 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
403 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
404 {
404 {
405 return PyString_FromString(m->m_ml->metaMethod()->signature());
405 return PyString_FromString(m->m_ml->metaMethod()->signature());
406 }
406 }
407
407
408 static int
408 static int
409 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
409 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
410 {
410 {
411 int err;
411 int err;
412 if (m->m_self != NULL) {
412 if (m->m_self != NULL) {
413 err = visit(m->m_self, arg);
413 err = visit(m->m_self, arg);
414 if (err)
414 if (err)
415 return err;
415 return err;
416 }
416 }
417 if (m->m_module != NULL) {
417 if (m->m_module != NULL) {
418 err = visit(m->m_module, arg);
418 err = visit(m->m_module, arg);
419 if (err)
419 if (err)
420 return err;
420 return err;
421 }
421 }
422 return 0;
422 return 0;
423 }
423 }
424
424
425 static PyObject *
425 static PyObject *
426 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
426 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
427 {
427 {
428 PyObject *self;
428 PyObject *self;
429 if (PyEval_GetRestricted()) {
429 if (PyEval_GetRestricted()) {
430 PyErr_SetString(PyExc_RuntimeError,
430 PyErr_SetString(PyExc_RuntimeError,
431 "method.__self__ not accessible in restricted mode");
431 "method.__self__ not accessible in restricted mode");
432 return NULL;
432 return NULL;
433 }
433 }
434 self = m->m_self;
434 self = m->m_self;
435 if (self == NULL)
435 if (self == NULL)
436 self = Py_None;
436 self = Py_None;
437 Py_INCREF(self);
437 Py_INCREF(self);
438 return self;
438 return self;
439 }
439 }
440
440
441 static PyGetSetDef meth_getsets [] = {
441 static PyGetSetDef meth_getsets [] = {
442 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
442 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
443 {"__name__", (getter)meth_get__name__, NULL, NULL},
443 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
444 {"__self__", (getter)meth_get__self__, NULL, NULL},
444 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
445 {NULL, NULL, NULL,NULL},
445 {NULL, NULL, NULL,NULL},
446 };
446 };
447
447
448 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
448 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
449 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
449 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
450 #endif
450 #endif
451
451
452 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
452 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
453
453
454 static PyMemberDef meth_members[] = {
454 static PyMemberDef meth_members[] = {
455 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
455 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
456 {NULL}
456 {NULL}
457 };
457 };
458
458
459 static PyObject *
459 static PyObject *
460 meth_repr(PythonQtSlotFunctionObject *f)
460 meth_repr(PythonQtSlotFunctionObject *f)
461 {
461 {
462 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
462 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
463 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
463 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
464 return PyString_FromFormat("<unbound qt slot %s of %s type>",
464 return PyString_FromFormat("<unbound qt slot %s of %s type>",
465 f->m_ml->slotName().data(),
465 f->m_ml->slotName().data(),
466 self->classInfo()->className());
466 self->classInfo()->className());
467 } else {
467 } else {
468 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
468 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
469 f->m_ml->slotName().data(),
469 f->m_ml->slotName().data(),
470 f->m_self->ob_type->tp_name,
470 f->m_self->ob_type->tp_name,
471 f->m_self);
471 f->m_self);
472 }
472 }
473 }
473 }
474
474
475 static int
475 static int
476 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
476 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
477 {
477 {
478 if (a->m_self != b->m_self)
478 if (a->m_self != b->m_self)
479 return (a->m_self < b->m_self) ? -1 : 1;
479 return (a->m_self < b->m_self) ? -1 : 1;
480 if (a->m_ml == b->m_ml)
480 if (a->m_ml == b->m_ml)
481 return 0;
481 return 0;
482 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
482 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
483 return -1;
483 return -1;
484 else
484 else
485 return 1;
485 return 1;
486 }
486 }
487
487
488 static long
488 static long
489 meth_hash(PythonQtSlotFunctionObject *a)
489 meth_hash(PythonQtSlotFunctionObject *a)
490 {
490 {
491 long x,y;
491 long x,y;
492 if (a->m_self == NULL)
492 if (a->m_self == NULL)
493 x = 0;
493 x = 0;
494 else {
494 else {
495 x = PyObject_Hash(a->m_self);
495 x = PyObject_Hash(a->m_self);
496 if (x == -1)
496 if (x == -1)
497 return -1;
497 return -1;
498 }
498 }
499 y = _Py_HashPointer((void*)(a->m_ml));
499 y = _Py_HashPointer((void*)(a->m_ml));
500 if (y == -1)
500 if (y == -1)
501 return -1;
501 return -1;
502 x ^= y;
502 x ^= y;
503 if (x == -1)
503 if (x == -1)
504 x = -2;
504 x = -2;
505 return x;
505 return x;
506 }
506 }
507
507
508
508
509 PyTypeObject PythonQtSlotFunction_Type = {
509 PyTypeObject PythonQtSlotFunction_Type = {
510 PyObject_HEAD_INIT(&PyType_Type)
510 PyObject_HEAD_INIT(&PyType_Type)
511 0,
511 0,
512 "builtin_qt_slot",
512 "builtin_qt_slot",
513 sizeof(PythonQtSlotFunctionObject),
513 sizeof(PythonQtSlotFunctionObject),
514 0,
514 0,
515 (destructor)meth_dealloc, /* tp_dealloc */
515 (destructor)meth_dealloc, /* tp_dealloc */
516 0, /* tp_print */
516 0, /* tp_print */
517 0, /* tp_getattr */
517 0, /* tp_getattr */
518 0, /* tp_setattr */
518 0, /* tp_setattr */
519 (cmpfunc)meth_compare, /* tp_compare */
519 (cmpfunc)meth_compare, /* tp_compare */
520 (reprfunc)meth_repr, /* tp_repr */
520 (reprfunc)meth_repr, /* tp_repr */
521 0, /* tp_as_number */
521 0, /* tp_as_number */
522 0, /* tp_as_sequence */
522 0, /* tp_as_sequence */
523 0, /* tp_as_mapping */
523 0, /* tp_as_mapping */
524 (hashfunc)meth_hash, /* tp_hash */
524 (hashfunc)meth_hash, /* tp_hash */
525 PythonQtSlotFunction_Call, /* tp_call */
525 PythonQtSlotFunction_Call, /* tp_call */
526 0, /* tp_str */
526 0, /* tp_str */
527 PyObject_GenericGetAttr, /* tp_getattro */
527 PyObject_GenericGetAttr, /* tp_getattro */
528 0, /* tp_setattro */
528 0, /* tp_setattro */
529 0, /* tp_as_buffer */
529 0, /* tp_as_buffer */
530 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
530 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
531 0, /* tp_doc */
531 0, /* tp_doc */
532 (traverseproc)meth_traverse, /* tp_traverse */
532 (traverseproc)meth_traverse, /* tp_traverse */
533 0, /* tp_clear */
533 0, /* tp_clear */
534 0, /* tp_richcompare */
534 0, /* tp_richcompare */
535 0, /* tp_weaklistoffset */
535 0, /* tp_weaklistoffset */
536 0, /* tp_iter */
536 0, /* tp_iter */
537 0, /* tp_iternext */
537 0, /* tp_iternext */
538 0, /* tp_methods */
538 0, /* tp_methods */
539 meth_members, /* tp_members */
539 meth_members, /* tp_members */
540 meth_getsets, /* tp_getset */
540 meth_getsets, /* tp_getset */
541 0, /* tp_base */
541 0, /* tp_base */
542 0, /* tp_dict */
542 0, /* tp_dict */
543 };
543 };
544
544
545 /* Clear out the free list */
545 /* Clear out the free list */
546
546
547 void
547 void
548 PythonQtSlotFunction_Fini(void)
548 PythonQtSlotFunction_Fini(void)
549 {
549 {
550 while (pythonqtslot_free_list) {
550 while (pythonqtslot_free_list) {
551 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
551 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
552 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
552 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
553 PyObject_GC_Del(v);
553 PyObject_GC_Del(v);
554 }
554 }
555 }
555 }
556
556
@@ -1,80 +1,81
1 #ifndef _PYTHONQTSLOT_H
1 #ifndef _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
2 #define _PYTHONQTSLOT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtSlot.h
38 // \file PythonQtSlot.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "Python.h"
45 #include "PythonQtPythonInclude.h"
46
46 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
47 #include "structmember.h"
48 #include "structmember.h"
48
49
49 class PythonQtSlotInfo;
50 class PythonQtSlotInfo;
50
51
51 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
52 extern PYTHONQT_EXPORT PyTypeObject PythonQtSlotFunction_Type;
52
53
53 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
54 #define PythonQtSlotFunction_Check(op) ((op)->ob_type == &PythonQtSlotFunction_Type)
54
55
55 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
56 PythonQtSlotInfo* PythonQtSlotFunction_GetSlotInfo(PyObject *);
56 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
57 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
57
58
58 /* Macros for direct access to these values. Type checks are *not*
59 /* Macros for direct access to these values. Type checks are *not*
59 done, so use with care. */
60 done, so use with care. */
60 #define PythonQtSlotFunction_GET_SELF(func) \
61 #define PythonQtSlotFunction_GET_SELF(func) \
61 (((PythonQtSlotFunctionObject *)func) -> m_self)
62 (((PythonQtSlotFunctionObject *)func) -> m_self)
62
63
63 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
64 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
64
65
65 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
66 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
66
67
67
68
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
69 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
69 PyObject *);
70 PyObject *);
70
71
71 //! defines a python object that stores a Qt slot info
72 //! defines a python object that stores a Qt slot info
72 typedef struct {
73 typedef struct {
73 PyObject_HEAD
74 PyObject_HEAD
74 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
75 PythonQtSlotInfo *m_ml; /* Description of the C function to call */
75 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
76 PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */
76 PyObject *m_module; /* The __module__ attribute, can be anything */
77 PyObject *m_module; /* The __module__ attribute, can be anything */
77 } PythonQtSlotFunctionObject;
78 } PythonQtSlotFunctionObject;
78
79
79
80
80 #endif
81 #endif
@@ -1,107 +1,109
1 #ifndef _PYTHONQTSTDDECORATORS_H
1 #ifndef _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtStdDecorators.h
38 // \file PythonQtStdDecorators.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-04
41 // \date 2007-04
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtPythonInclude.h"
46
45 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
46 #include <Python.h>
48
47 #include <QObject>
49 #include <QObject>
48 #include <QVariantList>
50 #include <QVariantList>
49 #include <QTextDocument>
51 #include <QTextDocument>
50 #include <QColor>
52 #include <QColor>
51 #include <QDateTime>
53 #include <QDateTime>
52 #include <QDate>
54 #include <QDate>
53 #include <QTime>
55 #include <QTime>
54
56
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
57 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
56 {
58 {
57 Q_OBJECT
59 Q_OBJECT
58
60
59 public slots:
61 public slots:
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
62 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
63 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
64 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
65 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64
66
65 QObject* parent(QObject* o);
67 QObject* parent(QObject* o);
66 void setParent(QObject* o, QObject* parent);
68 void setParent(QObject* o, QObject* parent);
67
69
68 const QObjectList* children(QObject* o);
70 const QObjectList* children(QObject* o);
69 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
71 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
70 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
72 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
71 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
73 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
72
74
73 bool setProperty(QObject* o, const char* name, const QVariant& value);
75 bool setProperty(QObject* o, const char* name, const QVariant& value);
74 QVariant property(QObject* o, const char* name);
76 QVariant property(QObject* o, const char* name);
75
77
76 double static_Qt_qAbs(double a) { return qAbs(a); }
78 double static_Qt_qAbs(double a) { return qAbs(a); }
77 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
79 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
78 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
80 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
79 // TODO: multi arg qDebug...
81 // TODO: multi arg qDebug...
80 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
82 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
81 // TODO: multi arg qWarning...
83 // TODO: multi arg qWarning...
82 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
84 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
83 // TODO: multi arg qCritical...
85 // TODO: multi arg qCritical...
84 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
86 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
85 // TODO: multi arg qFatal...
87 // TODO: multi arg qFatal...
86 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
88 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
87 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
89 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
88 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
90 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
89 int static_Qt_qRound(double a) { return qRound(a); }
91 int static_Qt_qRound(double a) { return qRound(a); }
90 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
92 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
91 const char* static_Qt_qVersion() { return qVersion(); }
93 const char* static_Qt_qVersion() { return qVersion(); }
92 int static_Qt_qrand() { return qrand(); }
94 int static_Qt_qrand() { return qrand(); }
93 void static_Qt_qsrand(uint a) { qsrand(a); }
95 void static_Qt_qsrand(uint a) { qsrand(a); }
94
96
95 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
97 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
96
98
97 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
99 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
98 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
100 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
99
101
100 private:
102 private:
101 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
103 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
102 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
104 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
103 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
105 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
104 };
106 };
105
107
106
108
107 #endif
109 #endif
@@ -1,136 +1,136
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 PythonQtStdOut.cpp
35 // \file PythonQtStdOut.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 "PythonQtStdOut.h"
42 #include "PythonQtStdOut.h"
43
43
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
45 {
45 {
46 PythonQtStdOutRedirect *self;
46 PythonQtStdOutRedirect *self;
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
48
48
49 self->softspace = 0;
49 self->softspace = 0;
50 self->_cb = NULL;
50 self->_cb = NULL;
51
51
52 return (PyObject *)self;
52 return (PyObject *)self;
53 }
53 }
54
54
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
56 {
56 {
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
58 if (s->_cb) {
58 if (s->_cb) {
59 char *string;
59 char *string;
60 if (!PyArg_ParseTuple(args, "s", &string))
60 if (!PyArg_ParseTuple(args, "s", &string))
61 return NULL;
61 return NULL;
62
62
63 if (s->softspace > 0) {
63 if (s->softspace > 0) {
64 (*s->_cb)(QString(""));
64 (*s->_cb)(QString(""));
65 s->softspace = 0;
65 s->softspace = 0;
66 }
66 }
67
67
68 (*s->_cb)(QString(string));
68 (*s->_cb)(QString(string));
69 }
69 }
70 return Py_BuildValue("");
70 return Py_BuildValue("");
71 }
71 }
72
72
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
74 {
74 {
75 return Py_BuildValue("");
75 return Py_BuildValue("");
76 }
76 }
77
77
78
78
79
79
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
82 "redirect the writing to a callback"},
82 "redirect the writing to a callback"},
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
84 "flush the output, currently not implemented but needed for logging framework"
84 "flush the output, currently not implemented but needed for logging framework"
85 },
85 },
86 {NULL, NULL, 0 , NULL} /* sentinel */
86 {NULL, NULL, 0 , NULL} /* sentinel */
87 };
87 };
88
88
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
90 {const_cast<char*>("softspace"), T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
91 "soft space flag"
91 const_cast<char*>("soft space flag")
92 },
92 },
93 {NULL} /* Sentinel */
93 {NULL} /* Sentinel */
94 };
94 };
95
95
96 PyTypeObject PythonQtStdOutRedirectType = {
96 PyTypeObject PythonQtStdOutRedirectType = {
97 PyObject_HEAD_INIT(NULL)
97 PyObject_HEAD_INIT(NULL)
98 0, /*ob_size*/
98 0, /*ob_size*/
99 "PythonQtStdOutRedirect", /*tp_name*/
99 "PythonQtStdOutRedirect", /*tp_name*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
101 0, /*tp_itemsize*/
101 0, /*tp_itemsize*/
102 0, /*tp_dealloc*/
102 0, /*tp_dealloc*/
103 0, /*tp_print*/
103 0, /*tp_print*/
104 0, /*tp_getattr*/
104 0, /*tp_getattr*/
105 0, /*tp_setattr*/
105 0, /*tp_setattr*/
106 0, /*tp_compare*/
106 0, /*tp_compare*/
107 0, /*tp_repr*/
107 0, /*tp_repr*/
108 0, /*tp_as_number*/
108 0, /*tp_as_number*/
109 0, /*tp_as_sequence*/
109 0, /*tp_as_sequence*/
110 0, /*tp_as_mapping*/
110 0, /*tp_as_mapping*/
111 0, /*tp_hash */
111 0, /*tp_hash */
112 0, /*tp_call*/
112 0, /*tp_call*/
113 0, /*tp_str*/
113 0, /*tp_str*/
114 0, /*tp_getattro*/
114 0, /*tp_getattro*/
115 0, /*tp_setattro*/
115 0, /*tp_setattro*/
116 0, /*tp_as_buffer*/
116 0, /*tp_as_buffer*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
118 "PythonQtStdOutRedirect", /* tp_doc */
118 "PythonQtStdOutRedirect", /* tp_doc */
119 0, /* tp_traverse */
119 0, /* tp_traverse */
120 0, /* tp_clear */
120 0, /* tp_clear */
121 0, /* tp_richcompare */
121 0, /* tp_richcompare */
122 0, /* tp_weaklistoffset */
122 0, /* tp_weaklistoffset */
123 0, /* tp_iter */
123 0, /* tp_iter */
124 0, /* tp_iternext */
124 0, /* tp_iternext */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
126 PythonQtStdOutRedirect_members, /* tp_members */
126 PythonQtStdOutRedirect_members, /* tp_members */
127 0, /* tp_getset */
127 0, /* tp_getset */
128 0, /* tp_base */
128 0, /* tp_base */
129 0, /* tp_dict */
129 0, /* tp_dict */
130 0, /* tp_descr_get */
130 0, /* tp_descr_get */
131 0, /* tp_descr_set */
131 0, /* tp_descr_set */
132 0, /* tp_dictoffset */
132 0, /* tp_dictoffset */
133 0, /* tp_init */
133 0, /* tp_init */
134 0, /* tp_alloc */
134 0, /* tp_alloc */
135 PythonQtStdOutRedirect_new, /* tp_new */
135 PythonQtStdOutRedirect_new, /* tp_new */
136 };
136 };
@@ -1,63 +1,64
1 #ifndef _PYTHONQTSTDOUT_H
1 #ifndef _PYTHONQTSTDOUT_H
2 #define _PYTHONQTSTDOUT_H
2 #define _PYTHONQTSTDOUT_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 PythonQtStdOut.h
38 // \file PythonQtStdOut.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45
45
46 #include <Python.h>
46 #include "PythonQtPythonInclude.h"
47
47 #include "structmember.h"
48 #include "structmember.h"
48 #include <QString>
49 #include <QString>
49
50
50 //! declares the type of the stdout redirection class
51 //! declares the type of the stdout redirection class
51 extern PyTypeObject PythonQtStdOutRedirectType;
52 extern PyTypeObject PythonQtStdOutRedirectType;
52
53
53 //! declares the callback that is called from the write() function
54 //! declares the callback that is called from the write() function
54 typedef void PythonQtOutputChangedCB(const QString& str);
55 typedef void PythonQtOutputChangedCB(const QString& str);
55
56
56 //! declares the stdout redirection class
57 //! declares the stdout redirection class
57 typedef struct {
58 typedef struct {
58 PyObject_HEAD
59 PyObject_HEAD
59 PythonQtOutputChangedCB* _cb;
60 PythonQtOutputChangedCB* _cb;
60 int softspace;
61 int softspace;
61 } PythonQtStdOutRedirect;
62 } PythonQtStdOutRedirect;
62
63
63 #endif
64 #endif
@@ -1,149 +1,150
1 #ifndef _PythonQtScriptingConsole_H
1 #ifndef _PythonQtScriptingConsole_H
2 #define _PythonQtScriptingConsole_H
2 #define _PythonQtScriptingConsole_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 PythonQtScriptingConsole.h
38 // \file PythonQtScriptingConsole.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-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QVariant>
46 #include <QVariant>
47 #include <QTextEdit>
47 #include <QTextEdit>
48
48
49 class QCompleter;
49 class QCompleter;
50
50
51 //-------------------------------------------------------------------------------
51 //-------------------------------------------------------------------------------
52 //! A simple console for python scripting
52 //! A simple console for python scripting
53 class PYTHONQT_EXPORT PythonQtScriptingConsole : public QTextEdit
53 class PYTHONQT_EXPORT PythonQtScriptingConsole : public QTextEdit
54 {
54 {
55 Q_OBJECT
55 Q_OBJECT
56
56
57 public:
57 public:
58 PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags i = 0);
58 PythonQtScriptingConsole(QWidget* parent, const PythonQtObjectPtr& context, Qt::WindowFlags i = 0);
59
59
60 ~PythonQtScriptingConsole();
60 ~PythonQtScriptingConsole();
61
61
62 public slots:
62 public slots:
63 //! execute current line
63 //! execute current line
64 void executeLine(bool storeOnly);
64 void executeLine(bool storeOnly);
65
65
66 //! derived key press event
66 //! derived key press event
67 void keyPressEvent (QKeyEvent * e);
67 void keyPressEvent (QKeyEvent * e);
68
68
69 //! output from console
69 //! output from console
70 void consoleMessage(const QString & message);
70 void consoleMessage(const QString & message);
71
71
72 //! get history
72 //! get history
73 QStringList history() { return _history; }
73 QStringList history() { return _history; }
74
74
75 //! set history
75 //! set history
76 void setHistory(const QStringList& h) { _history = h; _historyPosition = 0; }
76 void setHistory(const QStringList& h) { _history = h; _historyPosition = 0; }
77
77
78 //! clear the console
78 //! clear the console
79 void clear();
79 void clear();
80
80
81 //! overridden to control which characters a user may delete
81 //! overridden to control which characters a user may delete
82 virtual void cut();
82 virtual void cut();
83
83
84 //! output redirection
84 //! output redirection
85 void stdOut(const QString& s);
85 void stdOut(const QString& s);
86 //! output redirection
86 //! output redirection
87 void stdErr(const QString& s);
87 void stdErr(const QString& s);
88
88
89 void insertCompletion(const QString&);
89 void insertCompletion(const QString&);
90
90
91 //! Appends a newline and command prompt at the end of the document.
91 //! Appends a newline and command prompt at the end of the document.
92 void appendCommandPrompt(bool storeOnly = false);
92 void appendCommandPrompt(bool storeOnly = false);
93
93
94 public:
94 public:
95 //! returns true if python cerr had an error
95 //! returns true if python cerr had an error
96 bool hadError() { return _hadError; }
96 bool hadError() { return _hadError; }
97
97
98 //! returns true if python cerr had an error
98 //! returns true if python cerr had an error
99 void clearError() {
99 void clearError() {
100 _hadError = false;
100 _hadError = false;
101 }
101 }
102
102
103 protected:
103 protected:
104 //! handle the pressing of tab
104 //! handle the pressing of tab
105 void handleTabCompletion();
105 void handleTabCompletion();
106
106
107 //! Returns the position of the command prompt
107 //! Returns the position of the command prompt
108 int commandPromptPosition();
108 int commandPromptPosition();
109
109
110 //! Returns if deletion is allowed at the current cursor
110 //! Returns if deletion is allowed at the current cursor
111 //! (with and without selected text)
111 //! (with and without selected text)
112 bool verifySelectionBeforeDeletion();
112 bool verifySelectionBeforeDeletion();
113
113
114 //! Sets the current font
114 //! Sets the current font
115 void setCurrentFont(const QColor& color = QColor(0,0,0), bool bold = false);
115 void setCurrentFont(const QColor& color = QColor(0,0,0), bool bold = false);
116
116
117 //! change the history according to _historyPos
117 //! change the history according to _historyPos
118 void changeHistory();
118 void changeHistory();
119
119
120 //! flush output that was not yet printed
120 //! flush output that was not yet printed
121 void flushStdOut();
121 void flushStdOut();
122
122
123
123
124 private:
124 private:
125 void executeCode(const QString& code);
125 void executeCode(const QString& code);
126
126
127 PythonQtObjectPtr _context;
127 PythonQtObjectPtr _context;
128
128
129 QStringList _history;
129 QStringList _history;
130 int _historyPosition;
130 int _historyPosition;
131
131
132 QString _clickedAnchor;
132 QString _clickedAnchor;
133 QString _storageKey;
133 QString _storageKey;
134 QString _commandPrompt;
134 QString _commandPrompt;
135
135
136 QString _currentMultiLineCode;
136 QString _currentMultiLineCode;
137
137
138 QString _stdOut;
138 QString _stdOut;
139 QString _stdErr;
139 QString _stdErr;
140
140
141 QTextCharFormat _defaultTextCharacterFormat;
141 QTextCharFormat _defaultTextCharacterFormat;
142 QCompleter* _completer;
142 QCompleter* _completer;
143
143
144 bool _hadError;
144 bool _hadError;
145 };
145 };
146
146
147
147
148
148
149 #endif
149 #endif
150
General Comments 0
You need to be logged in to leave comments. Login now