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