##// END OF EJS Templates
added initial version of foreign wrappers, needs testing...
florianlink -
r167:2184742f9ca8
parent child
Show More
@@ -1,1318 +1,1342
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 "PythonQtStdIn.h"
49 #include "PythonQtStdOut.h"
49 #include "PythonQtStdOut.h"
50 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtVariants.h"
51 #include "PythonQtVariants.h"
52 #include "PythonQtStdDecorators.h"
52 #include "PythonQtStdDecorators.h"
53 #include "PythonQtQFileImporter.h"
53 #include "PythonQtQFileImporter.h"
54 #include <pydebug.h>
54 #include <pydebug.h>
55 #include <vector>
55 #include <vector>
56
56
57 PythonQt* PythonQt::_self = NULL;
57 PythonQt* PythonQt::_self = NULL;
58 int PythonQt::_uniqueModuleCount = 0;
58 int PythonQt::_uniqueModuleCount = 0;
59
59
60 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtCoreBuiltin(PyObject*);
61 void PythonQt_init_QtCoreBuiltin(PyObject*);
62
62
63 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
64 {
64 {
65 if (!_self) {
65 if (!_self) {
66 _self = new PythonQt(flags, pythonQtModuleName);
66 _self = new PythonQt(flags, pythonQtModuleName);
67
67
68 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
69 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69 qRegisterMetaType<QList<QObject*> >("QList<void*>");
70
70
71 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(int);
72 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(float);
73 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(double);
74 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(qint32);
75 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(quint32);
76 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(qint64);
77 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 PythonQtRegisterToolClassesTemplateConverter(quint64);
78 // TODO: which other POD types should be available for QList etc.
78 // TODO: which other POD types should be available for QList etc.
79
79
80 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
81
81
82 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtCoreBuiltin(NULL);
83 PythonQt_init_QtGuiBuiltin(NULL);
83 PythonQt_init_QtGuiBuiltin(NULL);
84
84
85 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
86 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QDate);
87 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QTime);
88 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
89 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QUrl);
90 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QLocale);
91 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRect);
92 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QRectF);
93 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSize);
94 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
95 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLine);
96 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QLineF);
97 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPoint);
98 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QPointF);
99 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
100
100
101 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QFont);
102 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
103 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QBrush);
104 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QColor);
105 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QPalette);
106 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QIcon);
107 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QImage);
108 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
109 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QRegion);
110 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
111 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QCursor);
112 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
113 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
114 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QPen);
115 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
116 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
117 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
118
118
119
119
120 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
121 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
122 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
123 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"
124 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
125 for (unsigned int i = 0;i<16; i++) {
125 for (unsigned int i = 0;i<16; i++) {
126 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
127 if (obj) {
127 if (obj) {
128 PyModule_AddObject(pack, names[i], obj);
128 PyModule_AddObject(pack, names[i], obj);
129 Py_INCREF(obj);
129 Py_INCREF(obj);
130 PyModule_AddObject(pack2, names[i], obj);
130 PyModule_AddObject(pack2, names[i], obj);
131 } else {
131 } else {
132 std::cerr << "method not found " << names[i];
132 std::cerr << "method not found " << names[i];
133 }
133 }
134 }
134 }
135 }
135 }
136 }
136 }
137
137
138 void PythonQt::cleanup()
138 void PythonQt::cleanup()
139 {
139 {
140 if (_self) {
140 if (_self) {
141 delete _self;
141 delete _self;
142 _self = NULL;
142 _self = NULL;
143 }
143 }
144 }
144 }
145
145
146 PythonQt* PythonQt::self() { return _self; }
146 PythonQt* PythonQt::self() { return _self; }
147
147
148 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
148 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
149 {
149 {
150 _p = new PythonQtPrivate;
150 _p = new PythonQtPrivate;
151 _p->_initFlags = flags;
151 _p->_initFlags = flags;
152
152
153 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
153 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
154
154
155 if ((flags & PythonAlreadyInitialized) == 0) {
155 if ((flags & PythonAlreadyInitialized) == 0) {
156 Py_SetProgramName(const_cast<char*>("PythonQt"));
156 Py_SetProgramName(const_cast<char*>("PythonQt"));
157 if (flags & IgnoreSiteModule) {
157 if (flags & IgnoreSiteModule) {
158 // this prevents the automatic importing of Python site files
158 // this prevents the automatic importing of Python site files
159 Py_NoSiteFlag = 1;
159 Py_NoSiteFlag = 1;
160 }
160 }
161 Py_Initialize();
161 Py_Initialize();
162 }
162 }
163
163
164 // add our own python object types for qt object slots
164 // add our own python object types for qt object slots
165 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
165 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
166 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;
167 }
167 }
168 Py_INCREF(&PythonQtSlotFunction_Type);
168 Py_INCREF(&PythonQtSlotFunction_Type);
169
169
170 // 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
171 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
171 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
172 // add our own python object types for classes
172 // add our own python object types for classes
173 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
173 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
174 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;
175 }
175 }
176 Py_INCREF(&PythonQtClassWrapper_Type);
176 Py_INCREF(&PythonQtClassWrapper_Type);
177
177
178 // add our own python object types for CPP instances
178 // add our own python object types for CPP instances
179 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
179 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
180 PythonQt::handleError();
180 PythonQt::handleError();
181 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;
182 }
182 }
183 Py_INCREF(&PythonQtInstanceWrapper_Type);
183 Py_INCREF(&PythonQtInstanceWrapper_Type);
184
184
185 // add our own python object types for redirection of stdout
185 // add our own python object types for redirection of stdout
186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
187 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
187 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 }
188 }
189 Py_INCREF(&PythonQtStdOutRedirectType);
189 Py_INCREF(&PythonQtStdOutRedirectType);
190
190
191 // add our own python object types for redirection of stdin
191 // add our own python object types for redirection of stdin
192 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
192 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
193 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
193 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
194 }
194 }
195 Py_INCREF(&PythonQtStdInRedirectType);
195 Py_INCREF(&PythonQtStdInRedirectType);
196
196
197 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
197 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
198
198
199 _p->setupSharedLibrarySuffixes();
199 _p->setupSharedLibrarySuffixes();
200
200
201 }
201 }
202
202
203 PythonQt::~PythonQt() {
203 PythonQt::~PythonQt() {
204 delete _p;
204 delete _p;
205 _p = NULL;
205 _p = NULL;
206 }
206 }
207
207
208 PythonQtPrivate::~PythonQtPrivate() {
208 PythonQtPrivate::~PythonQtPrivate() {
209 delete _defaultImporter;
209 delete _defaultImporter;
210 _defaultImporter = NULL;
210 _defaultImporter = NULL;
211
211
212 {
212 {
213 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
213 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
214 while (i.hasNext()) {
214 while (i.hasNext()) {
215 delete i.next().value();
215 delete i.next().value();
216 }
216 }
217 }
217 }
218 PythonQtConv::global_valueStorage.clear();
218 PythonQtConv::global_valueStorage.clear();
219 PythonQtConv::global_ptrStorage.clear();
219 PythonQtConv::global_ptrStorage.clear();
220 PythonQtConv::global_variantStorage.clear();
220 PythonQtConv::global_variantStorage.clear();
221
221
222 PythonQtMethodInfo::cleanupCachedMethodInfos();
222 PythonQtMethodInfo::cleanupCachedMethodInfos();
223 }
223 }
224
224
225 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
225 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
226 {
226 {
227 if (!callback)
227 if (!callback)
228 {
228 {
229 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
229 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
230 return;
230 return;
231 }
231 }
232
232
233 PythonQtObjectPtr sys;
233 PythonQtObjectPtr sys;
234 PythonQtObjectPtr in;
234 PythonQtObjectPtr in;
235 sys.setNewRef(PyImport_ImportModule("sys"));
235 sys.setNewRef(PyImport_ImportModule("sys"));
236
236
237 // Backup original 'sys.stdin' if not yet done
237 // Backup original 'sys.stdin' if not yet done
238 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
238 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
239 "sys.pythonqt_original_stdin = sys.stdin");
239 "sys.pythonqt_original_stdin = sys.stdin");
240
240
241 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
241 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
242 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
242 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
243 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
243 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
244 // replace the built in file objects with our own objects
244 // replace the built in file objects with our own objects
245 PyModule_AddObject(sys, "stdin", in);
245 PyModule_AddObject(sys, "stdin", in);
246
246
247 // Backup custom 'stdin' into 'pythonqt_stdin'
247 // Backup custom 'stdin' into 'pythonqt_stdin'
248 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
248 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
249 }
249 }
250
250
251 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
251 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
252 {
252 {
253 if (enabled)
253 if (enabled)
254 {
254 {
255 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
255 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
256 "sys.stdin = sys.pythonqt_stdin");
256 "sys.stdin = sys.pythonqt_stdin");
257 }
257 }
258 else
258 else
259 {
259 {
260 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
260 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
261 "sys.stdin = sys.pythonqt_original_stdin");
261 "sys.stdin = sys.pythonqt_original_stdin");
262 }
262 }
263 }
263 }
264
264
265 PythonQtImportFileInterface* PythonQt::importInterface()
265 PythonQtImportFileInterface* PythonQt::importInterface()
266 {
266 {
267 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
267 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
268 }
268 }
269
269
270 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
270 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
271 {
271 {
272 if (_self->_p->_noLongerWrappedCB) {
272 if (_self->_p->_noLongerWrappedCB) {
273 (*_self->_p->_noLongerWrappedCB)(o);
273 (*_self->_p->_noLongerWrappedCB)(o);
274 };
274 };
275 }
275 }
276
276
277 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)
278 {
278 {
279 _p->registerClass(metaobject, package, wrapperCreator, shell);
279 _p->registerClass(metaobject, package, wrapperCreator, shell);
280 }
280 }
281
281
282 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)
283 {
283 {
284 // we register all classes in the hierarchy
284 // we register all classes in the hierarchy
285 const QMetaObject* m = metaobject;
285 const QMetaObject* m = metaobject;
286 bool first = true;
286 bool first = true;
287 while (m) {
287 while (m) {
288 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
288 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
289 if (!info->pythonQtClassWrapper()) {
289 if (!info->pythonQtClassWrapper()) {
290 info->setTypeSlots(typeSlots);
290 info->setTypeSlots(typeSlots);
291 info->setupQObject(m);
291 info->setupQObject(m);
292 createPythonQtClassWrapper(info, package, module);
292 createPythonQtClassWrapper(info, package, module);
293 if (m->superClass()) {
293 if (m->superClass()) {
294 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
294 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
295 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
295 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
296 }
296 }
297 } else if (first && module) {
297 } else if (first && module) {
298 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
298 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
299 // since it might have been placed into "private" earlier on.
299 // since it might have been placed into "private" earlier on.
300 // If the wrapper was already added to module before, it is just readded, which does no harm.
300 // If the wrapper was already added to module before, it is just readded, which does no harm.
301 PyObject* classWrapper = info->pythonQtClassWrapper();
301 PyObject* classWrapper = info->pythonQtClassWrapper();
302 // AddObject steals a reference, so we need to INCREF
302 // AddObject steals a reference, so we need to INCREF
303 Py_INCREF(classWrapper);
303 Py_INCREF(classWrapper);
304 PyModule_AddObject(module, info->className(), classWrapper);
304 PyModule_AddObject(module, info->className(), classWrapper);
305 }
305 }
306 if (first) {
306 if (first) {
307 first = false;
307 first = false;
308 if (wrapperCreator) {
308 if (wrapperCreator) {
309 info->setDecoratorProvider(wrapperCreator);
309 info->setDecoratorProvider(wrapperCreator);
310 }
310 }
311 if (shell) {
311 if (shell) {
312 info->setShellSetInstanceWrapperCB(shell);
312 info->setShellSetInstanceWrapperCB(shell);
313 }
313 }
314 }
314 }
315 m = m->superClass();
315 m = m->superClass();
316 }
316 }
317 }
317 }
318
318
319 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
319 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
320 {
320 {
321 PyObject* pack = module?module:packageByName(package);
321 PyObject* pack = module?module:packageByName(package);
322 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
322 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
323 PyModule_AddObject(pack, info->className(), pyobj);
323 PyModule_AddObject(pack, info->className(), pyobj);
324 if (!module && package && strncmp(package,"Qt",2)==0) {
324 if (!module && package && strncmp(package,"Qt",2)==0) {
325 // 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...
326 Py_INCREF(pyobj);
326 Py_INCREF(pyobj);
327 // put all qt objects into Qt as well
327 // put all qt objects into Qt as well
328 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
328 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
329 }
329 }
330 info->setPythonQtClassWrapper(pyobj);
330 info->setPythonQtClassWrapper(pyobj);
331 }
331 }
332
332
333 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
333 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
334 {
334 {
335 if (!obj) {
335 if (!obj) {
336 Py_INCREF(Py_None);
336 Py_INCREF(Py_None);
337 return Py_None;
337 return Py_None;
338 }
338 }
339 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
339 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
340 if (!wrap) {
340 if (!wrap) {
341 // smuggling it in...
341 // smuggling it in...
342 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
342 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
343 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
343 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
344 registerClass(obj->metaObject());
344 registerClass(obj->metaObject());
345 classInfo = _knownClassInfos.value(obj->metaObject()->className());
345 classInfo = _knownClassInfos.value(obj->metaObject()->className());
346 }
346 }
347 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
347 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
348 // 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());
349 } else {
349 } else {
350 Py_INCREF(wrap);
350 Py_INCREF(wrap);
351 // 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());
352 }
352 }
353 return (PyObject*)wrap;
353 return (PyObject*)wrap;
354 }
354 }
355
355
356 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
356 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
357 {
357 {
358 if (!ptr) {
358 if (!ptr) {
359 Py_INCREF(Py_None);
359 Py_INCREF(Py_None);
360 return Py_None;
360 return Py_None;
361 }
361 }
362
362
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
364 if (!wrap) {
364 if (!wrap) {
365 PythonQtClassInfo* info = _knownClassInfos.value(name);
365 PythonQtClassInfo* info = _knownClassInfos.value(name);
366 if (!info) {
366 if (!info) {
367 // maybe it is a PyObject, which we can return directly
367 // maybe it is a PyObject, which we can return directly
368 if (name == "PyObject") {
368 if (name == "PyObject") {
369 PyObject* p = (PyObject*)ptr;
369 PyObject* p = (PyObject*)ptr;
370 Py_INCREF(p);
370 Py_INCREF(p);
371 return p;
371 return p;
372 }
372 }
373
373
374 // 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:
375 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
375 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
376 // yes, we know it, so we can convert to QObject
376 // yes, we know it, so we can convert to QObject
377 QObject* qptr = (QObject*)ptr;
377 QObject* qptr = (QObject*)ptr;
378 registerClass(qptr->metaObject());
378 registerClass(qptr->metaObject());
379 info = _knownClassInfos.value(qptr->metaObject()->className());
379 info = _knownClassInfos.value(qptr->metaObject()->className());
380 }
380 }
381 }
381 }
382 if (info && info->isQObject()) {
382 if (info && info->isQObject()) {
383 QObject* qptr = (QObject*)ptr;
383 QObject* qptr = (QObject*)ptr;
384 // if the object is a derived object, we want to switch the class info to the one of the derived class:
384 // if the object is a derived object, we want to switch the class info to the one of the derived class:
385 if (name!=(qptr->metaObject()->className())) {
385 if (name!=(qptr->metaObject()->className())) {
386 registerClass(qptr->metaObject());
386 registerClass(qptr->metaObject());
387 info = _knownClassInfos.value(qptr->metaObject()->className());
387 info = _knownClassInfos.value(qptr->metaObject()->className());
388 }
388 }
389 wrap = createNewPythonQtInstanceWrapper(qptr, info);
389 wrap = createNewPythonQtInstanceWrapper(qptr, info);
390 // 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());
391 return (PyObject*)wrap;
391 return (PyObject*)wrap;
392 }
392 }
393
393
394 // not a known QObject, try to wrap via foreign wrapper factories
395 PyObject* foreignWrapper = NULL;
396 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
397 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
398 if (foreignWrapper) {
399 return foreignWrapper;
400 }
401 }
402
394 // not a known QObject, so try our wrapper factory:
403 // not a known QObject, so try our wrapper factory:
395 QObject* wrapper = NULL;
404 QObject* wrapper = NULL;
396 for (int i=0; i<_cppWrapperFactories.size(); i++) {
405 for (int i=0; i<_cppWrapperFactories.size(); i++) {
397 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
406 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
398 if (wrapper) {
407 if (wrapper) {
399 break;
408 break;
400 }
409 }
401 }
410 }
402
411
403 if (info) {
412 if (info) {
404 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
413 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
405 ptr = info->castDownIfPossible(ptr, &info);
414 ptr = info->castDownIfPossible(ptr, &info);
406 }
415 }
407
416
408 if (!info || info->pythonQtClassWrapper()==NULL) {
417 if (!info || info->pythonQtClassWrapper()==NULL) {
409 // still unknown, register as CPP class
418 // still unknown, register as CPP class
410 registerCPPClass(name.constData());
419 registerCPPClass(name.constData());
411 info = _knownClassInfos.value(name);
420 info = _knownClassInfos.value(name);
412 }
421 }
413 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
422 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
414 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
423 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
415 info->setMetaObject(wrapper->metaObject());
424 info->setMetaObject(wrapper->metaObject());
416 }
425 }
417
426
418 // TODO XXX: delegate wrapping via CB here (pass name and ptr)
419
420 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
427 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
421 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
428 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
422 } else {
429 } else {
423 Py_INCREF(wrap);
430 Py_INCREF(wrap);
424 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
431 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
425 }
432 }
426 return (PyObject*)wrap;
433 return (PyObject*)wrap;
427 }
434 }
428
435
429 PyObject* PythonQtPrivate::dummyTuple() {
436 PyObject* PythonQtPrivate::dummyTuple() {
430 static PyObject* dummyTuple = NULL;
437 static PyObject* dummyTuple = NULL;
431 if (dummyTuple==NULL) {
438 if (dummyTuple==NULL) {
432 dummyTuple = PyTuple_New(1);
439 dummyTuple = PyTuple_New(1);
433 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
440 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
434 }
441 }
435 return dummyTuple;
442 return dummyTuple;
436 }
443 }
437
444
438
445
439 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
446 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
440 // call the associated class type to create a new instance...
447 // call the associated class type to create a new instance...
441 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
448 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
442
449
443 result->setQObject(obj);
450 result->setQObject(obj);
444 result->_wrappedPtr = wrappedPtr;
451 result->_wrappedPtr = wrappedPtr;
445 result->_ownedByPythonQt = false;
452 result->_ownedByPythonQt = false;
446 result->_useQMetaTypeDestroy = false;
453 result->_useQMetaTypeDestroy = false;
447
454
448 if (wrappedPtr) {
455 if (wrappedPtr) {
449 _wrappedObjects.insert(wrappedPtr, result);
456 _wrappedObjects.insert(wrappedPtr, result);
450 } else {
457 } else {
451 _wrappedObjects.insert(obj, result);
458 _wrappedObjects.insert(obj, result);
452 if (obj->parent()== NULL && _wrappedCB) {
459 if (obj->parent()== NULL && _wrappedCB) {
453 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
460 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
454 (*_wrappedCB)(obj);
461 (*_wrappedCB)(obj);
455 }
462 }
456 }
463 }
457 return result;
464 return result;
458 }
465 }
459
466
460 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
467 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
461 PythonQtClassWrapper* result;
468 PythonQtClassWrapper* result;
462
469
463 PyObject* className = PyString_FromString(info->className());
470 PyObject* className = PyString_FromString(info->className());
464
471
465 PyObject* baseClasses = PyTuple_New(1);
472 PyObject* baseClasses = PyTuple_New(1);
466 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
473 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
467
474
468 PyObject* typeDict = PyDict_New();
475 PyObject* typeDict = PyDict_New();
469 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
476 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
470 PyDict_SetItemString(typeDict, "__module__", moduleName);
477 PyDict_SetItemString(typeDict, "__module__", moduleName);
471
478
472 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
479 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
473
480
474 // set the class info so that PythonQtClassWrapper_new can read it
481 // set the class info so that PythonQtClassWrapper_new can read it
475 _currentClassInfoForClassWrapperCreation = info;
482 _currentClassInfoForClassWrapperCreation = info;
476 // create the new type object by calling the type
483 // create the new type object by calling the type
477 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
484 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
478
485
479 Py_DECREF(baseClasses);
486 Py_DECREF(baseClasses);
480 Py_DECREF(typeDict);
487 Py_DECREF(typeDict);
481 Py_DECREF(args);
488 Py_DECREF(args);
482 Py_DECREF(className);
489 Py_DECREF(className);
483
490
484 return result;
491 return result;
485 }
492 }
486
493
487 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
494 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
488 {
495 {
489 PyObject* args = Py_BuildValue("(i)", enumValue);
496 PyObject* args = Py_BuildValue("(i)", enumValue);
490 PyObject* result = PyObject_Call(enumType, args, NULL);
497 PyObject* result = PyObject_Call(enumType, args, NULL);
491 Py_DECREF(args);
498 Py_DECREF(args);
492 return result;
499 return result;
493 }
500 }
494
501
495 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
502 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
496 PyObject* result;
503 PyObject* result;
497
504
498 PyObject* className = PyString_FromString(enumName);
505 PyObject* className = PyString_FromString(enumName);
499
506
500 PyObject* baseClasses = PyTuple_New(1);
507 PyObject* baseClasses = PyTuple_New(1);
501 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
508 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
502
509
503 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
510 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
504 PyObject* typeDict = PyDict_New();
511 PyObject* typeDict = PyDict_New();
505 PyDict_SetItemString(typeDict, "__module__", module);
512 PyDict_SetItemString(typeDict, "__module__", module);
506
513
507 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
514 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
508
515
509 // create the new int derived type object by calling the core type
516 // create the new int derived type object by calling the core type
510 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
517 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
511
518
512 Py_DECREF(baseClasses);
519 Py_DECREF(baseClasses);
513 Py_DECREF(typeDict);
520 Py_DECREF(typeDict);
514 Py_DECREF(args);
521 Py_DECREF(args);
515 Py_DECREF(className);
522 Py_DECREF(className);
516
523
517 return result;
524 return result;
518 }
525 }
519
526
520 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
527 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
521 {
528 {
522 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
529 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
523 if (!r) {
530 if (!r) {
524 r = new PythonQtSignalReceiver(obj);
531 r = new PythonQtSignalReceiver(obj);
525 _p->_signalReceivers.insert(obj, r);
532 _p->_signalReceivers.insert(obj, r);
526 }
533 }
527 return r;
534 return r;
528 }
535 }
529
536
530 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
537 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
531 {
538 {
532 bool flag = false;
539 bool flag = false;
533 PythonQtObjectPtr callable = lookupCallable(module, objectname);
540 PythonQtObjectPtr callable = lookupCallable(module, objectname);
534 if (callable) {
541 if (callable) {
535 PythonQtSignalReceiver* r = getSignalReceiver(obj);
542 PythonQtSignalReceiver* r = getSignalReceiver(obj);
536 flag = r->addSignalHandler(signal, callable);
543 flag = r->addSignalHandler(signal, callable);
537 if (!flag) {
544 if (!flag) {
538 // signal not found
545 // signal not found
539 }
546 }
540 } else {
547 } else {
541 // callable not found
548 // callable not found
542 }
549 }
543 return flag;
550 return flag;
544 }
551 }
545
552
546 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
553 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
547 {
554 {
548 bool flag = false;
555 bool flag = false;
549 PythonQtSignalReceiver* r = getSignalReceiver(obj);
556 PythonQtSignalReceiver* r = getSignalReceiver(obj);
550 if (r) {
557 if (r) {
551 flag = r->addSignalHandler(signal, receiver);
558 flag = r->addSignalHandler(signal, receiver);
552 }
559 }
553 return flag;
560 return flag;
554 }
561 }
555
562
556 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
563 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
557 {
564 {
558 bool flag = false;
565 bool flag = false;
559 PythonQtObjectPtr callable = lookupCallable(module, objectname);
566 PythonQtObjectPtr callable = lookupCallable(module, objectname);
560 if (callable) {
567 if (callable) {
561 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
568 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
562 if (r) {
569 if (r) {
563 flag = r->removeSignalHandler(signal, callable);
570 flag = r->removeSignalHandler(signal, callable);
564 }
571 }
565 } else {
572 } else {
566 // callable not found
573 // callable not found
567 }
574 }
568 return flag;
575 return flag;
569 }
576 }
570
577
571 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
578 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
572 {
579 {
573 bool flag = false;
580 bool flag = false;
574 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
581 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
575 if (r) {
582 if (r) {
576 flag = r->removeSignalHandler(signal, receiver);
583 flag = r->removeSignalHandler(signal, receiver);
577 }
584 }
578 return flag;
585 return flag;
579 }
586 }
580
587
581 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
588 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
582 {
589 {
583 PythonQtObjectPtr p = lookupObject(module, name);
590 PythonQtObjectPtr p = lookupObject(module, name);
584 if (p) {
591 if (p) {
585 if (PyCallable_Check(p)) {
592 if (PyCallable_Check(p)) {
586 return p;
593 return p;
587 }
594 }
588 }
595 }
589 PyErr_Clear();
596 PyErr_Clear();
590 return NULL;
597 return NULL;
591 }
598 }
592
599
593 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
600 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
594 {
601 {
595 QStringList l = name.split('.');
602 QStringList l = name.split('.');
596 PythonQtObjectPtr p = module;
603 PythonQtObjectPtr p = module;
597 PythonQtObjectPtr prev;
604 PythonQtObjectPtr prev;
598 QString s;
605 QString s;
599 QByteArray b;
606 QByteArray b;
600 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
607 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
601 prev = p;
608 prev = p;
602 b = (*i).toLatin1();
609 b = (*i).toLatin1();
603 if (PyDict_Check(p)) {
610 if (PyDict_Check(p)) {
604 p = PyDict_GetItemString(p, b.data());
611 p = PyDict_GetItemString(p, b.data());
605 } else {
612 } else {
606 p.setNewRef(PyObject_GetAttrString(p, b.data()));
613 p.setNewRef(PyObject_GetAttrString(p, b.data()));
607 }
614 }
608 }
615 }
609 PyErr_Clear();
616 PyErr_Clear();
610 return p;
617 return p;
611 }
618 }
612
619
613 PythonQtObjectPtr PythonQt::getMainModule() {
620 PythonQtObjectPtr PythonQt::getMainModule() {
614 //both borrowed
621 //both borrowed
615 PythonQtObjectPtr dict = PyImport_GetModuleDict();
622 PythonQtObjectPtr dict = PyImport_GetModuleDict();
616 return PyDict_GetItemString(dict, "__main__");
623 return PyDict_GetItemString(dict, "__main__");
617 }
624 }
618
625
619 PythonQtObjectPtr PythonQt::importModule(const QString& name)
626 PythonQtObjectPtr PythonQt::importModule(const QString& name)
620 {
627 {
621 PythonQtObjectPtr mod;
628 PythonQtObjectPtr mod;
622 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
629 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
623 return mod;
630 return mod;
624 }
631 }
625
632
626
633
627 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
634 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
628 QVariant result;
635 QVariant result;
629 if (pycode) {
636 if (pycode) {
630 PyObject* dict = NULL;
637 PyObject* dict = NULL;
631 if (PyModule_Check(object)) {
638 if (PyModule_Check(object)) {
632 dict = PyModule_GetDict(object);
639 dict = PyModule_GetDict(object);
633 } else if (PyDict_Check(object)) {
640 } else if (PyDict_Check(object)) {
634 dict = object;
641 dict = object;
635 }
642 }
636 PyObject* r = NULL;
643 PyObject* r = NULL;
637 if (dict) {
644 if (dict) {
638 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
645 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
639 }
646 }
640 if (r) {
647 if (r) {
641 result = PythonQtConv::PyObjToQVariant(r);
648 result = PythonQtConv::PyObjToQVariant(r);
642 Py_DECREF(r);
649 Py_DECREF(r);
643 } else {
650 } else {
644 handleError();
651 handleError();
645 }
652 }
646 } else {
653 } else {
647 handleError();
654 handleError();
648 }
655 }
649 return result;
656 return result;
650 }
657 }
651
658
652 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
659 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
653 {
660 {
654 QVariant result;
661 QVariant result;
655 PythonQtObjectPtr p;
662 PythonQtObjectPtr p;
656 PyObject* dict = NULL;
663 PyObject* dict = NULL;
657 if (PyModule_Check(object)) {
664 if (PyModule_Check(object)) {
658 dict = PyModule_GetDict(object);
665 dict = PyModule_GetDict(object);
659 } else if (PyDict_Check(object)) {
666 } else if (PyDict_Check(object)) {
660 dict = object;
667 dict = object;
661 }
668 }
662 if (dict) {
669 if (dict) {
663 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
670 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
664 }
671 }
665 if (p) {
672 if (p) {
666 result = PythonQtConv::PyObjToQVariant(p);
673 result = PythonQtConv::PyObjToQVariant(p);
667 } else {
674 } else {
668 handleError();
675 handleError();
669 }
676 }
670 return result;
677 return result;
671 }
678 }
672
679
673 void PythonQt::evalFile(PyObject* module, const QString& filename)
680 void PythonQt::evalFile(PyObject* module, const QString& filename)
674 {
681 {
675 PythonQtObjectPtr code = parseFile(filename);
682 PythonQtObjectPtr code = parseFile(filename);
676 if (code) {
683 if (code) {
677 evalCode(module, code);
684 evalCode(module, code);
678 } else {
685 } else {
679 handleError();
686 handleError();
680 }
687 }
681 }
688 }
682
689
683 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
690 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
684 {
691 {
685 PythonQtObjectPtr p;
692 PythonQtObjectPtr p;
686 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
693 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
687 if (!p) {
694 if (!p) {
688 handleError();
695 handleError();
689 }
696 }
690 return p;
697 return p;
691 }
698 }
692
699
693 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
700 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
694 {
701 {
695 PythonQtObjectPtr code = parseFile(filename);
702 PythonQtObjectPtr code = parseFile(filename);
696 PythonQtObjectPtr module = _p->createModule(name, code);
703 PythonQtObjectPtr module = _p->createModule(name, code);
697 return module;
704 return module;
698 }
705 }
699
706
700 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
707 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
701 {
708 {
702 PyErr_Clear();
709 PyErr_Clear();
703 QString scriptCode = script;
710 QString scriptCode = script;
704 if (scriptCode.isEmpty()) {
711 if (scriptCode.isEmpty()) {
705 // we always need at least a linefeed
712 // we always need at least a linefeed
706 scriptCode = "\n";
713 scriptCode = "\n";
707 }
714 }
708 PythonQtObjectPtr pycode;
715 PythonQtObjectPtr pycode;
709 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
716 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
710 PythonQtObjectPtr module = _p->createModule(name, pycode);
717 PythonQtObjectPtr module = _p->createModule(name, pycode);
711 return module;
718 return module;
712 }
719 }
713
720
714 PythonQtObjectPtr PythonQt::createUniqueModule()
721 PythonQtObjectPtr PythonQt::createUniqueModule()
715 {
722 {
716 static QString pyQtStr("PythonQt_module");
723 static QString pyQtStr("PythonQt_module");
717 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
724 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
718 return createModuleFromScript(moduleName);
725 return createModuleFromScript(moduleName);
719 }
726 }
720
727
721 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
728 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
722 {
729 {
723 if (PyModule_Check(object)) {
730 if (PyModule_Check(object)) {
724 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
731 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
725 } else if (PyDict_Check(object)) {
732 } else if (PyDict_Check(object)) {
726 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
733 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
727 } else {
734 } else {
728 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
735 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
729 }
736 }
730 }
737 }
731
738
732 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
739 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
733 {
740 {
734 if (PyModule_Check(object)) {
741 if (PyModule_Check(object)) {
735 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
742 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
736 } else if (PyDict_Check(object)) {
743 } else if (PyDict_Check(object)) {
737 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
744 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
738 } else {
745 } else {
739 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
746 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
740 }
747 }
741 }
748 }
742
749
743 void PythonQt::removeVariable(PyObject* object, const QString& name)
750 void PythonQt::removeVariable(PyObject* object, const QString& name)
744 {
751 {
745 if (PyDict_Check(object)) {
752 if (PyDict_Check(object)) {
746 PyDict_DelItemString(object, name.toLatin1().data());
753 PyDict_DelItemString(object, name.toLatin1().data());
747 } else {
754 } else {
748 PyObject_DelAttrString(object, name.toLatin1().data());
755 PyObject_DelAttrString(object, name.toLatin1().data());
749 }
756 }
750 }
757 }
751
758
752 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
759 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
753 {
760 {
754 QVariant result;
761 QVariant result;
755 PythonQtObjectPtr obj = lookupObject(object, objectname);
762 PythonQtObjectPtr obj = lookupObject(object, objectname);
756 if (obj) {
763 if (obj) {
757 result = PythonQtConv::PyObjToQVariant(obj);
764 result = PythonQtConv::PyObjToQVariant(obj);
758 }
765 }
759 return result;
766 return result;
760 }
767 }
761
768
762 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
769 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
763 {
770 {
764 QStringList results;
771 QStringList results;
765
772
766 PythonQtObjectPtr object;
773 PythonQtObjectPtr object;
767 if (objectname.isEmpty()) {
774 if (objectname.isEmpty()) {
768 object = module;
775 object = module;
769 } else {
776 } else {
770 object = lookupObject(module, objectname);
777 object = lookupObject(module, objectname);
771 if (!object && type == CallOverloads) {
778 if (!object && type == CallOverloads) {
772 PyObject* dict = lookupObject(module, "__builtins__");
779 PyObject* dict = lookupObject(module, "__builtins__");
773 if (dict) {
780 if (dict) {
774 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
781 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
775 }
782 }
776 }
783 }
777 }
784 }
778
785
779 if (object) {
786 if (object) {
780 if (type == CallOverloads) {
787 if (type == CallOverloads) {
781 if (PythonQtSlotFunction_Check(object)) {
788 if (PythonQtSlotFunction_Check(object)) {
782 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
789 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
783 PythonQtSlotInfo* info = o->m_ml;
790 PythonQtSlotInfo* info = o->m_ml;
784
791
785 while (info) {
792 while (info) {
786 results << info->fullSignature();
793 results << info->fullSignature();
787 info = info->nextInfo();
794 info = info->nextInfo();
788 }
795 }
789 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
796 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
790 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
797 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
791 PythonQtSlotInfo* info = o->classInfo()->constructors();
798 PythonQtSlotInfo* info = o->classInfo()->constructors();
792
799
793 while (info) {
800 while (info) {
794 results << info->fullSignature();
801 results << info->fullSignature();
795 info = info->nextInfo();
802 info = info->nextInfo();
796 }
803 }
797 } else {
804 } else {
798 //TODO: use pydoc!
805 //TODO: use pydoc!
799 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
806 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
800 if (doc) {
807 if (doc) {
801 results << PyString_AsString(doc);
808 results << PyString_AsString(doc);
802 Py_DECREF(doc);
809 Py_DECREF(doc);
803 }
810 }
804 }
811 }
805 } else {
812 } else {
806 PyObject* keys = NULL;
813 PyObject* keys = NULL;
807 bool isDict = false;
814 bool isDict = false;
808 if (PyDict_Check(object)) {
815 if (PyDict_Check(object)) {
809 keys = PyDict_Keys(object);
816 keys = PyDict_Keys(object);
810 isDict = true;
817 isDict = true;
811 } else {
818 } else {
812 keys = PyObject_Dir(object);
819 keys = PyObject_Dir(object);
813 }
820 }
814 if (keys) {
821 if (keys) {
815 int count = PyList_Size(keys);
822 int count = PyList_Size(keys);
816 PyObject* key;
823 PyObject* key;
817 PyObject* value;
824 PyObject* value;
818 QString keystr;
825 QString keystr;
819 for (int i = 0;i<count;i++) {
826 for (int i = 0;i<count;i++) {
820 key = PyList_GetItem(keys,i);
827 key = PyList_GetItem(keys,i);
821 if (isDict) {
828 if (isDict) {
822 value = PyDict_GetItem(object, key);
829 value = PyDict_GetItem(object, key);
823 Py_INCREF(value);
830 Py_INCREF(value);
824 } else {
831 } else {
825 value = PyObject_GetAttr(object, key);
832 value = PyObject_GetAttr(object, key);
826 }
833 }
827 if (!value) continue;
834 if (!value) continue;
828 keystr = PyString_AsString(key);
835 keystr = PyString_AsString(key);
829 static const QString underscoreStr("__tmp");
836 static const QString underscoreStr("__tmp");
830 if (!keystr.startsWith(underscoreStr)) {
837 if (!keystr.startsWith(underscoreStr)) {
831 switch (type) {
838 switch (type) {
832 case Anything:
839 case Anything:
833 results << keystr;
840 results << keystr;
834 break;
841 break;
835 case Class:
842 case Class:
836 if (value->ob_type == &PyClass_Type) {
843 if (value->ob_type == &PyClass_Type) {
837 results << keystr;
844 results << keystr;
838 }
845 }
839 break;
846 break;
840 case Variable:
847 case Variable:
841 if (value->ob_type != &PyClass_Type
848 if (value->ob_type != &PyClass_Type
842 && value->ob_type != &PyCFunction_Type
849 && value->ob_type != &PyCFunction_Type
843 && value->ob_type != &PyFunction_Type
850 && value->ob_type != &PyFunction_Type
844 && value->ob_type != &PyModule_Type
851 && value->ob_type != &PyModule_Type
845 ) {
852 ) {
846 results << keystr;
853 results << keystr;
847 }
854 }
848 break;
855 break;
849 case Function:
856 case Function:
850 if (value->ob_type == &PyFunction_Type ||
857 if (value->ob_type == &PyFunction_Type ||
851 value->ob_type == &PyMethod_Type
858 value->ob_type == &PyMethod_Type
852 ) {
859 ) {
853 results << keystr;
860 results << keystr;
854 }
861 }
855 break;
862 break;
856 case Module:
863 case Module:
857 if (value->ob_type == &PyModule_Type) {
864 if (value->ob_type == &PyModule_Type) {
858 results << keystr;
865 results << keystr;
859 }
866 }
860 break;
867 break;
861 default:
868 default:
862 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
869 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
863 }
870 }
864 }
871 }
865 Py_DECREF(value);
872 Py_DECREF(value);
866 }
873 }
867 Py_DECREF(keys);
874 Py_DECREF(keys);
868 }
875 }
869 }
876 }
870 }
877 }
871 return results;
878 return results;
872 }
879 }
873
880
874 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
881 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
875 {
882 {
876 PythonQtObjectPtr callable = lookupCallable(object, name);
883 PythonQtObjectPtr callable = lookupCallable(object, name);
877 if (callable) {
884 if (callable) {
878 return call(callable, args);
885 return call(callable, args);
879 } else {
886 } else {
880 return QVariant();
887 return QVariant();
881 }
888 }
882 }
889 }
883
890
884 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
891 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
885 {
892 {
886 QVariant r;
893 QVariant r;
887 PythonQtObjectPtr result;
894 PythonQtObjectPtr result;
888 result.setNewRef(callAndReturnPyObject(callable, args));
895 result.setNewRef(callAndReturnPyObject(callable, args));
889 if (result) {
896 if (result) {
890 r = PythonQtConv::PyObjToQVariant(result);
897 r = PythonQtConv::PyObjToQVariant(result);
891 } else {
898 } else {
892 PythonQt::self()->handleError();
899 PythonQt::self()->handleError();
893 }
900 }
894 return r;
901 return r;
895 }
902 }
896
903
897 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
904 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
898 {
905 {
899 PyObject* result = NULL;
906 PyObject* result = NULL;
900 if (callable) {
907 if (callable) {
901 PythonQtObjectPtr pargs;
908 PythonQtObjectPtr pargs;
902 int count = args.size();
909 int count = args.size();
903 if (count>0) {
910 if (count>0) {
904 pargs.setNewRef(PyTuple_New(count));
911 pargs.setNewRef(PyTuple_New(count));
905 }
912 }
906 bool err = false;
913 bool err = false;
907 // transform QVariants to Python
914 // transform QVariants to Python
908 for (int i = 0; i < count; i++) {
915 for (int i = 0; i < count; i++) {
909 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
916 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
910 if (arg) {
917 if (arg) {
911 // steals reference, no unref
918 // steals reference, no unref
912 PyTuple_SetItem(pargs, i,arg);
919 PyTuple_SetItem(pargs, i,arg);
913 } else {
920 } else {
914 err = true;
921 err = true;
915 break;
922 break;
916 }
923 }
917 }
924 }
918
925
919 if (!err) {
926 if (!err) {
920 PyErr_Clear();
927 PyErr_Clear();
921 result = PyObject_CallObject(callable, pargs);
928 result = PyObject_CallObject(callable, pargs);
922 }
929 }
923 }
930 }
924 return result;
931 return result;
925 }
932 }
926
933
927 void PythonQt::addInstanceDecorators(QObject* o)
934 void PythonQt::addInstanceDecorators(QObject* o)
928 {
935 {
929 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
936 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
930 }
937 }
931
938
932 void PythonQt::addClassDecorators(QObject* o)
939 void PythonQt::addClassDecorators(QObject* o)
933 {
940 {
934 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
941 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
935 }
942 }
936
943
937 void PythonQt::addDecorators(QObject* o)
944 void PythonQt::addDecorators(QObject* o)
938 {
945 {
939 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
946 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
940 }
947 }
941
948
942 void PythonQt::registerQObjectClassNames(const QStringList& names)
949 void PythonQt::registerQObjectClassNames(const QStringList& names)
943 {
950 {
944 _p->registerQObjectClassNames(names);
951 _p->registerQObjectClassNames(names);
945 }
952 }
946
953
947 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
954 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
948 {
955 {
949 _p->_importInterface = importInterface;
956 _p->_importInterface = importInterface;
950 PythonQtImport::init();
957 PythonQtImport::init();
951 }
958 }
952
959
953 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
960 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
954 {
961 {
955 _p->_importIgnorePaths = paths;
962 _p->_importIgnorePaths = paths;
956 }
963 }
957
964
958 const QStringList& PythonQt::getImporterIgnorePaths()
965 const QStringList& PythonQt::getImporterIgnorePaths()
959 {
966 {
960 return _p->_importIgnorePaths;
967 return _p->_importIgnorePaths;
961 }
968 }
962
969
963 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
970 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
964 {
971 {
965 _p->_cppWrapperFactories.append(factory);
972 _p->_cppWrapperFactories.append(factory);
966 }
973 }
967
974
975 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
976 {
977 _p->_foreignWrapperFactories.append(factory);
978 }
979
968 //---------------------------------------------------------------------------------------------------
980 //---------------------------------------------------------------------------------------------------
969 PythonQtPrivate::PythonQtPrivate()
981 PythonQtPrivate::PythonQtPrivate()
970 {
982 {
971 _importInterface = NULL;
983 _importInterface = NULL;
972 _defaultImporter = new PythonQtQFileImporter;
984 _defaultImporter = new PythonQtQFileImporter;
973 _noLongerWrappedCB = NULL;
985 _noLongerWrappedCB = NULL;
974 _wrappedCB = NULL;
986 _wrappedCB = NULL;
975 _currentClassInfoForClassWrapperCreation = NULL;
987 _currentClassInfoForClassWrapperCreation = NULL;
976 _profilingCB = NULL;
988 _profilingCB = NULL;
977 }
989 }
978
990
979 void PythonQtPrivate::setupSharedLibrarySuffixes()
991 void PythonQtPrivate::setupSharedLibrarySuffixes()
980 {
992 {
981 _sharedLibrarySuffixes.clear();
993 _sharedLibrarySuffixes.clear();
982 PythonQtObjectPtr imp;
994 PythonQtObjectPtr imp;
983 imp.setNewRef(PyImport_ImportModule("imp"));
995 imp.setNewRef(PyImport_ImportModule("imp"));
984 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
996 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
985 QVariant result = imp.call("get_suffixes");
997 QVariant result = imp.call("get_suffixes");
986 #ifdef __linux
998 #ifdef __linux
987 #ifdef _DEBUG
999 #ifdef _DEBUG
988 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1000 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
989 // This is a workaround, because python does not append the '_d' suffix on Linux
1001 // This is a workaround, because python does not append the '_d' suffix on Linux
990 // and would always load the release library otherwise.
1002 // and would always load the release library otherwise.
991 _sharedLibrarySuffixes << "_d.so";
1003 _sharedLibrarySuffixes << "_d.so";
992 #endif
1004 #endif
993 #endif
1005 #endif
994 foreach (QVariant entry, result.toList()) {
1006 foreach (QVariant entry, result.toList()) {
995 QVariantList suffixEntry = entry.toList();
1007 QVariantList suffixEntry = entry.toList();
996 if (suffixEntry.count()==3) {
1008 if (suffixEntry.count()==3) {
997 int code = suffixEntry.at(2).toInt();
1009 int code = suffixEntry.at(2).toInt();
998 if (code == cExtensionCode) {
1010 if (code == cExtensionCode) {
999 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1011 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1000 }
1012 }
1001 }
1013 }
1002 }
1014 }
1003 }
1015 }
1004
1016
1005 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1017 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1006 {
1018 {
1007 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1019 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1008 _currentClassInfoForClassWrapperCreation = NULL;
1020 _currentClassInfoForClassWrapperCreation = NULL;
1009 return info;
1021 return info;
1010 }
1022 }
1011
1023
1012 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1024 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1013 {
1025 {
1014 o->setParent(this);
1026 o->setParent(this);
1015 int numMethods = o->metaObject()->methodCount();
1027 int numMethods = o->metaObject()->methodCount();
1016 for (int i = 0; i < numMethods; i++) {
1028 for (int i = 0; i < numMethods; i++) {
1017 QMetaMethod m = o->metaObject()->method(i);
1029 QMetaMethod m = o->metaObject()->method(i);
1018 if ((m.methodType() == QMetaMethod::Method ||
1030 if ((m.methodType() == QMetaMethod::Method ||
1019 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1031 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1020 if (qstrncmp(m.signature(), "new_", 4)==0) {
1032 if (qstrncmp(m.signature(), "new_", 4)==0) {
1021 if ((decoTypes & ConstructorDecorator) == 0) continue;
1033 if ((decoTypes & ConstructorDecorator) == 0) continue;
1022 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1034 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1023 if (info->parameters().at(0).pointerCount == 1) {
1035 if (info->parameters().at(0).pointerCount == 1) {
1024 QByteArray signature = m.signature();
1036 QByteArray signature = m.signature();
1025 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1037 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1026 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1038 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1027 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1039 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1028 classInfo->addConstructor(newSlot);
1040 classInfo->addConstructor(newSlot);
1029 }
1041 }
1030 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1042 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1031 if ((decoTypes & DestructorDecorator) == 0) continue;
1043 if ((decoTypes & DestructorDecorator) == 0) continue;
1032 QByteArray signature = m.signature();
1044 QByteArray signature = m.signature();
1033 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1045 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1034 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1046 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1035 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1047 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1036 classInfo->setDestructor(newSlot);
1048 classInfo->setDestructor(newSlot);
1037 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1049 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1038 if ((decoTypes & StaticDecorator) == 0) continue;
1050 if ((decoTypes & StaticDecorator) == 0) continue;
1039 QByteArray signature = m.signature();
1051 QByteArray signature = m.signature();
1040 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1052 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1041 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1053 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1042 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1054 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1043 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1055 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1044 classInfo->addDecoratorSlot(newSlot);
1056 classInfo->addDecoratorSlot(newSlot);
1045 } else {
1057 } else {
1046 if ((decoTypes & InstanceDecorator) == 0) continue;
1058 if ((decoTypes & InstanceDecorator) == 0) continue;
1047 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1059 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1048 if (info->parameters().count()>1) {
1060 if (info->parameters().count()>1) {
1049 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1061 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1050 if (p.pointerCount==1) {
1062 if (p.pointerCount==1) {
1051 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1063 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1052 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1064 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1053 classInfo->addDecoratorSlot(newSlot);
1065 classInfo->addDecoratorSlot(newSlot);
1054 }
1066 }
1055 }
1067 }
1056 }
1068 }
1057 }
1069 }
1058 }
1070 }
1059 }
1071 }
1060
1072
1061 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1073 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1062 {
1074 {
1063 foreach(QString name, names) {
1075 foreach(QString name, names) {
1064 _knownQObjectClassNames.insert(name.toLatin1(), true);
1076 _knownQObjectClassNames.insert(name.toLatin1(), true);
1065 }
1077 }
1066 }
1078 }
1067
1079
1068 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1080 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1069 {
1081 {
1070 _signalReceivers.remove(obj);
1082 _signalReceivers.remove(obj);
1071 }
1083 }
1072
1084
1073 bool PythonQt::handleError()
1085 bool PythonQt::handleError()
1074 {
1086 {
1075 bool flag = false;
1087 bool flag = false;
1076 if (PyErr_Occurred()) {
1088 if (PyErr_Occurred()) {
1077
1089
1078 // currently we just print the error and the stderr handler parses the errors
1090 // currently we just print the error and the stderr handler parses the errors
1079 PyErr_Print();
1091 PyErr_Print();
1080
1092
1081 /*
1093 /*
1082 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1094 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1083 PyObject *ptype;
1095 PyObject *ptype;
1084 PyObject *pvalue;
1096 PyObject *pvalue;
1085 PyObject *ptraceback;
1097 PyObject *ptraceback;
1086 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1098 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1087
1099
1088 Py_XDECREF(ptype);
1100 Py_XDECREF(ptype);
1089 Py_XDECREF(pvalue);
1101 Py_XDECREF(pvalue);
1090 Py_XDECREF(ptraceback);
1102 Py_XDECREF(ptraceback);
1091 */
1103 */
1092 PyErr_Clear();
1104 PyErr_Clear();
1093 flag = true;
1105 flag = true;
1094 }
1106 }
1095 return flag;
1107 return flag;
1096 }
1108 }
1097
1109
1098 void PythonQt::addSysPath(const QString& path)
1110 void PythonQt::addSysPath(const QString& path)
1099 {
1111 {
1100 PythonQtObjectPtr sys;
1112 PythonQtObjectPtr sys;
1101 sys.setNewRef(PyImport_ImportModule("sys"));
1113 sys.setNewRef(PyImport_ImportModule("sys"));
1102 PythonQtObjectPtr obj = lookupObject(sys, "path");
1114 PythonQtObjectPtr obj = lookupObject(sys, "path");
1103 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1115 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1104 }
1116 }
1105
1117
1106 void PythonQt::overwriteSysPath(const QStringList& paths)
1118 void PythonQt::overwriteSysPath(const QStringList& paths)
1107 {
1119 {
1108 PythonQtObjectPtr sys;
1120 PythonQtObjectPtr sys;
1109 sys.setNewRef(PyImport_ImportModule("sys"));
1121 sys.setNewRef(PyImport_ImportModule("sys"));
1110 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1122 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1111 }
1123 }
1112
1124
1113 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1125 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1114 {
1126 {
1115 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1127 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1116 }
1128 }
1117
1129
1118 void PythonQt::stdOutRedirectCB(const QString& str)
1130 void PythonQt::stdOutRedirectCB(const QString& str)
1119 {
1131 {
1120 if (!PythonQt::self()) {
1132 if (!PythonQt::self()) {
1121 std::cout << str.toLatin1().data() << std::endl;
1133 std::cout << str.toLatin1().data() << std::endl;
1122 return;
1134 return;
1123 }
1135 }
1124 emit PythonQt::self()->pythonStdOut(str);
1136 emit PythonQt::self()->pythonStdOut(str);
1125 }
1137 }
1126
1138
1127 void PythonQt::stdErrRedirectCB(const QString& str)
1139 void PythonQt::stdErrRedirectCB(const QString& str)
1128 {
1140 {
1129 if (!PythonQt::self()) {
1141 if (!PythonQt::self()) {
1130 std::cerr << str.toLatin1().data() << std::endl;
1142 std::cerr << str.toLatin1().data() << std::endl;
1131 return;
1143 return;
1132 }
1144 }
1133 emit PythonQt::self()->pythonStdErr(str);
1145 emit PythonQt::self()->pythonStdErr(str);
1134 }
1146 }
1135
1147
1136 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1148 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1137 {
1149 {
1138 _p->_wrappedCB = cb;
1150 _p->_wrappedCB = cb;
1139 }
1151 }
1140
1152
1141 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1153 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1142 {
1154 {
1143 _p->_noLongerWrappedCB = cb;
1155 _p->_noLongerWrappedCB = cb;
1144 }
1156 }
1145
1157
1146 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1158 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1147 {
1159 {
1148 _p->_profilingCB = cb;
1160 _p->_profilingCB = cb;
1149 }
1161 }
1150
1162
1151
1163
1152 static PyMethodDef PythonQtMethods[] = {
1164 static PyMethodDef PythonQtMethods[] = {
1153 {NULL, NULL, 0, NULL}
1165 {NULL, NULL, 0, NULL}
1154 };
1166 };
1155
1167
1156 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1168 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1157 {
1169 {
1158 QByteArray name = "PythonQt";
1170 QByteArray name = "PythonQt";
1159 if (!pythonQtModuleName.isEmpty()) {
1171 if (!pythonQtModuleName.isEmpty()) {
1160 name = pythonQtModuleName;
1172 name = pythonQtModuleName;
1161 }
1173 }
1162 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1174 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1163 _p->_pythonQtModuleName = name;
1175 _p->_pythonQtModuleName = name;
1164
1176
1165 if (redirectStdOut) {
1177 if (redirectStdOut) {
1166 PythonQtObjectPtr sys;
1178 PythonQtObjectPtr sys;
1167 PythonQtObjectPtr out;
1179 PythonQtObjectPtr out;
1168 PythonQtObjectPtr err;
1180 PythonQtObjectPtr err;
1169 sys.setNewRef(PyImport_ImportModule("sys"));
1181 sys.setNewRef(PyImport_ImportModule("sys"));
1170 // create a redirection object for stdout and stderr
1182 // create a redirection object for stdout and stderr
1171 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1183 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1172 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1184 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1173 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1185 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1174 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1186 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1175 // replace the built in file objects with our own objects
1187 // replace the built in file objects with our own objects
1176 PyModule_AddObject(sys, "stdout", out);
1188 PyModule_AddObject(sys, "stdout", out);
1177 PyModule_AddObject(sys, "stderr", err);
1189 PyModule_AddObject(sys, "stderr", err);
1178 }
1190 }
1179 }
1191 }
1180
1192
1181 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1193 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1182 {
1194 {
1183 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1195 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1184 }
1196 }
1185
1197
1186
1198
1187 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1199 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1188 {
1200 {
1189 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1201 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1190 if (!info) {
1202 if (!info) {
1191 info = new PythonQtClassInfo();
1203 info = new PythonQtClassInfo();
1192 info->setupCPPObject(typeName);
1204 info->setupCPPObject(typeName);
1193 _knownClassInfos.insert(typeName, info);
1205 _knownClassInfos.insert(typeName, info);
1194 }
1206 }
1195 return info;
1207 return info;
1196 }
1208 }
1197
1209
1198 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1210 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1199 {
1211 {
1200 _p->addPolymorphicHandler(typeName, cb);
1212 _p->addPolymorphicHandler(typeName, cb);
1201 }
1213 }
1202
1214
1203 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1215 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1204 {
1216 {
1205 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1217 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1206 info->addPolymorphicHandler(cb);
1218 info->addPolymorphicHandler(cb);
1207 }
1219 }
1208
1220
1209 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1221 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1210 {
1222 {
1211 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1223 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1212 }
1224 }
1213
1225
1214 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1226 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1215 {
1227 {
1216 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1228 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1217 if (info) {
1229 if (info) {
1218 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1230 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1219 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1231 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1220 return true;
1232 return true;
1221 } else {
1233 } else {
1222 return false;
1234 return false;
1223 }
1235 }
1224 }
1236 }
1225
1237
1226 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1238 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1227 {
1239 {
1228 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1240 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1229 if (!info->pythonQtClassWrapper()) {
1241 if (!info->pythonQtClassWrapper()) {
1230 info->setTypeSlots(typeSlots);
1242 info->setTypeSlots(typeSlots);
1231 info->setupCPPObject(typeName);
1243 info->setupCPPObject(typeName);
1232 createPythonQtClassWrapper(info, package, module);
1244 createPythonQtClassWrapper(info, package, module);
1233 }
1245 }
1234 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1246 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1235 addParentClass(typeName, parentTypeName, 0);
1247 addParentClass(typeName, parentTypeName, 0);
1236 }
1248 }
1237 if (wrapperCreator) {
1249 if (wrapperCreator) {
1238 info->setDecoratorProvider(wrapperCreator);
1250 info->setDecoratorProvider(wrapperCreator);
1239 }
1251 }
1240 if (shell) {
1252 if (shell) {
1241 info->setShellSetInstanceWrapperCB(shell);
1253 info->setShellSetInstanceWrapperCB(shell);
1242 }
1254 }
1243 }
1255 }
1244
1256
1245 PyObject* PythonQtPrivate::packageByName(const char* name)
1257 PyObject* PythonQtPrivate::packageByName(const char* name)
1246 {
1258 {
1247 if (name==NULL || name[0]==0) {
1259 if (name==NULL || name[0]==0) {
1248 name = "private";
1260 name = "private";
1249 }
1261 }
1250 PyObject* v = _packages.value(name);
1262 PyObject* v = _packages.value(name);
1251 if (!v) {
1263 if (!v) {
1252 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1264 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1253 _packages.insert(name, v);
1265 _packages.insert(name, v);
1254 // AddObject steals the reference, so increment it!
1266 // AddObject steals the reference, so increment it!
1255 Py_INCREF(v);
1267 Py_INCREF(v);
1256 PyModule_AddObject(_pythonQtModule, name, v);
1268 PyModule_AddObject(_pythonQtModule, name, v);
1257 }
1269 }
1258 return v;
1270 return v;
1259 }
1271 }
1260
1272
1261 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1273 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1262 {
1274 {
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;
1275 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1264 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1276 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1265 PythonQt::self()->handleError();
1277 PythonQt::self()->handleError();
1266 }
1278 }
1267
1279
1268 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1280 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1269 {
1281 {
1270 if (_p->_initFlags & ExternalHelp) {
1282 if (_p->_initFlags & ExternalHelp) {
1271 emit pythonHelpRequest(QByteArray(info->className()));
1283 emit pythonHelpRequest(QByteArray(info->className()));
1272 return Py_BuildValue("");
1284 return Py_BuildValue("");
1273 } else {
1285 } else {
1274 return PyString_FromString(info->help().toLatin1().data());
1286 return PyString_FromString(info->help().toLatin1().data());
1275 }
1287 }
1276 }
1288 }
1277
1289
1278 void PythonQt::clearNotFoundCachedMembers()
1290 void PythonQt::clearNotFoundCachedMembers()
1279 {
1291 {
1280 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1292 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1281 info->clearNotFoundCachedMembers();
1293 info->clearNotFoundCachedMembers();
1282 }
1294 }
1283 }
1295 }
1284
1296
1285 void PythonQtPrivate::removeWrapperPointer(void* obj)
1297 void PythonQtPrivate::removeWrapperPointer(void* obj)
1286 {
1298 {
1287 _wrappedObjects.remove(obj);
1299 _wrappedObjects.remove(obj);
1288 }
1300 }
1289
1301
1290 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1302 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1291 {
1303 {
1292 _wrappedObjects.insert(obj, wrapper);
1304 _wrappedObjects.insert(obj, wrapper);
1293 }
1305 }
1294
1306
1295 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1307 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1296 {
1308 {
1297 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1309 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1298 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1310 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1299 // this is a wrapper whose QObject was already removed due to destruction
1311 // this is a wrapper whose QObject was already removed due to destruction
1300 // so the obj pointer has to be a new QObject with the same address...
1312 // so the obj pointer has to be a new QObject with the same address...
1301 // we remove the old one and set the copy to NULL
1313 // we remove the old one and set the copy to NULL
1302 wrap->_objPointerCopy = NULL;
1314 wrap->_objPointerCopy = NULL;
1303 removeWrapperPointer(obj);
1315 removeWrapperPointer(obj);
1304 wrap = NULL;
1316 wrap = NULL;
1305 }
1317 }
1306 return wrap;
1318 return wrap;
1307 }
1319 }
1308
1320
1309 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1321 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1310 {
1322 {
1311 PythonQtObjectPtr result;
1323 PythonQtObjectPtr result;
1312 if (pycode) {
1324 if (pycode) {
1313 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1325 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1314 } else {
1326 } else {
1315 PythonQt::self()->handleError();
1327 PythonQt::self()->handleError();
1316 }
1328 }
1317 return result;
1329 return result;
1318 }
1330 }
1331
1332 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1333 {
1334 void* foreignObject = NULL;
1335 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1336 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1337 if (foreignObject) {
1338 return foreignObject;
1339 }
1340 }
1341 return NULL;
1342 } No newline at end of file
@@ -1,675 +1,684
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include "PythonQtStdIn.h"
50 #include "PythonQtStdIn.h"
51 #include <QObject>
51 #include <QObject>
52 #include <QVariant>
52 #include <QVariant>
53 #include <QList>
53 #include <QList>
54 #include <QHash>
54 #include <QHash>
55 #include <QByteArray>
55 #include <QByteArray>
56 #include <QStringList>
56 #include <QStringList>
57 #include <QtDebug>
57 #include <QtDebug>
58 #include <iostream>
58 #include <iostream>
59
59
60
60
61 class PythonQtClassInfo;
61 class PythonQtClassInfo;
62 class PythonQtPrivate;
62 class PythonQtPrivate;
63 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
64 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
65 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
66 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
67 class PythonQtForeignWrapperFactory;
67 class PythonQtQFileImporter;
68 class PythonQtQFileImporter;
68
69
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
72 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
72
73
73 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
74 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
74
75
75 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 }
78 }
78
79
79 //! returns the offset that needs to be added to upcast an object of type T1 to T2
80 //! returns the offset that needs to be added to upcast an object of type T1 to T2
80 template<class T1, class T2> int PythonQtUpcastingOffset() {
81 template<class T1, class T2> int PythonQtUpcastingOffset() {
81 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
83 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
83 }
84 }
84
85
85 //! callback to create a QObject lazily
86 //! callback to create a QObject lazily
86 typedef QObject* PythonQtQObjectCreatorFunctionCB();
87 typedef QObject* PythonQtQObjectCreatorFunctionCB();
87
88
88 //! helper template to create a derived QObject class
89 //! helper template to create a derived QObject class
89 template<class T> QObject* PythonQtCreateObject() { return new T(); };
90 template<class T> QObject* PythonQtCreateObject() { return new T(); };
90
91
91 //! The main interface to the Python Qt binding, realized as a singleton
92 //! The main interface to the Python Qt binding, realized as a singleton
92 /*!
93 /*!
93 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
94 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
94 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
95 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
95 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
96 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
96 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
97 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
97 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
98 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
98 code in the scope of a dict.
99 code in the scope of a dict.
99 */
100 */
100 class PYTHONQT_EXPORT PythonQt : public QObject {
101 class PYTHONQT_EXPORT PythonQt : public QObject {
101
102
102 Q_OBJECT
103 Q_OBJECT
103
104
104 public:
105 public:
105
106
106 //! flags that can be passed to PythonQt::init()
107 //! flags that can be passed to PythonQt::init()
107 enum InitFlags {
108 enum InitFlags {
108 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
109 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
109 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
110 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
110 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
111 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
111 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
112 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
112 };
113 };
113
114
114 //! flags that tell PythonQt which operators to expect on the registered type
115 //! flags that tell PythonQt which operators to expect on the registered type
115 enum TypeSlots {
116 enum TypeSlots {
116 Type_Add = 1,
117 Type_Add = 1,
117 Type_Subtract = 1 << 1,
118 Type_Subtract = 1 << 1,
118 Type_Multiply = 1 << 2,
119 Type_Multiply = 1 << 2,
119 Type_Divide = 1 << 3,
120 Type_Divide = 1 << 3,
120 Type_Mod = 1 << 4,
121 Type_Mod = 1 << 4,
121 Type_And = 1 << 5,
122 Type_And = 1 << 5,
122 Type_Or = 1 << 6,
123 Type_Or = 1 << 6,
123 Type_Xor = 1 << 7,
124 Type_Xor = 1 << 7,
124 Type_LShift = 1 << 8,
125 Type_LShift = 1 << 8,
125 Type_RShift = 1 << 9,
126 Type_RShift = 1 << 9,
126
127
127 Type_InplaceAdd = 1 << 10,
128 Type_InplaceAdd = 1 << 10,
128 Type_InplaceSubtract = 1 << 11,
129 Type_InplaceSubtract = 1 << 11,
129 Type_InplaceMultiply = 1 << 12,
130 Type_InplaceMultiply = 1 << 12,
130 Type_InplaceDivide = 1 << 13,
131 Type_InplaceDivide = 1 << 13,
131 Type_InplaceMod = 1 << 14,
132 Type_InplaceMod = 1 << 14,
132 Type_InplaceAnd = 1 << 15,
133 Type_InplaceAnd = 1 << 15,
133 Type_InplaceOr = 1 << 16,
134 Type_InplaceOr = 1 << 16,
134 Type_InplaceXor = 1 << 17,
135 Type_InplaceXor = 1 << 17,
135 Type_InplaceLShift = 1 << 18,
136 Type_InplaceLShift = 1 << 18,
136 Type_InplaceRShift = 1 << 19,
137 Type_InplaceRShift = 1 << 19,
137
138
138 // Not yet needed/nicely mappable/generated...
139 // Not yet needed/nicely mappable/generated...
139 //Type_Positive = 1 << 29,
140 //Type_Positive = 1 << 29,
140 //Type_Negative = 1 << 29,
141 //Type_Negative = 1 << 29,
141 //Type_Abs = 1 << 29,
142 //Type_Abs = 1 << 29,
142 //Type_Hash = 1 << 29,
143 //Type_Hash = 1 << 29,
143
144
144 Type_Invert = 1 << 29,
145 Type_Invert = 1 << 29,
145 Type_RichCompare = 1 << 30,
146 Type_RichCompare = 1 << 30,
146 Type_NonZero = 1 << 31,
147 Type_NonZero = 1 << 31,
147
148
148 };
149 };
149
150
150 //! enum for profiling callback
151 //! enum for profiling callback
151 enum ProfilingCallbackState {
152 enum ProfilingCallbackState {
152 Enter = 1,
153 Enter = 1,
153 Leave = 2
154 Leave = 2
154 };
155 };
155
156
156 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
157 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
157 //! they are NULL.
158 //! they are NULL.
158 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
159
160
160 //---------------------------------------------------------------------------
161 //---------------------------------------------------------------------------
161 //! \name Singleton Initialization
162 //! \name Singleton Initialization
162 //@{
163 //@{
163
164
164 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
165 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
165 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
166 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
166 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
167 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
167 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
168
169
169 //! cleanup of the singleton
170 //! cleanup of the singleton
170 static void cleanup();
171 static void cleanup();
171
172
172 //! get the singleton instance
173 //! get the singleton instance
173 static PythonQt* self();
174 static PythonQt* self();
174
175
175 //@}
176 //@}
176
177
177 //! defines the object types for introspection
178 //! defines the object types for introspection
178 enum ObjectType {
179 enum ObjectType {
179 Class,
180 Class,
180 Function,
181 Function,
181 Variable,
182 Variable,
182 Module,
183 Module,
183 Anything,
184 Anything,
184 CallOverloads
185 CallOverloads
185 };
186 };
186
187
187
188
188 //---------------------------------------------------------------------------
189 //---------------------------------------------------------------------------
189 //! \name Standard input handling
190 //! \name Standard input handling
190 //@{
191 //@{
191
192
192 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195
196
196 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! or 'sys.pythonqt_original_stdin'
198 //! or 'sys.pythonqt_original_stdin'
198 void setRedirectStdInCallbackEnabled(bool enabled);
199 void setRedirectStdInCallbackEnabled(bool enabled);
199
200
200 //@}
201 //@}
201
202
202 //---------------------------------------------------------------------------
203 //---------------------------------------------------------------------------
203 //! \name Modules
204 //! \name Modules
204 //@{
205 //@{
205
206
206 //! get the __main__ module of python
207 //! get the __main__ module of python
207 PythonQtObjectPtr getMainModule();
208 PythonQtObjectPtr getMainModule();
208
209
209 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
210 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
210 //! If a module is already imported, this returns the already imported module.
211 //! If a module is already imported, this returns the already imported module.
211 PythonQtObjectPtr importModule(const QString& name);
212 PythonQtObjectPtr importModule(const QString& name);
212
213
213 //! creates the new module \c name and evaluates the given file in the context of that module
214 //! creates the new module \c name and evaluates the given file in the context of that module
214 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
215 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
215 //! to a module later on.
216 //! to a module later on.
216 //! The user needs to make sure that the \c name is unique in the python module dictionary.
217 //! The user needs to make sure that the \c name is unique in the python module dictionary.
217 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
218
219
219 //! creates the new module \c name and evaluates the given script in the context of that module.
220 //! creates the new module \c name and evaluates the given script in the context of that module.
220 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
221 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
221 //! to a module later on.
222 //! to a module later on.
222 //! The user needs to make sure that the \c name is unique in the python module dictionary.
223 //! The user needs to make sure that the \c name is unique in the python module dictionary.
223 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
224
225
225 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
226 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
226 //! script code
227 //! script code
227 PythonQtObjectPtr createUniqueModule();
228 PythonQtObjectPtr createUniqueModule();
228
229
229 //@}
230 //@}
230
231
231 //---------------------------------------------------------------------------
232 //---------------------------------------------------------------------------
232 //! \name Importing/Paths
233 //! \name Importing/Paths
233 //@{
234 //@{
234
235
235 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
236 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
236 void overwriteSysPath(const QStringList& paths);
237 void overwriteSysPath(const QStringList& paths);
237
238
238 //! prepend a path to sys.path to allow importing from it
239 //! prepend a path to sys.path to allow importing from it
239 void addSysPath(const QString& path);
240 void addSysPath(const QString& path);
240
241
241 //! sets the __path__ list of a module to the given list (important for local imports)
242 //! sets the __path__ list of a module to the given list (important for local imports)
242 void setModuleImportPath(PyObject* module, const QStringList& paths);
243 void setModuleImportPath(PyObject* module, const QStringList& paths);
243
244
244 //@}
245 //@}
245
246
246 //---------------------------------------------------------------------------
247 //---------------------------------------------------------------------------
247 //! \name Registering Classes
248 //! \name Registering Classes
248 //@{
249 //@{
249
250
250 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
251 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
251 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
252 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
253 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
254
255
255 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
256 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
256 //! (ownership of wrapper is passed to PythonQt)
257 //! (ownership of wrapper is passed to PythonQt)
257 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
258 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
258
259
259 This will add a wrapper object that is used to make calls to the given classname \c typeName.
260 This will add a wrapper object that is used to make calls to the given classname \c typeName.
260 All slots that take a pointer to typeName as the first argument will be callable from Python on
261 All slots that take a pointer to typeName as the first argument will be callable from Python on
261 a variant object that contains such a type.
262 a variant object that contains such a type.
262 */
263 */
263 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
264
265
265 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
266 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
266 //! and it will register the classes when it first sees a pointer to such a derived class
267 //! and it will register the classes when it first sees a pointer to such a derived class
267 void registerQObjectClassNames(const QStringList& names);
268 void registerQObjectClassNames(const QStringList& names);
268
269
269 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
270 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
270 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
271 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
271 //! type is really derived from parentType.
272 //! type is really derived from parentType.
272 //! Returns false if the typeName was not yet registered.
273 //! Returns false if the typeName was not yet registered.
273 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
274
275
275 //! add a handler for polymorphic downcasting
276 //! add a handler for polymorphic downcasting
276 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
277
278
278 //@}
279 //@}
279
280
280 //---------------------------------------------------------------------------
281 //---------------------------------------------------------------------------
281 //! \name Script Parsing and Evaluation
282 //! \name Script Parsing and Evaluation
282 //@{
283 //@{
283
284
284 //! parses the given file and returns the python code object, this can then be used to call evalCode()
285 //! parses the given file and returns the python code object, this can then be used to call evalCode()
285 PythonQtObjectPtr parseFile(const QString& filename);
286 PythonQtObjectPtr parseFile(const QString& filename);
286
287
287 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
288 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
288 //! If pycode is NULL, a python error is printed.
289 //! If pycode is NULL, a python error is printed.
289 QVariant evalCode(PyObject* object, PyObject* pycode);
290 QVariant evalCode(PyObject* object, PyObject* pycode);
290
291
291 //! evaluates the given script code and returns the result value
292 //! evaluates the given script code and returns the result value
292 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
293
294
294 //! evaluates the given script code from file
295 //! evaluates the given script code from file
295 void evalFile(PyObject* object, const QString& filename);
296 void evalFile(PyObject* object, const QString& filename);
296
297
297 //@}
298 //@}
298
299
299 //---------------------------------------------------------------------------
300 //---------------------------------------------------------------------------
300 //! \name Signal Handlers
301 //! \name Signal Handlers
301 //@{
302 //@{
302
303
303 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
304 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
304 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
305
306
306 //! remove a signal handler from the given \c signal of \c obj
307 //! remove a signal handler from the given \c signal of \c obj
307 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
308
309
309 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
310 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
310 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
311
312
312 //! remove a signal handler from the given \c signal of \c obj
313 //! remove a signal handler from the given \c signal of \c obj
313 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
314
315
315 //@}
316 //@}
316
317
317 //---------------------------------------------------------------------------
318 //---------------------------------------------------------------------------
318 //! \name Variable access
319 //! \name Variable access
319 //@{
320 //@{
320
321
321 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
322 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
322 void addObject(PyObject* object, const QString& name, QObject* qObject);
323 void addObject(PyObject* object, const QString& name, QObject* qObject);
323
324
324 //! add the given variable to the object
325 //! add the given variable to the object
325 void addVariable(PyObject* object, const QString& name, const QVariant& v);
326 void addVariable(PyObject* object, const QString& name, const QVariant& v);
326
327
327 //! remove the given variable
328 //! remove the given variable
328 void removeVariable(PyObject* module, const QString& name);
329 void removeVariable(PyObject* module, const QString& name);
329
330
330 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
331 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
331 QVariant getVariable(PyObject* object, const QString& name);
332 QVariant getVariable(PyObject* object, const QString& name);
332
333
333 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
334 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
334 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
335
336
336 //! returns the found callable object or NULL
337 //! returns the found callable object or NULL
337 //! @return new reference
338 //! @return new reference
338 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
339 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
339
340
340 //@}
341 //@}
341
342
342 //---------------------------------------------------------------------------
343 //---------------------------------------------------------------------------
343 //! \name Calling Python Objects
344 //! \name Calling Python Objects
344 //@{
345 //@{
345
346
346 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
347 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
347 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
348 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
348
349
349 //! call the given python object, returns the result converted to a QVariant
350 //! call the given python object, returns the result converted to a QVariant
350 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
351 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
351
352
352 //! call the given python object, returns the result as new PyObject
353 //! call the given python object, returns the result as new PyObject
353 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
354 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
354
355
355 //@}
356 //@}
356
357
357 //---------------------------------------------------------------------------
358 //---------------------------------------------------------------------------
358 //! \name Decorations, Constructors, Wrappers...
359 //! \name Decorations, Constructors, Wrappers...
359 //@{
360 //@{
360
361
361 //! add an object whose slots will be used as decorator slots for
362 //! add an object whose slots will be used as decorator slots for
362 //! other QObjects or CPP classes. The slots need to follow the
363 //! other QObjects or CPP classes. The slots need to follow the
363 //! convention that the first argument is a pointer to the wrapped object.
364 //! convention that the first argument is a pointer to the wrapped object.
364 //! (ownership is passed to PythonQt)
365 //! (ownership is passed to PythonQt)
365 /*!
366 /*!
366 Example:
367 Example:
367
368
368 A slot with the signature
369 A slot with the signature
369
370
370 \code
371 \code
371 bool doSomething(QWidget* w, int a)
372 bool doSomething(QWidget* w, int a)
372 \endcode
373 \endcode
373
374
374 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
375 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
375 that will be called with the concrete instance as first argument.
376 that will be called with the concrete instance as first argument.
376 So in Python you can now e.g. call
377 So in Python you can now e.g. call
377
378
378 \code
379 \code
379 someWidget.doSomething(12)
380 someWidget.doSomething(12)
380 \endcode
381 \endcode
381
382
382 without QWidget really having this method. This allows to easily make normal methods
383 without QWidget really having this method. This allows to easily make normal methods
383 of Qt classes callable by forwarding them with such decorator slots
384 of Qt classes callable by forwarding them with such decorator slots
384 or to make CPP classes (which are not derived from QObject) callable from Python.
385 or to make CPP classes (which are not derived from QObject) callable from Python.
385 */
386 */
386 void addInstanceDecorators(QObject* o);
387 void addInstanceDecorators(QObject* o);
387
388
388 //! add an object whose slots will be used as decorator slots for
389 //! add an object whose slots will be used as decorator slots for
389 //! class objects (ownership is passed to PythonQt)
390 //! class objects (ownership is passed to PythonQt)
390 /*!
391 /*!
391 The slots need to follow the following convention:
392 The slots need to follow the following convention:
392 - SomeClass* new_SomeClass(...)
393 - SomeClass* new_SomeClass(...)
393 - QVariant new_SomeClass(...)
394 - QVariant new_SomeClass(...)
394 - void delete_SomeClass(SomeClass*)
395 - void delete_SomeClass(SomeClass*)
395 - ... static_SomeClass_someName(...)
396 - ... static_SomeClass_someName(...)
396
397
397 This will add:
398 This will add:
398 - a constructor
399 - a constructor
399 - a constructor which generates a QVariant
400 - a constructor which generates a QVariant
400 - a destructor (only useful for CPP objects)
401 - a destructor (only useful for CPP objects)
401 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
402 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
402
403
403 */
404 */
404 void addClassDecorators(QObject* o);
405 void addClassDecorators(QObject* o);
405
406
406 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
407 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
407 void addDecorators(QObject* o);
408 void addDecorators(QObject* o);
408
409
409 //! add the given factory to PythonQt (ownership stays with caller)
410 //! add the given factory to PythonQt (ownership stays with caller)
410 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
411 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
411
412
413 //! add the given factory to PythonQt (ownership stays with caller)
414 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
415
412 //@}
416 //@}
413
417
414 //---------------------------------------------------------------------------
418 //---------------------------------------------------------------------------
415 //! \name Custom Importer
419 //! \name Custom Importer
416 //@{
420 //@{
417
421
418 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
422 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
419 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
423 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
420 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
424 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
421 //! This is not reversible, so even setting setImporter(NULL) afterwards will
425 //! This is not reversible, so even setting setImporter(NULL) afterwards will
422 //! keep the custom PythonQt importer with a QFile default import interface.
426 //! keep the custom PythonQt importer with a QFile default import interface.
423 //! Subsequent python import calls will make use of the passed importInterface
427 //! Subsequent python import calls will make use of the passed importInterface
424 //! which forwards all import calls to the given \c importInterface.
428 //! which forwards all import calls to the given \c importInterface.
425 //! Passing NULL will install a default QFile importer.
429 //! Passing NULL will install a default QFile importer.
426 //! (\c importInterface ownership stays with caller)
430 //! (\c importInterface ownership stays with caller)
427 void setImporter(PythonQtImportFileInterface* importInterface);
431 void setImporter(PythonQtImportFileInterface* importInterface);
428
432
429 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
433 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
430 //! (without calling setImporter or installDefaultImporter at least once, the default python import
434 //! (without calling setImporter or installDefaultImporter at least once, the default python import
431 //! mechanism is in place)
435 //! mechanism is in place)
432 //! the default importer allows to import files from anywhere QFile can read from,
436 //! the default importer allows to import files from anywhere QFile can read from,
433 //! including the Qt resource system using ":". Keep in mind that you need to extend
437 //! including the Qt resource system using ":". Keep in mind that you need to extend
434 //! "sys.path" with ":" to be able to import from the Qt resources.
438 //! "sys.path" with ":" to be able to import from the Qt resources.
435 void installDefaultImporter() { setImporter(NULL); }
439 void installDefaultImporter() { setImporter(NULL); }
436
440
437 //! set paths that the importer should ignore
441 //! set paths that the importer should ignore
438 void setImporterIgnorePaths(const QStringList& paths);
442 void setImporterIgnorePaths(const QStringList& paths);
439
443
440 //! get paths that the importer should ignore
444 //! get paths that the importer should ignore
441 const QStringList& getImporterIgnorePaths();
445 const QStringList& getImporterIgnorePaths();
442
446
443 //! get access to the file importer (if set)
447 //! get access to the file importer (if set)
444 static PythonQtImportFileInterface* importInterface();
448 static PythonQtImportFileInterface* importInterface();
445
449
446 //@}
450 //@}
447
451
448 //---------------------------------------------------------------------------
452 //---------------------------------------------------------------------------
449 //! \name Other Stuff
453 //! \name Other Stuff
450 //@{
454 //@{
451
455
452 //! get access to internal data (should not be used on the public API, but is used by some C functions)
456 //! get access to internal data (should not be used on the public API, but is used by some C functions)
453 static PythonQtPrivate* priv() { return _self->_p; }
457 static PythonQtPrivate* priv() { return _self->_p; }
454
458
455 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
459 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
456 //! The error is currently just output to the python stderr, future version might implement better trace printing
460 //! The error is currently just output to the python stderr, future version might implement better trace printing
457 bool handleError();
461 bool handleError();
458
462
459 //! clear all NotFound entries on all class infos, to ensure that
463 //! clear all NotFound entries on all class infos, to ensure that
460 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
464 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
461 void clearNotFoundCachedMembers();
465 void clearNotFoundCachedMembers();
462
466
463 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
467 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
464 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
468 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
465 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
469 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
466 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
470 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
467
471
468 //! call the callback if it is set
472 //! call the callback if it is set
469 static void qObjectNoLongerWrappedCB(QObject* o);
473 static void qObjectNoLongerWrappedCB(QObject* o);
470
474
471 //! called by internal help methods
475 //! called by internal help methods
472 PyObject* helpCalled(PythonQtClassInfo* info);
476 PyObject* helpCalled(PythonQtClassInfo* info);
473
477
474 //! returns the found object or NULL
478 //! returns the found object or NULL
475 //! @return new reference
479 //! @return new reference
476 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
480 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
477
481
478 //! sets a callback that is called before and after function calls for profiling
482 //! sets a callback that is called before and after function calls for profiling
479 void setProfilingCallback(ProfilingCB* cb);
483 void setProfilingCallback(ProfilingCB* cb);
480
484
481 //@}
485 //@}
482
486
483 signals:
487 signals:
484 //! emitted when python outputs something to stdout (and redirection is turned on)
488 //! emitted when python outputs something to stdout (and redirection is turned on)
485 void pythonStdOut(const QString& str);
489 void pythonStdOut(const QString& str);
486 //! emitted when python outputs something to stderr (and redirection is turned on)
490 //! emitted when python outputs something to stderr (and redirection is turned on)
487 void pythonStdErr(const QString& str);
491 void pythonStdErr(const QString& str);
488
492
489 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
493 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
490 void pythonHelpRequest(const QByteArray& cppClassName);
494 void pythonHelpRequest(const QByteArray& cppClassName);
491
495
492 private:
496 private:
493 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
497 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
494
498
495 //! callback for stdout redirection, emits pythonStdOut signal
499 //! callback for stdout redirection, emits pythonStdOut signal
496 static void stdOutRedirectCB(const QString& str);
500 static void stdOutRedirectCB(const QString& str);
497 //! callback for stderr redirection, emits pythonStdErr signal
501 //! callback for stderr redirection, emits pythonStdErr signal
498 static void stdErrRedirectCB(const QString& str);
502 static void stdErrRedirectCB(const QString& str);
499
503
500 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
504 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
501 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
505 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
502
506
503 PythonQt(int flags, const QByteArray& pythonQtModuleName);
507 PythonQt(int flags, const QByteArray& pythonQtModuleName);
504 ~PythonQt();
508 ~PythonQt();
505
509
506 static PythonQt* _self;
510 static PythonQt* _self;
507 static int _uniqueModuleCount;
511 static int _uniqueModuleCount;
508
512
509 PythonQtPrivate* _p;
513 PythonQtPrivate* _p;
510
514
511 };
515 };
512
516
513 //! internal PythonQt details
517 //! internal PythonQt details
514 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
518 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
515
519
516 Q_OBJECT
520 Q_OBJECT
517
521
518 public:
522 public:
519 PythonQtPrivate();
523 PythonQtPrivate();
520 ~PythonQtPrivate();
524 ~PythonQtPrivate();
521
525
522 enum DecoratorTypes {
526 enum DecoratorTypes {
523 StaticDecorator = 1,
527 StaticDecorator = 1,
524 ConstructorDecorator = 2,
528 ConstructorDecorator = 2,
525 DestructorDecorator = 4,
529 DestructorDecorator = 4,
526 InstanceDecorator = 8,
530 InstanceDecorator = 8,
527 AllDecorators = 0xffff
531 AllDecorators = 0xffff
528 };
532 };
529
533
530 //! get the suffixes that are used for shared libraries
534 //! get the suffixes that are used for shared libraries
531 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
535 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
532
536
533 //! returns if the id is the id for PythonQtObjectPtr
537 //! returns if the id is the id for PythonQtObjectPtr
534 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
538 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
535
539
536 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
540 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
537 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
541 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
538 //! remove the wrapper ptr again
542 //! remove the wrapper ptr again
539 void removeWrapperPointer(void* obj);
543 void removeWrapperPointer(void* obj);
540
544
545 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
546 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
547
541 //! add parent class relation
548 //! add parent class relation
542 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
549 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
543
550
544 //! add a handler for polymorphic downcasting
551 //! add a handler for polymorphic downcasting
545 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
552 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
546
553
547 //! lookup existing classinfo and return new if not yet present
554 //! lookup existing classinfo and return new if not yet present
548 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
555 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
549
556
550 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
557 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
551 void removeSignalEmitter(QObject* obj);
558 void removeSignalEmitter(QObject* obj);
552
559
553 //! wrap the given QObject into a Python object (or return existing wrapper!)
560 //! wrap the given QObject into a Python object (or return existing wrapper!)
554 PyObject* wrapQObject(QObject* obj);
561 PyObject* wrapQObject(QObject* obj);
555
562
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
563 //! 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
557 PyObject* wrapPtr(void* ptr, const QByteArray& name);
564 PyObject* wrapPtr(void* ptr, const QByteArray& name);
558
565
559 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
566 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
560 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
567 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
561 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
568 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
562 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
569 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
563
570
564 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
571 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
565 //! (ownership of wrapper is passed to PythonQt)
572 //! (ownership of wrapper is passed to PythonQt)
566 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
573 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
567
574
568 This will add a wrapper object that is used to make calls to the given classname \c typeName.
575 This will add a wrapper object that is used to make calls to the given classname \c typeName.
569 All slots that take a pointer to typeName as the first argument will be callable from Python on
576 All slots that take a pointer to typeName as the first argument will be callable from Python on
570 a variant object that contains such a type.
577 a variant object that contains such a type.
571 */
578 */
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);
579 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);
573
580
574 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
581 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
575 //! and it will register the classes when it first sees a pointer to such a derived class
582 //! and it will register the classes when it first sees a pointer to such a derived class
576 void registerQObjectClassNames(const QStringList& names);
583 void registerQObjectClassNames(const QStringList& names);
577
584
578 //! add a decorator object
585 //! add a decorator object
579 void addDecorators(QObject* o, int decoTypes);
586 void addDecorators(QObject* o, int decoTypes);
580
587
581 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
588 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
582 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
589 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
583
590
584 //! create a new instance of the given enum type with given value (returns a new reference)
591 //! create a new instance of the given enum type with given value (returns a new reference)
585 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
592 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
586
593
587 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
594 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
588 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
595 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
589
596
590 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
597 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
591 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
598 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
592
599
593 //! get the class info for a meta object (if available)
600 //! get the class info for a meta object (if available)
594 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
601 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
595
602
596 //! get the class info for a meta object (if available)
603 //! get the class info for a meta object (if available)
597 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
604 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
598
605
599 //! creates the new module from the given pycode
606 //! creates the new module from the given pycode
600 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
607 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
601
608
602 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
609 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
603 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
610 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
604
611
605 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
612 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
606 static PyObject* dummyTuple();
613 static PyObject* dummyTuple();
607
614
608 //! called by virtual overloads when a python return value can not be converted to the required Qt type
615 //! called by virtual overloads when a python return value can not be converted to the required Qt type
609 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
616 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
610
617
611 //! get access to the PythonQt module
618 //! get access to the PythonQt module
612 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
619 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
613
620
614 //! returns the profiling callback, which may be NULL
621 //! returns the profiling callback, which may be NULL
615 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
622 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
616
623
617 private:
624 private:
618 //! Setup the shared library suffixes by getting them from the "imp" module.
625 //! Setup the shared library suffixes by getting them from the "imp" module.
619 void setupSharedLibrarySuffixes();
626 void setupSharedLibrarySuffixes();
620
627
621 //! create a new pythonqt class wrapper and place it in the pythonqt module
628 //! create a new pythonqt class wrapper and place it in the pythonqt module
622 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
629 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
623
630
624 //! get/create new package module (the returned object is a borrowed reference)
631 //! get/create new package module (the returned object is a borrowed reference)
625 PyObject* packageByName(const char* name);
632 PyObject* packageByName(const char* name);
626
633
627 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
634 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
628 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
635 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
629
636
630 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
637 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
631 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
638 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
632
639
633 //! stores the meta info of known Qt classes
640 //! stores the meta info of known Qt classes
634 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
641 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
635
642
636 //! names of qobject derived classes that can be casted to qobject savely
643 //! names of qobject derived classes that can be casted to qobject savely
637 QHash<QByteArray, bool> _knownQObjectClassNames;
644 QHash<QByteArray, bool> _knownQObjectClassNames;
638
645
639 //! stores signal receivers for QObjects
646 //! stores signal receivers for QObjects
640 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
647 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
641
648
642 //! the PythonQt python module
649 //! the PythonQt python module
643 PythonQtObjectPtr _pythonQtModule;
650 PythonQtObjectPtr _pythonQtModule;
644
651
645 //! the name of the PythonQt python module
652 //! the name of the PythonQt python module
646 QByteArray _pythonQtModuleName;
653 QByteArray _pythonQtModuleName;
647
654
648 //! the importer interface (if set)
655 //! the importer interface (if set)
649 PythonQtImportFileInterface* _importInterface;
656 PythonQtImportFileInterface* _importInterface;
650
657
651 //! the default importer
658 //! the default importer
652 PythonQtQFileImporter* _defaultImporter;
659 PythonQtQFileImporter* _defaultImporter;
653
660
654 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
661 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
655 PythonQtQObjectWrappedCB* _wrappedCB;
662 PythonQtQObjectWrappedCB* _wrappedCB;
656
663
657 QStringList _importIgnorePaths;
664 QStringList _importIgnorePaths;
658 QStringList _sharedLibrarySuffixes;
665 QStringList _sharedLibrarySuffixes;
659
666
660 //! the cpp object wrapper factories
667 //! the cpp object wrapper factories
661 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
668 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
662
669
670 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
671
663 QHash<QByteArray, PyObject*> _packages;
672 QHash<QByteArray, PyObject*> _packages;
664
673
665 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
674 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
666
675
667 PythonQt::ProfilingCB* _profilingCB;
676 PythonQt::ProfilingCB* _profilingCB;
668
677
669 int _initFlags;
678 int _initFlags;
670 int _PythonQtObjectPtr_metaId;
679 int _PythonQtObjectPtr_metaId;
671
680
672 friend class PythonQt;
681 friend class PythonQt;
673 };
682 };
674
683
675 #endif
684 #endif
@@ -1,1229 +1,1232
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 }
389 } else if (obj == Py_None) {
390 // TODO XXX: pass obj and name and add when it returns a pointer
391 else if (obj == Py_None) {
392 // None is treated as a NULL ptr
390 // None is treated as a NULL ptr
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
394 } else {
392 } else {
395 // if we are not strict, we try if we are passed a 0 integer
393 void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj);
396 if (!strict) {
394 if (foreignWrapper) {
397 bool ok;
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr);
398 int value = PyObjGetInt(obj, true, ok);
396 } else {
399 if (ok && value==0) {
397 // if we are not strict, we try if we are passed a 0 integer
400 // TODOXXX is this wise? or should it be expected from the programmer to use None?
398 if (!strict) {
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
399 bool ok;
400 int value = PyObjGetInt(obj, true, ok);
401 if (ok && value==0) {
402 // TODOXXX is this wise? or should it be expected from the programmer to use None?
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
404 }
402 }
405 }
403 }
406 }
404 }
407 }
405 } else if (info.pointerCount == 0) {
408 } else if (info.pointerCount == 0) {
406 // not a pointer
409 // not a pointer
407 switch (info.typeId) {
410 switch (info.typeId) {
408 case QMetaType::Char:
411 case QMetaType::Char:
409 {
412 {
410 int val = PyObjGetInt(obj, strict, ok);
413 int val = PyObjGetInt(obj, strict, ok);
411 if (ok) {
414 if (ok) {
412 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
415 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
413 }
416 }
414 }
417 }
415 break;
418 break;
416 case QMetaType::UChar:
419 case QMetaType::UChar:
417 {
420 {
418 int val = PyObjGetInt(obj, strict, ok);
421 int val = PyObjGetInt(obj, strict, ok);
419 if (ok) {
422 if (ok) {
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
423 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
421 }
424 }
422 }
425 }
423 break;
426 break;
424 case QMetaType::Short:
427 case QMetaType::Short:
425 {
428 {
426 int val = PyObjGetInt(obj, strict, ok);
429 int val = PyObjGetInt(obj, strict, ok);
427 if (ok) {
430 if (ok) {
428 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
431 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
429 }
432 }
430 }
433 }
431 break;
434 break;
432 case QMetaType::UShort:
435 case QMetaType::UShort:
433 {
436 {
434 int val = PyObjGetInt(obj, strict, ok);
437 int val = PyObjGetInt(obj, strict, ok);
435 if (ok) {
438 if (ok) {
436 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
439 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
437 }
440 }
438 }
441 }
439 break;
442 break;
440 case QMetaType::Long:
443 case QMetaType::Long:
441 {
444 {
442 long val = (long)PyObjGetLongLong(obj, strict, ok);
445 long val = (long)PyObjGetLongLong(obj, strict, ok);
443 if (ok) {
446 if (ok) {
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
447 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
445 }
448 }
446 }
449 }
447 break;
450 break;
448 case QMetaType::ULong:
451 case QMetaType::ULong:
449 {
452 {
450 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
453 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
451 if (ok) {
454 if (ok) {
452 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
455 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
453 }
456 }
454 }
457 }
455 break;
458 break;
456 case QMetaType::Bool:
459 case QMetaType::Bool:
457 {
460 {
458 bool val = PyObjGetBool(obj, strict, ok);
461 bool val = PyObjGetBool(obj, strict, ok);
459 if (ok) {
462 if (ok) {
460 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
463 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
461 }
464 }
462 }
465 }
463 break;
466 break;
464 case QMetaType::Int:
467 case QMetaType::Int:
465 {
468 {
466 int val = PyObjGetInt(obj, strict, ok);
469 int val = PyObjGetInt(obj, strict, ok);
467 if (ok) {
470 if (ok) {
468 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
471 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
469 }
472 }
470 }
473 }
471 break;
474 break;
472 case QMetaType::UInt:
475 case QMetaType::UInt:
473 {
476 {
474 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
477 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
475 if (ok) {
478 if (ok) {
476 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
479 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
477 }
480 }
478 }
481 }
479 break;
482 break;
480 case QMetaType::QChar:
483 case QMetaType::QChar:
481 {
484 {
482 int val = PyObjGetInt(obj, strict, ok);
485 int val = PyObjGetInt(obj, strict, ok);
483 if (ok) {
486 if (ok) {
484 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
487 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
485 }
488 }
486 }
489 }
487 break;
490 break;
488 case QMetaType::Float:
491 case QMetaType::Float:
489 {
492 {
490 float val = (float)PyObjGetDouble(obj, strict, ok);
493 float val = (float)PyObjGetDouble(obj, strict, ok);
491 if (ok) {
494 if (ok) {
492 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
495 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
493 }
496 }
494 }
497 }
495 break;
498 break;
496 case QMetaType::Double:
499 case QMetaType::Double:
497 {
500 {
498 double val = (double)PyObjGetDouble(obj, strict, ok);
501 double val = (double)PyObjGetDouble(obj, strict, ok);
499 if (ok) {
502 if (ok) {
500 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
503 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
501 }
504 }
502 }
505 }
503 break;
506 break;
504 case QMetaType::LongLong:
507 case QMetaType::LongLong:
505 {
508 {
506 qint64 val = PyObjGetLongLong(obj, strict, ok);
509 qint64 val = PyObjGetLongLong(obj, strict, ok);
507 if (ok) {
510 if (ok) {
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
511 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
509 }
512 }
510 }
513 }
511 break;
514 break;
512 case QMetaType::ULongLong:
515 case QMetaType::ULongLong:
513 {
516 {
514 quint64 val = PyObjGetULongLong(obj, strict, ok);
517 quint64 val = PyObjGetULongLong(obj, strict, ok);
515 if (ok) {
518 if (ok) {
516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
519 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
517 }
520 }
518 }
521 }
519 break;
522 break;
520 case QMetaType::QByteArray:
523 case QMetaType::QByteArray:
521 {
524 {
522 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
525 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
523 if (ok) {
526 if (ok) {
524 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
527 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
525 ptr = (void*)((QVariant*)ptr)->constData();
528 ptr = (void*)((QVariant*)ptr)->constData();
526 }
529 }
527 }
530 }
528 break;
531 break;
529 case QMetaType::QString:
532 case QMetaType::QString:
530 {
533 {
531 QString str = PyObjGetString(obj, strict, ok);
534 QString str = PyObjGetString(obj, strict, ok);
532 if (ok) {
535 if (ok) {
533 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
536 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
534 ptr = (void*)((QVariant*)ptr)->constData();
537 ptr = (void*)((QVariant*)ptr)->constData();
535 }
538 }
536 }
539 }
537 break;
540 break;
538 case QMetaType::QStringList:
541 case QMetaType::QStringList:
539 {
542 {
540 QStringList l = PyObjToStringList(obj, strict, ok);
543 QStringList l = PyObjToStringList(obj, strict, ok);
541 if (ok) {
544 if (ok) {
542 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
545 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
543 ptr = (void*)((QVariant*)ptr)->constData();
546 ptr = (void*)((QVariant*)ptr)->constData();
544 }
547 }
545 }
548 }
546 break;
549 break;
547
550
548 case PythonQtMethodInfo::Variant:
551 case PythonQtMethodInfo::Variant:
549 {
552 {
550 QVariant v = PyObjToQVariant(obj);
553 QVariant v = PyObjToQVariant(obj);
551 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
554 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
552 // so we do not check v.isValid() here
555 // so we do not check v.isValid() here
553 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
556 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
554 }
557 }
555 break;
558 break;
556 default:
559 default:
557 {
560 {
558 // check for enum case
561 // check for enum case
559 if (info.enumWrapper) {
562 if (info.enumWrapper) {
560 unsigned int val;
563 unsigned int val;
561 ok = false;
564 ok = false;
562 if ((PyObject*)obj->ob_type == info.enumWrapper) {
565 if ((PyObject*)obj->ob_type == info.enumWrapper) {
563 // we have a exact enum type match:
566 // we have a exact enum type match:
564 val = PyInt_AS_LONG(obj);
567 val = PyInt_AS_LONG(obj);
565 ok = true;
568 ok = true;
566 } else if (!strict) {
569 } else if (!strict) {
567 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
570 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
568 // we want an integer overload to be taken first!
571 // we want an integer overload to be taken first!
569 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
572 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
570 }
573 }
571 if (ok) {
574 if (ok) {
572 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
575 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
573 return ptr;
576 return ptr;
574 } else {
577 } else {
575 return NULL;
578 return NULL;
576 }
579 }
577 }
580 }
578
581
579 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
582 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
580 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
583 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
581 if (info.name.startsWith("QList<")) {
584 if (info.name.startsWith("QList<")) {
582 QByteArray innerType = info.name.mid(6,info.name.length()-7);
585 QByteArray innerType = info.name.mid(6,info.name.length()-7);
583 if (innerType.endsWith("*")) {
586 if (innerType.endsWith("*")) {
584 innerType.truncate(innerType.length()-1);
587 innerType.truncate(innerType.length()-1);
585 static int id = QMetaType::type("QList<void*>");
588 static int id = QMetaType::type("QList<void*>");
586 if (!alreadyAllocatedCPPObject) {
589 if (!alreadyAllocatedCPPObject) {
587 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
590 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
588 ptr = (void*)((QVariant*)ptr)->constData();
591 ptr = (void*)((QVariant*)ptr)->constData();
589 } else {
592 } else {
590 ptr = alreadyAllocatedCPPObject;
593 ptr = alreadyAllocatedCPPObject;
591 }
594 }
592 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
595 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
593 if (ok) {
596 if (ok) {
594 return ptr;
597 return ptr;
595 } else {
598 } else {
596 return NULL;
599 return NULL;
597 }
600 }
598 }
601 }
599 }
602 }
600 }
603 }
601
604
602 // We only do this for registered type > QMetaType::User for performance reasons.
605 // We only do this for registered type > QMetaType::User for performance reasons.
603 if (info.typeId >= QMetaType::User) {
606 if (info.typeId >= QMetaType::User) {
604 // Maybe we have a special converter that is registered for that type:
607 // Maybe we have a special converter that is registered for that type:
605 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
608 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
606 if (converter) {
609 if (converter) {
607 if (!alreadyAllocatedCPPObject) {
610 if (!alreadyAllocatedCPPObject) {
608 // create a new empty variant of concrete type:
611 // create a new empty variant of concrete type:
609 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
612 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
610 ptr = (void*)((QVariant*)ptr)->constData();
613 ptr = (void*)((QVariant*)ptr)->constData();
611 } else {
614 } else {
612 ptr = alreadyAllocatedCPPObject;
615 ptr = alreadyAllocatedCPPObject;
613 }
616 }
614 // now call the converter, passing the internal object of the variant
617 // now call the converter, passing the internal object of the variant
615 ok = (*converter)(obj, ptr, info.typeId, strict);
618 ok = (*converter)(obj, ptr, info.typeId, strict);
616 if (ok) {
619 if (ok) {
617 return ptr;
620 return ptr;
618 } else {
621 } else {
619 return NULL;
622 return NULL;
620 }
623 }
621 }
624 }
622 }
625 }
623 // if no type id is available, conversion to a QVariant makes no sense/is not possible
626 // if no type id is available, conversion to a QVariant makes no sense/is not possible
624 if (info.typeId != PythonQtMethodInfo::Unknown) {
627 if (info.typeId != PythonQtMethodInfo::Unknown) {
625 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
628 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
626 QVariant v = PyObjToQVariant(obj, info.typeId);
629 QVariant v = PyObjToQVariant(obj, info.typeId);
627 if (v.isValid()) {
630 if (v.isValid()) {
628 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
631 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
629 ptr = (void*)((QVariant*)ptr)->constData();
632 ptr = (void*)((QVariant*)ptr)->constData();
630 }
633 }
631 }
634 }
632 }
635 }
633 }
636 }
634 }
637 }
635 return ptr;
638 return ptr;
636 }
639 }
637
640
638
641
639 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
642 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
640 QStringList v;
643 QStringList v;
641 ok = false;
644 ok = false;
642 // if we are strict, we do not want to convert a string to a stringlist
645 // if we are strict, we do not want to convert a string to a stringlist
643 // (strings in python are detected to be sequences)
646 // (strings in python are detected to be sequences)
644 if (strict &&
647 if (strict &&
645 (val->ob_type == &PyString_Type ||
648 (val->ob_type == &PyString_Type ||
646 PyUnicode_Check(val))) {
649 PyUnicode_Check(val))) {
647 ok = false;
650 ok = false;
648 return v;
651 return v;
649 }
652 }
650 if (PySequence_Check(val)) {
653 if (PySequence_Check(val)) {
651 int count = PySequence_Size(val);
654 int count = PySequence_Size(val);
652 for (int i = 0;i<count;i++) {
655 for (int i = 0;i<count;i++) {
653 PyObject* value = PySequence_GetItem(val,i);
656 PyObject* value = PySequence_GetItem(val,i);
654 v.append(PyObjGetString(value,false,ok));
657 v.append(PyObjGetString(value,false,ok));
655 }
658 }
656 ok = true;
659 ok = true;
657 }
660 }
658 return v;
661 return v;
659 }
662 }
660
663
661 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
664 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
662 {
665 {
663 QString r;
666 QString r;
664 PyObject* str = PyObject_Repr(val);
667 PyObject* str = PyObject_Repr(val);
665 if (str) {
668 if (str) {
666 r = QString(PyString_AS_STRING(str));
669 r = QString(PyString_AS_STRING(str));
667 Py_DECREF(str);
670 Py_DECREF(str);
668 }
671 }
669 return r;
672 return r;
670 }
673 }
671
674
672 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
675 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
673 QString r;
676 QString r;
674 ok = true;
677 ok = true;
675 if (val->ob_type == &PyString_Type) {
678 if (val->ob_type == &PyString_Type) {
676 r = QString(PyString_AS_STRING(val));
679 r = QString(PyString_AS_STRING(val));
677 } else if (PyUnicode_Check(val)) {
680 } else if (PyUnicode_Check(val)) {
678 PyObject *ptmp = PyUnicode_AsUTF8String(val);
681 PyObject *ptmp = PyUnicode_AsUTF8String(val);
679 if(ptmp) {
682 if(ptmp) {
680 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
683 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
681 Py_DECREF(ptmp);
684 Py_DECREF(ptmp);
682 }
685 }
683 } else if (!strict) {
686 } else if (!strict) {
684 // EXTRA: could also use _Unicode, but why should we?
687 // EXTRA: could also use _Unicode, but why should we?
685 PyObject* str = PyObject_Str(val);
688 PyObject* str = PyObject_Str(val);
686 if (str) {
689 if (str) {
687 r = QString(PyString_AS_STRING(str));
690 r = QString(PyString_AS_STRING(str));
688 Py_DECREF(str);
691 Py_DECREF(str);
689 } else {
692 } else {
690 ok = false;
693 ok = false;
691 }
694 }
692 } else {
695 } else {
693 ok = false;
696 ok = false;
694 }
697 }
695 return r;
698 return r;
696 }
699 }
697
700
698 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
701 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
699 // TODO: support buffer objects in general
702 // TODO: support buffer objects in general
700 QByteArray r;
703 QByteArray r;
701 ok = true;
704 ok = true;
702 if (val->ob_type == &PyString_Type) {
705 if (val->ob_type == &PyString_Type) {
703 long size = PyString_GET_SIZE(val);
706 long size = PyString_GET_SIZE(val);
704 r = QByteArray(PyString_AS_STRING(val), size);
707 r = QByteArray(PyString_AS_STRING(val), size);
705 } else {
708 } else {
706 ok = false;
709 ok = false;
707 }
710 }
708 return r;
711 return r;
709 }
712 }
710
713
711 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
714 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
712 bool d = false;
715 bool d = false;
713 ok = false;
716 ok = false;
714 if (val == Py_False) {
717 if (val == Py_False) {
715 d = false;
718 d = false;
716 ok = true;
719 ok = true;
717 } else if (val == Py_True) {
720 } else if (val == Py_True) {
718 d = true;
721 d = true;
719 ok = true;
722 ok = true;
720 } else if (!strict) {
723 } else if (!strict) {
721 d = PyObjGetInt(val, false, ok)!=0;
724 d = PyObjGetInt(val, false, ok)!=0;
722 ok = true;
725 ok = true;
723 }
726 }
724 return d;
727 return d;
725 }
728 }
726
729
727 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
730 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
728 int d = 0;
731 int d = 0;
729 ok = true;
732 ok = true;
730 if (val->ob_type == &PyInt_Type) {
733 if (val->ob_type == &PyInt_Type) {
731 d = PyInt_AS_LONG(val);
734 d = PyInt_AS_LONG(val);
732 } else if (!strict) {
735 } else if (!strict) {
733 if (PyObject_TypeCheck(val, &PyInt_Type)) {
736 if (PyObject_TypeCheck(val, &PyInt_Type)) {
734 // support for derived int classes, e.g. for our enums
737 // support for derived int classes, e.g. for our enums
735 d = PyInt_AS_LONG(val);
738 d = PyInt_AS_LONG(val);
736 } else if (val->ob_type == &PyFloat_Type) {
739 } else if (val->ob_type == &PyFloat_Type) {
737 d = floor(PyFloat_AS_DOUBLE(val));
740 d = floor(PyFloat_AS_DOUBLE(val));
738 } else if (val->ob_type == &PyLong_Type) {
741 } else if (val->ob_type == &PyLong_Type) {
739 // handle error on overflow!
742 // handle error on overflow!
740 d = PyLong_AsLong(val);
743 d = PyLong_AsLong(val);
741 } else if (val == Py_False) {
744 } else if (val == Py_False) {
742 d = 0;
745 d = 0;
743 } else if (val == Py_True) {
746 } else if (val == Py_True) {
744 d = 1;
747 d = 1;
745 } else {
748 } else {
746 ok = false;
749 ok = false;
747 }
750 }
748 } else {
751 } else {
749 ok = false;
752 ok = false;
750 }
753 }
751 return d;
754 return d;
752 }
755 }
753
756
754 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
757 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
755 qint64 d = 0;
758 qint64 d = 0;
756 ok = true;
759 ok = true;
757 if (val->ob_type == &PyInt_Type) {
760 if (val->ob_type == &PyInt_Type) {
758 d = PyInt_AS_LONG(val);
761 d = PyInt_AS_LONG(val);
759 } else if (val->ob_type == &PyLong_Type) {
762 } else if (val->ob_type == &PyLong_Type) {
760 d = PyLong_AsLongLong(val);
763 d = PyLong_AsLongLong(val);
761 } else if (!strict) {
764 } else if (!strict) {
762 if (PyObject_TypeCheck(val, &PyInt_Type)) {
765 if (PyObject_TypeCheck(val, &PyInt_Type)) {
763 // support for derived int classes, e.g. for our enums
766 // support for derived int classes, e.g. for our enums
764 d = PyInt_AS_LONG(val);
767 d = PyInt_AS_LONG(val);
765 } else if (val->ob_type == &PyFloat_Type) {
768 } else if (val->ob_type == &PyFloat_Type) {
766 d = floor(PyFloat_AS_DOUBLE(val));
769 d = floor(PyFloat_AS_DOUBLE(val));
767 } else if (val == Py_False) {
770 } else if (val == Py_False) {
768 d = 0;
771 d = 0;
769 } else if (val == Py_True) {
772 } else if (val == Py_True) {
770 d = 1;
773 d = 1;
771 } else {
774 } else {
772 ok = false;
775 ok = false;
773 }
776 }
774 } else {
777 } else {
775 ok = false;
778 ok = false;
776 }
779 }
777 return d;
780 return d;
778 }
781 }
779
782
780 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
783 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
781 quint64 d = 0;
784 quint64 d = 0;
782 ok = true;
785 ok = true;
783 if (PyObject_TypeCheck(val, &PyInt_Type)) {
786 if (PyObject_TypeCheck(val, &PyInt_Type)) {
784 d = PyInt_AS_LONG(val);
787 d = PyInt_AS_LONG(val);
785 } else if (val->ob_type == &PyLong_Type) {
788 } else if (val->ob_type == &PyLong_Type) {
786 d = PyLong_AsLongLong(val);
789 d = PyLong_AsLongLong(val);
787 } else if (!strict) {
790 } else if (!strict) {
788 if (PyObject_TypeCheck(val, &PyInt_Type)) {
791 if (PyObject_TypeCheck(val, &PyInt_Type)) {
789 // support for derived int classes, e.g. for our enums
792 // support for derived int classes, e.g. for our enums
790 d = PyInt_AS_LONG(val);
793 d = PyInt_AS_LONG(val);
791 } else if (val->ob_type == &PyFloat_Type) {
794 } else if (val->ob_type == &PyFloat_Type) {
792 d = floor(PyFloat_AS_DOUBLE(val));
795 d = floor(PyFloat_AS_DOUBLE(val));
793 } else if (val == Py_False) {
796 } else if (val == Py_False) {
794 d = 0;
797 d = 0;
795 } else if (val == Py_True) {
798 } else if (val == Py_True) {
796 d = 1;
799 d = 1;
797 } else {
800 } else {
798 ok = false;
801 ok = false;
799 }
802 }
800 } else {
803 } else {
801 ok = false;
804 ok = false;
802 }
805 }
803 return d;
806 return d;
804 }
807 }
805
808
806 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
809 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
807 double d = 0;
810 double d = 0;
808 ok = true;
811 ok = true;
809 if (val->ob_type == &PyFloat_Type) {
812 if (val->ob_type == &PyFloat_Type) {
810 d = PyFloat_AS_DOUBLE(val);
813 d = PyFloat_AS_DOUBLE(val);
811 } else if (!strict) {
814 } else if (!strict) {
812 if (PyObject_TypeCheck(val, &PyInt_Type)) {
815 if (PyObject_TypeCheck(val, &PyInt_Type)) {
813 d = PyInt_AS_LONG(val);
816 d = PyInt_AS_LONG(val);
814 } else if (val->ob_type == &PyLong_Type) {
817 } else if (val->ob_type == &PyLong_Type) {
815 d = PyLong_AsLong(val);
818 d = PyLong_AsLong(val);
816 } else if (val == Py_False) {
819 } else if (val == Py_False) {
817 d = 0;
820 d = 0;
818 } else if (val == Py_True) {
821 } else if (val == Py_True) {
819 d = 1;
822 d = 1;
820 } else {
823 } else {
821 ok = false;
824 ok = false;
822 }
825 }
823 } else {
826 } else {
824 ok = false;
827 ok = false;
825 }
828 }
826 return d;
829 return d;
827 }
830 }
828
831
829 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
832 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
830 {
833 {
831 QVariant v;
834 QVariant v;
832 bool ok = true;
835 bool ok = true;
833
836
834 if (type==-1) {
837 if (type==-1) {
835 // no special type requested
838 // no special type requested
836 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
839 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
837 type = QVariant::String;
840 type = QVariant::String;
838 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
841 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
839 type = QVariant::Int;
842 type = QVariant::Int;
840 } else if (val->ob_type==&PyLong_Type) {
843 } else if (val->ob_type==&PyLong_Type) {
841 type = QVariant::LongLong;
844 type = QVariant::LongLong;
842 } else if (val->ob_type==&PyFloat_Type) {
845 } else if (val->ob_type==&PyFloat_Type) {
843 type = QVariant::Double;
846 type = QVariant::Double;
844 } else if (val == Py_False || val == Py_True) {
847 } else if (val == Py_False || val == Py_True) {
845 type = QVariant::Bool;
848 type = QVariant::Bool;
846 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
849 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
847 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
850 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
848 // c++ wrapper, check if the class names of the c++ objects match
851 // c++ wrapper, check if the class names of the c++ objects match
849 if (wrap->classInfo()->isCPPWrapper()) {
852 if (wrap->classInfo()->isCPPWrapper()) {
850 if (wrap->classInfo()->metaTypeId()>0) {
853 if (wrap->classInfo()->metaTypeId()>0) {
851 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
854 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
852 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
855 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
853 } else {
856 } else {
854 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
857 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
855 // the pointer here...
858 // the pointer here...
856 // is this worth anything? we loose the knowledge of the cpp object type
859 // is this worth anything? we loose the knowledge of the cpp object type
857 v = qVariantFromValue(wrap->_wrappedPtr);
860 v = qVariantFromValue(wrap->_wrappedPtr);
858 }
861 }
859 } else {
862 } else {
860 // this gives us a QObject pointer
863 // this gives us a QObject pointer
861 QObject* myObject = wrap->_obj;
864 QObject* myObject = wrap->_obj;
862 v = qVariantFromValue(myObject);
865 v = qVariantFromValue(myObject);
863 }
866 }
864 return v;
867 return v;
865 } else if (val->ob_type==&PyDict_Type) {
868 } else if (val->ob_type==&PyDict_Type) {
866 type = QVariant::Map;
869 type = QVariant::Map;
867 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
870 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
868 type = QVariant::List;
871 type = QVariant::List;
869 } else if (val == Py_None) {
872 } else if (val == Py_None) {
870 // none is invalid
873 // none is invalid
871 type = QVariant::Invalid;
874 type = QVariant::Invalid;
872 } else {
875 } else {
873 // this used to be:
876 // this used to be:
874 // type = QVariant::String;
877 // type = QVariant::String;
875 // but now we want to transport the Python Objects directly:
878 // but now we want to transport the Python Objects directly:
876 PythonQtObjectPtr o(val);
879 PythonQtObjectPtr o(val);
877 v = qVariantFromValue(o);
880 v = qVariantFromValue(o);
878 return v;
881 return v;
879 }
882 }
880 }
883 }
881 // special type request:
884 // special type request:
882 switch (type) {
885 switch (type) {
883 case QVariant::Invalid:
886 case QVariant::Invalid:
884 return v;
887 return v;
885 break;
888 break;
886 case QVariant::Int:
889 case QVariant::Int:
887 {
890 {
888 int d = PyObjGetInt(val, false, ok);
891 int d = PyObjGetInt(val, false, ok);
889 if (ok) return QVariant(d);
892 if (ok) return QVariant(d);
890 }
893 }
891 break;
894 break;
892 case QVariant::UInt:
895 case QVariant::UInt:
893 {
896 {
894 int d = PyObjGetInt(val, false,ok);
897 int d = PyObjGetInt(val, false,ok);
895 if (ok) v = QVariant((unsigned int)d);
898 if (ok) v = QVariant((unsigned int)d);
896 }
899 }
897 break;
900 break;
898 case QVariant::Bool:
901 case QVariant::Bool:
899 {
902 {
900 int d = PyObjGetBool(val,false,ok);
903 int d = PyObjGetBool(val,false,ok);
901 if (ok) v = QVariant((bool)(d!=0));
904 if (ok) v = QVariant((bool)(d!=0));
902 }
905 }
903 break;
906 break;
904 case QVariant::Double:
907 case QVariant::Double:
905 {
908 {
906 double d = PyObjGetDouble(val,false,ok);
909 double d = PyObjGetDouble(val,false,ok);
907 if (ok) v = QVariant(d);
910 if (ok) v = QVariant(d);
908 break;
911 break;
909 }
912 }
910 case QMetaType::Float:
913 case QMetaType::Float:
911 {
914 {
912 float d = (float) PyObjGetDouble(val,false,ok);
915 float d = (float) PyObjGetDouble(val,false,ok);
913 if (ok) v = qVariantFromValue(d);
916 if (ok) v = qVariantFromValue(d);
914 break;
917 break;
915 }
918 }
916 case QMetaType::Long:
919 case QMetaType::Long:
917 {
920 {
918 long d = (long) PyObjGetLongLong(val,false,ok);
921 long d = (long) PyObjGetLongLong(val,false,ok);
919 if (ok) v = qVariantFromValue(d);
922 if (ok) v = qVariantFromValue(d);
920 break;
923 break;
921 }
924 }
922 case QMetaType::ULong:
925 case QMetaType::ULong:
923 {
926 {
924 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
927 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
925 if (ok) v = qVariantFromValue(d);
928 if (ok) v = qVariantFromValue(d);
926 break;
929 break;
927 }
930 }
928 case QMetaType::LongLong:
931 case QMetaType::LongLong:
929 {
932 {
930 qint64 d = PyObjGetLongLong(val, false, ok);
933 qint64 d = PyObjGetLongLong(val, false, ok);
931 if (ok) v = qVariantFromValue(d);
934 if (ok) v = qVariantFromValue(d);
932 }
935 }
933 break;
936 break;
934 case QMetaType::ULongLong:
937 case QMetaType::ULongLong:
935 {
938 {
936 quint64 d = PyObjGetULongLong(val, false, ok);
939 quint64 d = PyObjGetULongLong(val, false, ok);
937 if (ok) v = qVariantFromValue(d);
940 if (ok) v = qVariantFromValue(d);
938 }
941 }
939 break;
942 break;
940 case QMetaType::Short:
943 case QMetaType::Short:
941 {
944 {
942 short d = (short) PyObjGetInt(val,false,ok);
945 short d = (short) PyObjGetInt(val,false,ok);
943 if (ok) v = qVariantFromValue(d);
946 if (ok) v = qVariantFromValue(d);
944 break;
947 break;
945 }
948 }
946 case QMetaType::UShort:
949 case QMetaType::UShort:
947 {
950 {
948 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
951 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
949 if (ok) v = qVariantFromValue(d);
952 if (ok) v = qVariantFromValue(d);
950 break;
953 break;
951 }
954 }
952 case QMetaType::Char:
955 case QMetaType::Char:
953 {
956 {
954 char d = (char) PyObjGetInt(val,false,ok);
957 char d = (char) PyObjGetInt(val,false,ok);
955 if (ok) v = qVariantFromValue(d);
958 if (ok) v = qVariantFromValue(d);
956 break;
959 break;
957 }
960 }
958 case QMetaType::UChar:
961 case QMetaType::UChar:
959 {
962 {
960 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
963 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
961 if (ok) v = qVariantFromValue(d);
964 if (ok) v = qVariantFromValue(d);
962 break;
965 break;
963 }
966 }
964
967
965 case QVariant::ByteArray:
968 case QVariant::ByteArray:
966 case QVariant::String:
969 case QVariant::String:
967 {
970 {
968 bool ok;
971 bool ok;
969 v = QVariant(PyObjGetString(val, false, ok));
972 v = QVariant(PyObjGetString(val, false, ok));
970 }
973 }
971 break;
974 break;
972
975
973 // these are important for MeVisLab
976 // these are important for MeVisLab
974 case QVariant::Map:
977 case QVariant::Map:
975 {
978 {
976 if (PyMapping_Check(val)) {
979 if (PyMapping_Check(val)) {
977 QMap<QString,QVariant> map;
980 QMap<QString,QVariant> map;
978 PyObject* items = PyMapping_Items(val);
981 PyObject* items = PyMapping_Items(val);
979 if (items) {
982 if (items) {
980 int count = PyList_Size(items);
983 int count = PyList_Size(items);
981 PyObject* value;
984 PyObject* value;
982 PyObject* key;
985 PyObject* key;
983 PyObject* tuple;
986 PyObject* tuple;
984 for (int i = 0;i<count;i++) {
987 for (int i = 0;i<count;i++) {
985 tuple = PyList_GetItem(items,i);
988 tuple = PyList_GetItem(items,i);
986 key = PyTuple_GetItem(tuple, 0);
989 key = PyTuple_GetItem(tuple, 0);
987 value = PyTuple_GetItem(tuple, 1);
990 value = PyTuple_GetItem(tuple, 1);
988 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
991 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
989 }
992 }
990 Py_DECREF(items);
993 Py_DECREF(items);
991 v = map;
994 v = map;
992 }
995 }
993 }
996 }
994 }
997 }
995 break;
998 break;
996 case QVariant::List:
999 case QVariant::List:
997 if (PySequence_Check(val)) {
1000 if (PySequence_Check(val)) {
998 QVariantList list;
1001 QVariantList list;
999 int count = PySequence_Size(val);
1002 int count = PySequence_Size(val);
1000 PyObject* value;
1003 PyObject* value;
1001 for (int i = 0;i<count;i++) {
1004 for (int i = 0;i<count;i++) {
1002 value = PySequence_GetItem(val,i);
1005 value = PySequence_GetItem(val,i);
1003 list.append(PyObjToQVariant(value, -1));
1006 list.append(PyObjToQVariant(value, -1));
1004 }
1007 }
1005 v = list;
1008 v = list;
1006 }
1009 }
1007 break;
1010 break;
1008 case QVariant::StringList:
1011 case QVariant::StringList:
1009 {
1012 {
1010 bool ok;
1013 bool ok;
1011 QStringList l = PyObjToStringList(val, false, ok);
1014 QStringList l = PyObjToStringList(val, false, ok);
1012 if (ok) {
1015 if (ok) {
1013 v = l;
1016 v = l;
1014 }
1017 }
1015 }
1018 }
1016 break;
1019 break;
1017
1020
1018 default:
1021 default:
1019 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1022 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1020 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1023 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1021 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1024 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1022 // construct a new variant from the C++ object if it has the same meta type
1025 // construct a new variant from the C++ object if it has the same meta type
1023 v = QVariant(type, wrap->_wrappedPtr);
1026 v = QVariant(type, wrap->_wrappedPtr);
1024 } else {
1027 } else {
1025 v = QVariant();
1028 v = QVariant();
1026 }
1029 }
1027 } else {
1030 } else {
1028 v = QVariant();
1031 v = QVariant();
1029 }
1032 }
1030 }
1033 }
1031 return v;
1034 return v;
1032 }
1035 }
1033
1036
1034 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1037 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1035 {
1038 {
1036 if (str.isNull()) {
1039 if (str.isNull()) {
1037 return PyString_FromString("");
1040 return PyString_FromString("");
1038 } else {
1041 } else {
1039 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1042 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1040 }
1043 }
1041 }
1044 }
1042
1045
1043 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1046 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1044 {
1047 {
1045 PyObject* result = PyTuple_New(list.count());
1048 PyObject* result = PyTuple_New(list.count());
1046 int i = 0;
1049 int i = 0;
1047 QString str;
1050 QString str;
1048 foreach (str, list) {
1051 foreach (str, list) {
1049 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1052 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1050 i++;
1053 i++;
1051 }
1054 }
1052 // why is the error state bad after this?
1055 // why is the error state bad after this?
1053 PyErr_Clear();
1056 PyErr_Clear();
1054 return result;
1057 return result;
1055 }
1058 }
1056
1059
1057 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1060 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1058 {
1061 {
1059 PyObject* result = PyList_New(list.count());
1062 PyObject* result = PyList_New(list.count());
1060 int i = 0;
1063 int i = 0;
1061 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1064 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1062 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1065 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1063 i++;
1066 i++;
1064 }
1067 }
1065 return result;
1068 return result;
1066 }
1069 }
1067
1070
1068 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1071 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1069 {
1072 {
1070 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1073 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1071 }
1074 }
1072
1075
1073 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1076 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1074 PyObject* result = PyDict_New();
1077 PyObject* result = PyDict_New();
1075 QVariantMap::const_iterator t = m.constBegin();
1078 QVariantMap::const_iterator t = m.constBegin();
1076 PyObject* key;
1079 PyObject* key;
1077 PyObject* val;
1080 PyObject* val;
1078 for (;t!=m.end();t++) {
1081 for (;t!=m.end();t++) {
1079 key = QStringToPyObject(t.key());
1082 key = QStringToPyObject(t.key());
1080 val = QVariantToPyObject(t.value());
1083 val = QVariantToPyObject(t.value());
1081 PyDict_SetItem(result, key, val);
1084 PyDict_SetItem(result, key, val);
1082 Py_DECREF(key);
1085 Py_DECREF(key);
1083 Py_DECREF(val);
1086 Py_DECREF(val);
1084 }
1087 }
1085 return result;
1088 return result;
1086 }
1089 }
1087
1090
1088 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1091 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1089 PyObject* result = PyTuple_New(l.count());
1092 PyObject* result = PyTuple_New(l.count());
1090 int i = 0;
1093 int i = 0;
1091 QVariant v;
1094 QVariant v;
1092 foreach (v, l) {
1095 foreach (v, l) {
1093 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1096 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1094 i++;
1097 i++;
1095 }
1098 }
1096 // why is the error state bad after this?
1099 // why is the error state bad after this?
1097 PyErr_Clear();
1100 PyErr_Clear();
1098 return result;
1101 return result;
1099 }
1102 }
1100
1103
1101 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1104 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1102 {
1105 {
1103 PyObject* result = PyTuple_New(list->count());
1106 PyObject* result = PyTuple_New(list->count());
1104 int i = 0;
1107 int i = 0;
1105 foreach (void* value, *list) {
1108 foreach (void* value, *list) {
1106 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1109 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1107 i++;
1110 i++;
1108 }
1111 }
1109 return result;
1112 return result;
1110 }
1113 }
1111
1114
1112 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1115 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1113 {
1116 {
1114 bool result = false;
1117 bool result = false;
1115 if (PySequence_Check(obj)) {
1118 if (PySequence_Check(obj)) {
1116 result = true;
1119 result = true;
1117 int count = PySequence_Size(obj);
1120 int count = PySequence_Size(obj);
1118 PyObject* value;
1121 PyObject* value;
1119 for (int i = 0;i<count;i++) {
1122 for (int i = 0;i<count;i++) {
1120 value = PySequence_GetItem(obj,i);
1123 value = PySequence_GetItem(obj,i);
1121 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1124 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1122 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1125 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1123 bool ok;
1126 bool ok;
1124 void* object = castWrapperTo(wrap, type, ok);
1127 void* object = castWrapperTo(wrap, type, ok);
1125 if (ok) {
1128 if (ok) {
1126 list->append(object);
1129 list->append(object);
1127 } else {
1130 } else {
1128 result = false;
1131 result = false;
1129 break;
1132 break;
1130 }
1133 }
1131 }
1134 }
1132 }
1135 }
1133 }
1136 }
1134 return result;
1137 return result;
1135 }
1138 }
1136
1139
1137 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1140 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1138 {
1141 {
1139 int idx = typeName.indexOf("<");
1142 int idx = typeName.indexOf("<");
1140 if (idx>0) {
1143 if (idx>0) {
1141 int idx2 = typeName.indexOf(">");
1144 int idx2 = typeName.indexOf(">");
1142 if (idx2>0) {
1145 if (idx2>0) {
1143 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1146 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1144 return QMetaType::type(innerType.constData());
1147 return QMetaType::type(innerType.constData());
1145 }
1148 }
1146 }
1149 }
1147 return QMetaType::Void;
1150 return QMetaType::Void;
1148 }
1151 }
1149
1152
1150
1153
1151 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1154 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1152 QString r;
1155 QString r;
1153 switch (type) {
1156 switch (type) {
1154 case QVariant::Size: {
1157 case QVariant::Size: {
1155 const QSize* s = static_cast<const QSize*>(data);
1158 const QSize* s = static_cast<const QSize*>(data);
1156 r = QString::number(s->width()) + ", " + QString::number(s->height());
1159 r = QString::number(s->width()) + ", " + QString::number(s->height());
1157 }
1160 }
1158 break;
1161 break;
1159 case QVariant::SizeF: {
1162 case QVariant::SizeF: {
1160 const QSizeF* s = static_cast<const QSizeF*>(data);
1163 const QSizeF* s = static_cast<const QSizeF*>(data);
1161 r = QString::number(s->width()) + ", " + QString::number(s->height());
1164 r = QString::number(s->width()) + ", " + QString::number(s->height());
1162 }
1165 }
1163 break;
1166 break;
1164 case QVariant::Point: {
1167 case QVariant::Point: {
1165 const QPoint* s = static_cast<const QPoint*>(data);
1168 const QPoint* s = static_cast<const QPoint*>(data);
1166 r = QString::number(s->x()) + ", " + QString::number(s->y());
1169 r = QString::number(s->x()) + ", " + QString::number(s->y());
1167 }
1170 }
1168 break;
1171 break;
1169 case QVariant::PointF: {
1172 case QVariant::PointF: {
1170 const QPointF* s = static_cast<const QPointF*>(data);
1173 const QPointF* s = static_cast<const QPointF*>(data);
1171 r = QString::number(s->x()) + ", " + QString::number(s->y());
1174 r = QString::number(s->x()) + ", " + QString::number(s->y());
1172 }
1175 }
1173 break;
1176 break;
1174 case QVariant::Rect: {
1177 case QVariant::Rect: {
1175 const QRect* s = static_cast<const QRect*>(data);
1178 const QRect* s = static_cast<const QRect*>(data);
1176 r = QString::number(s->x()) + ", " + QString::number(s->y());
1179 r = QString::number(s->x()) + ", " + QString::number(s->y());
1177 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1180 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1178 }
1181 }
1179 break;
1182 break;
1180 case QVariant::RectF: {
1183 case QVariant::RectF: {
1181 const QRectF* s = static_cast<const QRectF*>(data);
1184 const QRectF* s = static_cast<const QRectF*>(data);
1182 r = QString::number(s->x()) + ", " + QString::number(s->y());
1185 r = QString::number(s->x()) + ", " + QString::number(s->y());
1183 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1186 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1184 }
1187 }
1185 break;
1188 break;
1186 case QVariant::Date: {
1189 case QVariant::Date: {
1187 const QDate* s = static_cast<const QDate*>(data);
1190 const QDate* s = static_cast<const QDate*>(data);
1188 r = s->toString(Qt::ISODate);
1191 r = s->toString(Qt::ISODate);
1189 }
1192 }
1190 break;
1193 break;
1191 case QVariant::DateTime: {
1194 case QVariant::DateTime: {
1192 const QDateTime* s = static_cast<const QDateTime*>(data);
1195 const QDateTime* s = static_cast<const QDateTime*>(data);
1193 r = s->toString(Qt::ISODate);
1196 r = s->toString(Qt::ISODate);
1194 }
1197 }
1195 break;
1198 break;
1196 case QVariant::Time: {
1199 case QVariant::Time: {
1197 const QTime* s = static_cast<const QTime*>(data);
1200 const QTime* s = static_cast<const QTime*>(data);
1198 r = s->toString(Qt::ISODate);
1201 r = s->toString(Qt::ISODate);
1199 }
1202 }
1200 break;
1203 break;
1201 case QVariant::Pixmap:
1204 case QVariant::Pixmap:
1202 {
1205 {
1203 const QPixmap* s = static_cast<const QPixmap*>(data);
1206 const QPixmap* s = static_cast<const QPixmap*>(data);
1204 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1207 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1205 }
1208 }
1206 break;
1209 break;
1207 case QVariant::Image:
1210 case QVariant::Image:
1208 {
1211 {
1209 const QImage* s = static_cast<const QImage*>(data);
1212 const QImage* s = static_cast<const QImage*>(data);
1210 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1213 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1211 }
1214 }
1212 break;
1215 break;
1213 case QVariant::Url:
1216 case QVariant::Url:
1214 {
1217 {
1215 const QUrl* s = static_cast<const QUrl*>(data);
1218 const QUrl* s = static_cast<const QUrl*>(data);
1216 r = s->toString();
1219 r = s->toString();
1217 }
1220 }
1218 break;
1221 break;
1219 //TODO: add more printing for other variant types
1222 //TODO: add more printing for other variant types
1220 default:
1223 default:
1221 // this creates a copy, but that should not be expensive for typical simple variants
1224 // this creates a copy, but that should not be expensive for typical simple variants
1222 // (but we do not want to do this for our won user types!
1225 // (but we do not want to do this for our won user types!
1223 if (type>0 && type < (int)QVariant::UserType) {
1226 if (type>0 && type < (int)QVariant::UserType) {
1224 QVariant v(type, data);
1227 QVariant v(type, data);
1225 r = v.toString();
1228 r = v.toString();
1226 }
1229 }
1227 }
1230 }
1228 return r;
1231 return r;
1229 }
1232 }
@@ -1,62 +1,80
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtCppWrapperFactory.h
38 // \file PythonQtCppWrapperFactory.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-06
41 // \date 2006-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
47 the create() method.
47 the create() method.
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
49 */
49 */
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
51 {
51 {
52 public:
52 public:
53 PythonQtCppWrapperFactory() {};
53 PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
55
55
56 //! create a wrapper for the given object
56 //! create a wrapper for the given object
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
57 virtual QObject* create(const QByteArray& classname, void *ptr) = 0;
58
59 };
60
61 //! Factory interface for C++ classes that can be mapped directly from/to
62 //! Python with other means than PythonQt/QObjects.
63 class PYTHONQT_EXPORT PythonQtForeignWrapperFactory
64 {
65 public:
66 PythonQtForeignWrapperFactory() {};
67 virtual ~PythonQtForeignWrapperFactory() {};
68
69 //! create a Python object (with new reference count), wrapping the given \p ptr as class of type \p classname
70 //! Return NULL (and not Py_None) if the object could not be wrapped.
71 virtual PyObject* wrap(const QByteArray& classname, void *ptr) = 0;
72
73 //! unwrap the given object to a C++ object of type \p classname if possible
74 //! Return NULL otherwise.
75 virtual void* unwrap(const QByteArray& classname, PyObject* object) = 0;
58
76
59 };
77 };
60
78
61 #endif
79 #endif
62
80
General Comments 0
You need to be logged in to leave comments. Login now