##// END OF EJS Templates
florianlink -
r201:4443fddf8142
parent child
Show More
@@ -1,1796 +1,1892
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 "PythonQtSignal.h"
46 #include "PythonQtSignal.h"
47 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtSignalReceiver.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtStdIn.h"
49 #include "PythonQtStdIn.h"
50 #include "PythonQtStdOut.h"
50 #include "PythonQtStdOut.h"
51 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtCppWrapperFactory.h"
52 #include "PythonQtVariants.h"
52 #include "PythonQtVariants.h"
53 #include "PythonQtStdDecorators.h"
53 #include "PythonQtStdDecorators.h"
54 #include "PythonQtQFileImporter.h"
54 #include "PythonQtQFileImporter.h"
55 #include <pydebug.h>
55 #include <pydebug.h>
56 #include <vector>
56 #include <vector>
57
57
58 PythonQt* PythonQt::_self = NULL;
58 PythonQt* PythonQt::_self = NULL;
59 int PythonQt::_uniqueModuleCount = 0;
59 int PythonQt::_uniqueModuleCount = 0;
60
60
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
63
63
64
64
65 PyObject* PythonQtConvertFromStringRef(const void* inObject, int /*metaTypeId*/)
65 PyObject* PythonQtConvertFromStringRef(const void* inObject, int /*metaTypeId*/)
66 {
66 {
67 return PythonQtConv::QStringToPyObject(((QStringRef*)inObject)->toString());
67 return PythonQtConv::QStringToPyObject(((QStringRef*)inObject)->toString());
68 }
68 }
69
69
70 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
70 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
71 {
71 {
72 if (!_self) {
72 if (!_self) {
73 _self = new PythonQt(flags, pythonQtModuleName);
73 _self = new PythonQt(flags, pythonQtModuleName);
74
74
75 PythonQt::priv()->setupSharedLibrarySuffixes();
75 PythonQt::priv()->setupSharedLibrarySuffixes();
76
76
77 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
77 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
78 qRegisterMetaType<QList<QObject*> >("QList<void*>");
78 qRegisterMetaType<QList<QObject*> >("QList<void*>");
79
79
80 int stringRefId = qRegisterMetaType<QStringRef>("QStringRef");
80 int stringRefId = qRegisterMetaType<QStringRef>("QStringRef");
81 PythonQtConv::registerMetaTypeToPythonConverter(stringRefId, PythonQtConvertFromStringRef);
81 PythonQtConv::registerMetaTypeToPythonConverter(stringRefId, PythonQtConvertFromStringRef);
82
82
83 PythonQtRegisterToolClassesTemplateConverter(int);
83 PythonQtRegisterToolClassesTemplateConverter(int);
84 PythonQtRegisterToolClassesTemplateConverter(float);
84 PythonQtRegisterToolClassesTemplateConverter(float);
85 PythonQtRegisterToolClassesTemplateConverter(double);
85 PythonQtRegisterToolClassesTemplateConverter(double);
86 PythonQtRegisterToolClassesTemplateConverter(qint32);
86 PythonQtRegisterToolClassesTemplateConverter(qint32);
87 PythonQtRegisterToolClassesTemplateConverter(quint32);
87 PythonQtRegisterToolClassesTemplateConverter(quint32);
88 PythonQtRegisterToolClassesTemplateConverter(qint64);
88 PythonQtRegisterToolClassesTemplateConverter(qint64);
89 PythonQtRegisterToolClassesTemplateConverter(quint64);
89 PythonQtRegisterToolClassesTemplateConverter(quint64);
90 // TODO: which other POD types should be available for QList etc.
90 // TODO: which other POD types should be available for QList etc.
91
91
92 PythonQt_init_QtCoreBuiltin(NULL);
92 PythonQt_init_QtCoreBuiltin(NULL);
93 PythonQt_init_QtGuiBuiltin(NULL);
93 PythonQt_init_QtGuiBuiltin(NULL);
94
94
95 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
95 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
96 PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
96 PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
97
97
98 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
98 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
99 PythonQtRegisterToolClassesTemplateConverter(QDate);
99 PythonQtRegisterToolClassesTemplateConverter(QDate);
100 PythonQtRegisterToolClassesTemplateConverter(QTime);
100 PythonQtRegisterToolClassesTemplateConverter(QTime);
101 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
101 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
102 PythonQtRegisterToolClassesTemplateConverter(QUrl);
102 PythonQtRegisterToolClassesTemplateConverter(QUrl);
103 PythonQtRegisterToolClassesTemplateConverter(QLocale);
103 PythonQtRegisterToolClassesTemplateConverter(QLocale);
104 PythonQtRegisterToolClassesTemplateConverter(QRect);
104 PythonQtRegisterToolClassesTemplateConverter(QRect);
105 PythonQtRegisterToolClassesTemplateConverter(QRectF);
105 PythonQtRegisterToolClassesTemplateConverter(QRectF);
106 PythonQtRegisterToolClassesTemplateConverter(QSize);
106 PythonQtRegisterToolClassesTemplateConverter(QSize);
107 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
107 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
108 PythonQtRegisterToolClassesTemplateConverter(QLine);
108 PythonQtRegisterToolClassesTemplateConverter(QLine);
109 PythonQtRegisterToolClassesTemplateConverter(QLineF);
109 PythonQtRegisterToolClassesTemplateConverter(QLineF);
110 PythonQtRegisterToolClassesTemplateConverter(QPoint);
110 PythonQtRegisterToolClassesTemplateConverter(QPoint);
111 PythonQtRegisterToolClassesTemplateConverter(QPointF);
111 PythonQtRegisterToolClassesTemplateConverter(QPointF);
112 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
112 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
113
113
114 PythonQtRegisterToolClassesTemplateConverter(QFont);
114 PythonQtRegisterToolClassesTemplateConverter(QFont);
115 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
115 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
116 PythonQtRegisterToolClassesTemplateConverter(QBrush);
116 PythonQtRegisterToolClassesTemplateConverter(QBrush);
117 PythonQtRegisterToolClassesTemplateConverter(QColor);
117 PythonQtRegisterToolClassesTemplateConverter(QColor);
118 PythonQtRegisterToolClassesTemplateConverter(QPalette);
118 PythonQtRegisterToolClassesTemplateConverter(QPalette);
119 PythonQtRegisterToolClassesTemplateConverter(QIcon);
119 PythonQtRegisterToolClassesTemplateConverter(QIcon);
120 PythonQtRegisterToolClassesTemplateConverter(QImage);
120 PythonQtRegisterToolClassesTemplateConverter(QImage);
121 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
121 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
122 PythonQtRegisterToolClassesTemplateConverter(QRegion);
122 PythonQtRegisterToolClassesTemplateConverter(QRegion);
123 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
123 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
124 PythonQtRegisterToolClassesTemplateConverter(QCursor);
124 PythonQtRegisterToolClassesTemplateConverter(QCursor);
125 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
125 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
126 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
126 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
127 PythonQtRegisterToolClassesTemplateConverter(QPen);
127 PythonQtRegisterToolClassesTemplateConverter(QPen);
128 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
128 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
129 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
129 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
130 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
130 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
131
131
132
132
133 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
133 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
134 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
134 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
135 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
135 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
136 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
136 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
137 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
137 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
138 for (unsigned int i = 0;i<16; i++) {
138 for (unsigned int i = 0;i<16; i++) {
139 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
139 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
140 if (obj) {
140 if (obj) {
141 PyModule_AddObject(pack, names[i], obj);
141 PyModule_AddObject(pack, names[i], obj);
142 Py_INCREF(obj);
142 Py_INCREF(obj);
143 PyModule_AddObject(pack2, names[i], obj);
143 PyModule_AddObject(pack2, names[i], obj);
144 } else {
144 } else {
145 std::cerr << "method not found " << names[i];
145 std::cerr << "method not found " << names[i];
146 }
146 }
147 }
147 }
148 }
148 }
149 }
149 }
150
150
151 void PythonQt::cleanup()
151 void PythonQt::cleanup()
152 {
152 {
153 if (_self) {
153 if (_self) {
154 delete _self;
154 delete _self;
155 _self = NULL;
155 _self = NULL;
156 }
156 }
157 }
157 }
158
158
159 PythonQt* PythonQt::self() { return _self; }
159 PythonQt* PythonQt::self() { return _self; }
160
160
161 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
161 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
162 {
162 {
163 _p = new PythonQtPrivate;
163 _p = new PythonQtPrivate;
164 _p->_initFlags = flags;
164 _p->_initFlags = flags;
165
165
166 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
166 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
167
167
168 if ((flags & PythonAlreadyInitialized) == 0) {
168 if ((flags & PythonAlreadyInitialized) == 0) {
169 Py_SetProgramName(const_cast<char*>("PythonQt"));
169 Py_SetProgramName(const_cast<char*>("PythonQt"));
170 if (flags & IgnoreSiteModule) {
170 if (flags & IgnoreSiteModule) {
171 // this prevents the automatic importing of Python site files
171 // this prevents the automatic importing of Python site files
172 Py_NoSiteFlag = 1;
172 Py_NoSiteFlag = 1;
173 }
173 }
174 Py_Initialize();
174 Py_Initialize();
175 }
175 }
176
176
177 // add our own python object types for qt object slots
177 // add our own python object types for qt object slots
178 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
178 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
179 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
180 }
180 }
181 Py_INCREF(&PythonQtSlotFunction_Type);
181 Py_INCREF(&PythonQtSlotFunction_Type);
182
182
183 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
183 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
184 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
185 }
186 Py_INCREF(&PythonQtSignalFunction_Type);
186 Py_INCREF(&PythonQtSignalFunction_Type);
187
187
188 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
188 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
189 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
189 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
190 // add our own python object types for classes
190 // add our own python object types for classes
191 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
191 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
192 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
192 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
193 }
193 }
194 Py_INCREF(&PythonQtClassWrapper_Type);
194 Py_INCREF(&PythonQtClassWrapper_Type);
195
195
196 // add our own python object types for CPP instances
196 // add our own python object types for CPP instances
197 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
197 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
198 PythonQt::handleError();
198 PythonQt::handleError();
199 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
199 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
200 }
200 }
201 Py_INCREF(&PythonQtInstanceWrapper_Type);
201 Py_INCREF(&PythonQtInstanceWrapper_Type);
202
202
203 // add our own python object types for redirection of stdout
203 // add our own python object types for redirection of stdout
204 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
204 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
205 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
205 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
206 }
206 }
207 Py_INCREF(&PythonQtStdOutRedirectType);
207 Py_INCREF(&PythonQtStdOutRedirectType);
208
208
209 // add our own python object types for redirection of stdin
209 // add our own python object types for redirection of stdin
210 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
210 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
211 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
211 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
212 }
212 }
213 Py_INCREF(&PythonQtStdInRedirectType);
213 Py_INCREF(&PythonQtStdInRedirectType);
214
214
215 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
215 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
216
216
217 }
217 }
218
218
219 PythonQt::~PythonQt() {
219 PythonQt::~PythonQt() {
220 delete _p;
220 delete _p;
221 _p = NULL;
221 _p = NULL;
222 }
222 }
223
223
224 PythonQtPrivate::~PythonQtPrivate() {
224 PythonQtPrivate::~PythonQtPrivate() {
225 delete _defaultImporter;
225 delete _defaultImporter;
226 _defaultImporter = NULL;
226 _defaultImporter = NULL;
227
227
228 {
228 {
229 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
229 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
230 while (i.hasNext()) {
230 while (i.hasNext()) {
231 delete i.next().value();
231 delete i.next().value();
232 }
232 }
233 }
233 }
234 PythonQtConv::global_valueStorage.clear();
234 PythonQtConv::global_valueStorage.clear();
235 PythonQtConv::global_ptrStorage.clear();
235 PythonQtConv::global_ptrStorage.clear();
236 PythonQtConv::global_variantStorage.clear();
236 PythonQtConv::global_variantStorage.clear();
237
237
238 PythonQtMethodInfo::cleanupCachedMethodInfos();
238 PythonQtMethodInfo::cleanupCachedMethodInfos();
239 }
239 }
240
240
241 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
241 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
242 {
242 {
243 if (!callback)
243 if (!callback)
244 {
244 {
245 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
245 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
246 return;
246 return;
247 }
247 }
248
248
249 PythonQtObjectPtr sys;
249 PythonQtObjectPtr sys;
250 PythonQtObjectPtr in;
250 PythonQtObjectPtr in;
251 sys.setNewRef(PyImport_ImportModule("sys"));
251 sys.setNewRef(PyImport_ImportModule("sys"));
252
252
253 // Backup original 'sys.stdin' if not yet done
253 // Backup original 'sys.stdin' if not yet done
254 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
254 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
255 "sys.pythonqt_original_stdin = sys.stdin");
255 "sys.pythonqt_original_stdin = sys.stdin");
256
256
257 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
257 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
258 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
258 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
259 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
259 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
260 // replace the built in file objects with our own objects
260 // replace the built in file objects with our own objects
261 PyModule_AddObject(sys, "stdin", in);
261 PyModule_AddObject(sys, "stdin", in);
262
262
263 // Backup custom 'stdin' into 'pythonqt_stdin'
263 // Backup custom 'stdin' into 'pythonqt_stdin'
264 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
264 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
265 }
265 }
266
266
267 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
267 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
268 {
268 {
269 if (enabled)
269 if (enabled)
270 {
270 {
271 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
271 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
272 "sys.stdin = sys.pythonqt_stdin");
272 "sys.stdin = sys.pythonqt_stdin");
273 }
273 }
274 else
274 else
275 {
275 {
276 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
276 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
277 "sys.stdin = sys.pythonqt_original_stdin");
277 "sys.stdin = sys.pythonqt_original_stdin");
278 }
278 }
279 }
279 }
280
280
281 PythonQtImportFileInterface* PythonQt::importInterface()
281 PythonQtImportFileInterface* PythonQt::importInterface()
282 {
282 {
283 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
283 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
284 }
284 }
285
285
286 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
286 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
287 {
287 {
288 if (_self->_p->_noLongerWrappedCB) {
288 if (_self->_p->_noLongerWrappedCB) {
289 (*_self->_p->_noLongerWrappedCB)(o);
289 (*_self->_p->_noLongerWrappedCB)(o);
290 };
290 };
291 }
291 }
292
292
293 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
293 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
294 {
294 {
295 _p->registerClass(metaobject, package, wrapperCreator, shell);
295 _p->registerClass(metaobject, package, wrapperCreator, shell);
296 }
296 }
297
297
298 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
298 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
299 {
299 {
300 // we register all classes in the hierarchy
300 // we register all classes in the hierarchy
301 const QMetaObject* m = metaobject;
301 const QMetaObject* m = metaobject;
302 bool first = true;
302 bool first = true;
303 while (m) {
303 while (m) {
304 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
304 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
305 if (!info->pythonQtClassWrapper()) {
305 if (!info->pythonQtClassWrapper()) {
306 info->setTypeSlots(typeSlots);
306 info->setTypeSlots(typeSlots);
307 info->setupQObject(m);
307 info->setupQObject(m);
308 createPythonQtClassWrapper(info, package, module);
308 createPythonQtClassWrapper(info, package, module);
309 if (m->superClass()) {
309 if (m->superClass()) {
310 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
310 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
311 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
311 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
312 }
312 }
313 } else if (first && module) {
313 } else if (first && module) {
314 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
314 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
315 // since it might have been placed into "private" earlier on.
315 // since it might have been placed into "private" earlier on.
316 // If the wrapper was already added to module before, it is just readded, which does no harm.
316 // If the wrapper was already added to module before, it is just readded, which does no harm.
317 PyObject* classWrapper = info->pythonQtClassWrapper();
317 PyObject* classWrapper = info->pythonQtClassWrapper();
318 // AddObject steals a reference, so we need to INCREF
318 // AddObject steals a reference, so we need to INCREF
319 Py_INCREF(classWrapper);
319 Py_INCREF(classWrapper);
320 PyModule_AddObject(module, info->className(), classWrapper);
320 PyModule_AddObject(module, info->className(), classWrapper);
321 }
321 }
322 if (first) {
322 if (first) {
323 first = false;
323 first = false;
324 if (wrapperCreator) {
324 if (wrapperCreator) {
325 info->setDecoratorProvider(wrapperCreator);
325 info->setDecoratorProvider(wrapperCreator);
326 }
326 }
327 if (shell) {
327 if (shell) {
328 info->setShellSetInstanceWrapperCB(shell);
328 info->setShellSetInstanceWrapperCB(shell);
329 }
329 }
330 }
330 }
331 m = m->superClass();
331 m = m->superClass();
332 }
332 }
333 }
333 }
334
334
335 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
335 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
336 {
336 {
337 PyObject* pack = module?module:packageByName(package);
337 PyObject* pack = module?module:packageByName(package);
338 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
338 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
339 PyModule_AddObject(pack, info->className(), pyobj);
339 PyModule_AddObject(pack, info->className(), pyobj);
340 if (!module && package && strncmp(package,"Qt",2)==0) {
340 if (!module && package && strncmp(package,"Qt",2)==0) {
341 // since PyModule_AddObject steals the reference, we need a incref once more...
341 // since PyModule_AddObject steals the reference, we need a incref once more...
342 Py_INCREF(pyobj);
342 Py_INCREF(pyobj);
343 // put all qt objects into Qt as well
343 // put all qt objects into Qt as well
344 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
344 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
345 }
345 }
346 info->setPythonQtClassWrapper(pyobj);
346 info->setPythonQtClassWrapper(pyobj);
347 }
347 }
348
348
349 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
349 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
350 {
350 {
351 if (!obj) {
351 if (!obj) {
352 Py_INCREF(Py_None);
352 Py_INCREF(Py_None);
353 return Py_None;
353 return Py_None;
354 }
354 }
355 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
355 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
356 if (wrap && wrap->_wrappedPtr) {
356 if (wrap && wrap->_wrappedPtr) {
357 // uh oh, we want to wrap a QObject, but have a C++ wrapper at that
357 // uh oh, we want to wrap a QObject, but have a C++ wrapper at that
358 // address, so probably that C++ wrapper has been deleted earlier and
358 // address, so probably that C++ wrapper has been deleted earlier and
359 // now we see a QObject with the same address.
359 // now we see a QObject with the same address.
360 // Do not use the old wrapper anymore.
360 // Do not use the old wrapper anymore.
361 wrap = NULL;
361 wrap = NULL;
362 }
362 }
363 if (!wrap) {
363 if (!wrap) {
364 // smuggling it in...
364 // smuggling it in...
365 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
365 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
366 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
366 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
367 registerClass(obj->metaObject());
367 registerClass(obj->metaObject());
368 classInfo = _knownClassInfos.value(obj->metaObject()->className());
368 classInfo = _knownClassInfos.value(obj->metaObject()->className());
369 }
369 }
370 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
370 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
371 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
371 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
372 } else {
372 } else {
373 Py_INCREF(wrap);
373 Py_INCREF(wrap);
374 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
374 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
375 }
375 }
376 return (PyObject*)wrap;
376 return (PyObject*)wrap;
377 }
377 }
378
378
379 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
379 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
380 {
380 {
381 if (!ptr) {
381 if (!ptr) {
382 Py_INCREF(Py_None);
382 Py_INCREF(Py_None);
383 return Py_None;
383 return Py_None;
384 }
384 }
385
385
386 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
386 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
387 PythonQtInstanceWrapper* possibleStillAliveWrapper = NULL;
387 PythonQtInstanceWrapper* possibleStillAliveWrapper = NULL;
388 if (wrap && wrap->_wrappedPtr) {
388 if (wrap && wrap->_wrappedPtr) {
389 // we have a previous C++ wrapper... if the wrapper is for a C++ object,
389 // we have a previous C++ wrapper... if the wrapper is for a C++ object,
390 // we are not sure if it may have been deleted earlier and we just see the same C++
390 // we are not sure if it may have been deleted earlier and we just see the same C++
391 // pointer once again. To make sure that we do not reuse a wrapper of the wrong type,
391 // pointer once again. To make sure that we do not reuse a wrapper of the wrong type,
392 // we compare the classInfo() pointer and only reuse the wrapper if it has the same
392 // we compare the classInfo() pointer and only reuse the wrapper if it has the same
393 // info. This is only needed for non-QObjects, since we know it when a QObject gets deleted.
393 // info. This is only needed for non-QObjects, since we know it when a QObject gets deleted.
394 possibleStillAliveWrapper = wrap;
394 possibleStillAliveWrapper = wrap;
395 wrap = NULL;
395 wrap = NULL;
396 }
396 }
397 if (!wrap) {
397 if (!wrap) {
398 PythonQtClassInfo* info = _knownClassInfos.value(name);
398 PythonQtClassInfo* info = _knownClassInfos.value(name);
399 if (!info) {
399 if (!info) {
400 // maybe it is a PyObject, which we can return directly
400 // maybe it is a PyObject, which we can return directly
401 if (name == "PyObject") {
401 if (name == "PyObject") {
402 PyObject* p = (PyObject*)ptr;
402 PyObject* p = (PyObject*)ptr;
403 Py_INCREF(p);
403 Py_INCREF(p);
404 return p;
404 return p;
405 }
405 }
406
406
407 // we do not know the metaobject yet, but we might know it by its name:
407 // we do not know the metaobject yet, but we might know it by its name:
408 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
408 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
409 // yes, we know it, so we can convert to QObject
409 // yes, we know it, so we can convert to QObject
410 QObject* qptr = (QObject*)ptr;
410 QObject* qptr = (QObject*)ptr;
411 registerClass(qptr->metaObject());
411 registerClass(qptr->metaObject());
412 info = _knownClassInfos.value(qptr->metaObject()->className());
412 info = _knownClassInfos.value(qptr->metaObject()->className());
413 }
413 }
414 }
414 }
415 if (info && info->isQObject()) {
415 if (info && info->isQObject()) {
416 QObject* qptr = (QObject*)ptr;
416 QObject* qptr = (QObject*)ptr;
417 // if the object is a derived object, we want to switch the class info to the one of the derived class:
417 // if the object is a derived object, we want to switch the class info to the one of the derived class:
418 if (name!=(qptr->metaObject()->className())) {
418 if (name!=(qptr->metaObject()->className())) {
419 info = _knownClassInfos.value(qptr->metaObject()->className());
419 info = _knownClassInfos.value(qptr->metaObject()->className());
420 if (!info) {
420 if (!info) {
421 registerClass(qptr->metaObject());
421 registerClass(qptr->metaObject());
422 info = _knownClassInfos.value(qptr->metaObject()->className());
422 info = _knownClassInfos.value(qptr->metaObject()->className());
423 }
423 }
424 }
424 }
425 wrap = createNewPythonQtInstanceWrapper(qptr, info);
425 wrap = createNewPythonQtInstanceWrapper(qptr, info);
426 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
426 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
427 return (PyObject*)wrap;
427 return (PyObject*)wrap;
428 }
428 }
429
429
430 // not a known QObject, try to wrap via foreign wrapper factories
430 // not a known QObject, try to wrap via foreign wrapper factories
431 PyObject* foreignWrapper = NULL;
431 PyObject* foreignWrapper = NULL;
432 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
432 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
433 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
433 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
434 if (foreignWrapper) {
434 if (foreignWrapper) {
435 return foreignWrapper;
435 return foreignWrapper;
436 }
436 }
437 }
437 }
438
438
439 // not a known QObject, so try our wrapper factory:
439 // not a known QObject, so try our wrapper factory:
440 QObject* wrapper = NULL;
440 QObject* wrapper = NULL;
441 for (int i=0; i<_cppWrapperFactories.size(); i++) {
441 for (int i=0; i<_cppWrapperFactories.size(); i++) {
442 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
442 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
443 if (wrapper) {
443 if (wrapper) {
444 break;
444 break;
445 }
445 }
446 }
446 }
447
447
448 if (info) {
448 if (info) {
449 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
449 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
450 ptr = info->castDownIfPossible(ptr, &info);
450 ptr = info->castDownIfPossible(ptr, &info);
451
451
452 // if downcasting found out that the object is a QObject,
452 // if downcasting found out that the object is a QObject,
453 // handle it like one:
453 // handle it like one:
454 if (info && info->isQObject()) {
454 if (info && info->isQObject()) {
455 QObject* qptr = (QObject*)ptr;
455 QObject* qptr = (QObject*)ptr;
456 // if the object is a derived object, we want to switch the class info to the one of the derived class:
456 // if the object is a derived object, we want to switch the class info to the one of the derived class:
457 if (name!=(qptr->metaObject()->className())) {
457 if (name!=(qptr->metaObject()->className())) {
458 registerClass(qptr->metaObject());
458 registerClass(qptr->metaObject());
459 info = _knownClassInfos.value(qptr->metaObject()->className());
459 info = _knownClassInfos.value(qptr->metaObject()->className());
460 }
460 }
461 wrap = createNewPythonQtInstanceWrapper(qptr, info);
461 wrap = createNewPythonQtInstanceWrapper(qptr, info);
462 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
462 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
463 return (PyObject*)wrap;
463 return (PyObject*)wrap;
464 }
464 }
465 }
465 }
466
466
467 if (!info || info->pythonQtClassWrapper()==NULL) {
467 if (!info || info->pythonQtClassWrapper()==NULL) {
468 // still unknown, register as CPP class
468 // still unknown, register as CPP class
469 registerCPPClass(name.constData());
469 registerCPPClass(name.constData());
470 info = _knownClassInfos.value(name);
470 info = _knownClassInfos.value(name);
471 }
471 }
472 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
472 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
473 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
473 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
474 info->setMetaObject(wrapper->metaObject());
474 info->setMetaObject(wrapper->metaObject());
475 }
475 }
476
476
477 if (possibleStillAliveWrapper && possibleStillAliveWrapper->classInfo() == info) {
477 if (possibleStillAliveWrapper && possibleStillAliveWrapper->classInfo() == info) {
478 wrap = possibleStillAliveWrapper;
478 wrap = possibleStillAliveWrapper;
479 Py_INCREF(wrap);
479 Py_INCREF(wrap);
480 } else {
480 } else {
481 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
481 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
482 }
482 }
483 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
483 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
484 } else {
484 } else {
485 Py_INCREF(wrap);
485 Py_INCREF(wrap);
486 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
486 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
487 }
487 }
488 return (PyObject*)wrap;
488 return (PyObject*)wrap;
489 }
489 }
490
490
491 PyObject* PythonQtPrivate::dummyTuple() {
491 PyObject* PythonQtPrivate::dummyTuple() {
492 static PyObject* dummyTuple = NULL;
492 static PyObject* dummyTuple = NULL;
493 if (dummyTuple==NULL) {
493 if (dummyTuple==NULL) {
494 dummyTuple = PyTuple_New(1);
494 dummyTuple = PyTuple_New(1);
495 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
495 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
496 }
496 }
497 return dummyTuple;
497 return dummyTuple;
498 }
498 }
499
499
500
500
501 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
501 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
502 // call the associated class type to create a new instance...
502 // call the associated class type to create a new instance...
503 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
503 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
504
504
505 result->setQObject(obj);
505 result->setQObject(obj);
506 result->_wrappedPtr = wrappedPtr;
506 result->_wrappedPtr = wrappedPtr;
507 result->_ownedByPythonQt = false;
507 result->_ownedByPythonQt = false;
508 result->_useQMetaTypeDestroy = false;
508 result->_useQMetaTypeDestroy = false;
509
509
510 if (wrappedPtr) {
510 if (wrappedPtr) {
511 _wrappedObjects.insert(wrappedPtr, result);
511 _wrappedObjects.insert(wrappedPtr, result);
512 } else {
512 } else {
513 _wrappedObjects.insert(obj, result);
513 _wrappedObjects.insert(obj, result);
514 if (obj->parent()== NULL && _wrappedCB) {
514 if (obj->parent()== NULL && _wrappedCB) {
515 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
515 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
516 (*_wrappedCB)(obj);
516 (*_wrappedCB)(obj);
517 }
517 }
518 }
518 }
519 return result;
519 return result;
520 }
520 }
521
521
522 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
522 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
523 PythonQtClassWrapper* result;
523 PythonQtClassWrapper* result;
524
524
525 PyObject* className = PyString_FromString(info->className());
525 PyObject* className = PyString_FromString(info->className());
526
526
527 PyObject* baseClasses = PyTuple_New(1);
527 PyObject* baseClasses = PyTuple_New(1);
528 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
528 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
529
529
530 PyObject* typeDict = PyDict_New();
530 PyObject* typeDict = PyDict_New();
531 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
531 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
532 PyDict_SetItemString(typeDict, "__module__", moduleName);
532 PyDict_SetItemString(typeDict, "__module__", moduleName);
533
533
534 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
534 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
535
535
536 // set the class info so that PythonQtClassWrapper_new can read it
536 // set the class info so that PythonQtClassWrapper_new can read it
537 _currentClassInfoForClassWrapperCreation = info;
537 _currentClassInfoForClassWrapperCreation = info;
538 // create the new type object by calling the type
538 // create the new type object by calling the type
539 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
539 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
540
540
541 Py_DECREF(baseClasses);
541 Py_DECREF(baseClasses);
542 Py_DECREF(typeDict);
542 Py_DECREF(typeDict);
543 Py_DECREF(args);
543 Py_DECREF(args);
544 Py_DECREF(className);
544 Py_DECREF(className);
545
545
546 return result;
546 return result;
547 }
547 }
548
548
549 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
549 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
550 {
550 {
551 PyObject* args = Py_BuildValue("(i)", enumValue);
551 PyObject* args = Py_BuildValue("(i)", enumValue);
552 PyObject* result = PyObject_Call(enumType, args, NULL);
552 PyObject* result = PyObject_Call(enumType, args, NULL);
553 Py_DECREF(args);
553 Py_DECREF(args);
554 return result;
554 return result;
555 }
555 }
556
556
557 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
557 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
558 PyObject* result;
558 PyObject* result;
559
559
560 PyObject* className = PyString_FromString(enumName);
560 PyObject* className = PyString_FromString(enumName);
561
561
562 PyObject* baseClasses = PyTuple_New(1);
562 PyObject* baseClasses = PyTuple_New(1);
563 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
563 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
564
564
565 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
565 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
566 PyObject* typeDict = PyDict_New();
566 PyObject* typeDict = PyDict_New();
567 PyDict_SetItemString(typeDict, "__module__", module);
567 PyDict_SetItemString(typeDict, "__module__", module);
568
568
569 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
569 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
570
570
571 // create the new int derived type object by calling the core type
571 // create the new int derived type object by calling the core type
572 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
572 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
573
573
574 Py_DECREF(baseClasses);
574 Py_DECREF(baseClasses);
575 Py_DECREF(typeDict);
575 Py_DECREF(typeDict);
576 Py_DECREF(args);
576 Py_DECREF(args);
577 Py_DECREF(className);
577 Py_DECREF(className);
578
578
579 return result;
579 return result;
580 }
580 }
581
581
582 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
582 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
583 {
583 {
584 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
584 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
585 if (!r) {
585 if (!r) {
586 r = new PythonQtSignalReceiver(obj);
586 r = new PythonQtSignalReceiver(obj);
587 _p->_signalReceivers.insert(obj, r);
587 _p->_signalReceivers.insert(obj, r);
588 }
588 }
589 return r;
589 return r;
590 }
590 }
591
591
592 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
592 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
593 {
593 {
594 bool flag = false;
594 bool flag = false;
595 PythonQtObjectPtr callable = lookupCallable(module, objectname);
595 PythonQtObjectPtr callable = lookupCallable(module, objectname);
596 if (callable) {
596 if (callable) {
597 PythonQtSignalReceiver* r = getSignalReceiver(obj);
597 PythonQtSignalReceiver* r = getSignalReceiver(obj);
598 flag = r->addSignalHandler(signal, callable);
598 flag = r->addSignalHandler(signal, callable);
599 if (!flag) {
599 if (!flag) {
600 // signal not found
600 // signal not found
601 }
601 }
602 } else {
602 } else {
603 // callable not found
603 // callable not found
604 }
604 }
605 return flag;
605 return flag;
606 }
606 }
607
607
608 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
608 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
609 {
609 {
610 bool flag = false;
610 bool flag = false;
611 PythonQtSignalReceiver* r = getSignalReceiver(obj);
611 PythonQtSignalReceiver* r = getSignalReceiver(obj);
612 if (r) {
612 if (r) {
613 flag = r->addSignalHandler(signal, receiver);
613 flag = r->addSignalHandler(signal, receiver);
614 }
614 }
615 return flag;
615 return flag;
616 }
616 }
617
617
618 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
618 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
619 {
619 {
620 bool flag = false;
620 bool flag = false;
621 PythonQtObjectPtr callable = lookupCallable(module, objectname);
621 PythonQtObjectPtr callable = lookupCallable(module, objectname);
622 if (callable) {
622 if (callable) {
623 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
623 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
624 if (r) {
624 if (r) {
625 flag = r->removeSignalHandler(signal, callable);
625 flag = r->removeSignalHandler(signal, callable);
626 }
626 }
627 } else {
627 } else {
628 // callable not found
628 // callable not found
629 }
629 }
630 return flag;
630 return flag;
631 }
631 }
632
632
633 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
633 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
634 {
634 {
635 bool flag = false;
635 bool flag = false;
636 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
636 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
637 if (r) {
637 if (r) {
638 flag = r->removeSignalHandler(signal, receiver);
638 flag = r->removeSignalHandler(signal, receiver);
639 }
639 }
640 return flag;
640 return flag;
641 }
641 }
642
642
643 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
643 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
644 {
644 {
645 PythonQtObjectPtr p = lookupObject(module, name);
645 PythonQtObjectPtr p = lookupObject(module, name);
646 if (p) {
646 if (p) {
647 if (PyCallable_Check(p)) {
647 if (PyCallable_Check(p)) {
648 return p;
648 return p;
649 }
649 }
650 }
650 }
651 PyErr_Clear();
651 PyErr_Clear();
652 return NULL;
652 return NULL;
653 }
653 }
654
654
655 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
655 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
656 {
656 {
657 QStringList l = name.split('.');
657 QStringList l = name.split('.');
658 PythonQtObjectPtr p = module;
658 PythonQtObjectPtr p = module;
659 PythonQtObjectPtr prev;
659 PythonQtObjectPtr prev;
660 QByteArray b;
660 QByteArray b;
661 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
661 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
662 prev = p;
662 prev = p;
663 b = (*i).toLatin1();
663 b = (*i).toLatin1();
664 if (PyDict_Check(p)) {
664 if (PyDict_Check(p)) {
665 p = PyDict_GetItemString(p, b.data());
665 p = PyDict_GetItemString(p, b.data());
666 } else {
666 } else {
667 p.setNewRef(PyObject_GetAttrString(p, b.data()));
667 p.setNewRef(PyObject_GetAttrString(p, b.data()));
668 }
668 }
669 }
669 }
670 PyErr_Clear();
670 PyErr_Clear();
671 return p;
671 return p;
672 }
672 }
673
673
674 PythonQtObjectPtr PythonQt::getMainModule() {
674 PythonQtObjectPtr PythonQt::getMainModule() {
675 //both borrowed
675 //both borrowed
676 PythonQtObjectPtr dict = PyImport_GetModuleDict();
676 PythonQtObjectPtr dict = PyImport_GetModuleDict();
677 return PyDict_GetItemString(dict, "__main__");
677 return PyDict_GetItemString(dict, "__main__");
678 }
678 }
679
679
680 PythonQtObjectPtr PythonQt::importModule(const QString& name)
680 PythonQtObjectPtr PythonQt::importModule(const QString& name)
681 {
681 {
682 PythonQtObjectPtr mod;
682 PythonQtObjectPtr mod;
683 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
683 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
684 return mod;
684 return mod;
685 }
685 }
686
686
687
687
688 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
688 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
689 QVariant result;
689 QVariant result;
690 clearError();
690 if (pycode) {
691 if (pycode) {
691 PyObject* dict = NULL;
692 PyObject* dict = NULL;
692 PyObject* globals = NULL;
693 PyObject* globals = NULL;
693 if (PyModule_Check(object)) {
694 if (PyModule_Check(object)) {
694 dict = PyModule_GetDict(object);
695 dict = PyModule_GetDict(object);
695 globals = dict;
696 globals = dict;
696 } else if (PyDict_Check(object)) {
697 } else if (PyDict_Check(object)) {
697 dict = object;
698 dict = object;
698 globals = dict;
699 globals = dict;
699 } else {
700 } else {
700 dict = PyObject_GetAttrString(object, "__dict__");
701 dict = PyObject_GetAttrString(object, "__dict__");
701 globals = PyObject_GetAttrString(PyImport_ImportModule(PyString_AS_STRING(PyObject_GetAttrString(object, "__module__"))),"__dict__");
702 globals = PyObject_GetAttrString(PyImport_ImportModule(PyString_AS_STRING(PyObject_GetAttrString(object, "__module__"))),"__dict__");
702 }
703 }
703 PyObject* r = NULL;
704 PyObject* r = NULL;
704 if (dict) {
705 if (dict) {
705 r = PyEval_EvalCode((PyCodeObject*)pycode, globals , dict);
706 r = PyEval_EvalCode((PyCodeObject*)pycode, globals , dict);
706 }
707 }
707 if (r) {
708 if (r) {
708 result = PythonQtConv::PyObjToQVariant(r);
709 result = PythonQtConv::PyObjToQVariant(r);
709 Py_DECREF(r);
710 Py_DECREF(r);
710 } else {
711 } else {
711 handleError();
712 handleError();
712 }
713 }
713 } else {
714 } else {
714 handleError();
715 handleError();
715 }
716 }
716 return result;
717 return result;
717 }
718 }
718
719
719 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
720 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
720 {
721 {
721 QVariant result;
722 QVariant result;
722 PythonQtObjectPtr p;
723 PythonQtObjectPtr p;
723 PyObject* dict = NULL;
724 PyObject* dict = NULL;
725 clearError();
724 if (PyModule_Check(object)) {
726 if (PyModule_Check(object)) {
725 dict = PyModule_GetDict(object);
727 dict = PyModule_GetDict(object);
726 } else if (PyDict_Check(object)) {
728 } else if (PyDict_Check(object)) {
727 dict = object;
729 dict = object;
728 }
730 }
729 if (dict) {
731 if (dict) {
730 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
732 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
731 }
733 }
732 if (p) {
734 if (p) {
733 result = PythonQtConv::PyObjToQVariant(p);
735 result = PythonQtConv::PyObjToQVariant(p);
734 } else {
736 } else {
735 handleError();
737 handleError();
736 }
738 }
737 return result;
739 return result;
738 }
740 }
739
741
740 void PythonQt::evalFile(PyObject* module, const QString& filename)
742 void PythonQt::evalFile(PyObject* module, const QString& filename)
741 {
743 {
742 PythonQtObjectPtr code = parseFile(filename);
744 PythonQtObjectPtr code = parseFile(filename);
745 clearError();
743 if (code) {
746 if (code) {
744 evalCode(module, code);
747 evalCode(module, code);
745 } else {
748 } else {
746 handleError();
749 handleError();
747 }
750 }
748 }
751 }
749
752
750 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
753 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
751 {
754 {
752 PythonQtObjectPtr p;
755 PythonQtObjectPtr p;
753 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
756 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
757 clearError();
754 if (!p) {
758 if (!p) {
755 handleError();
759 handleError();
756 }
760 }
757 return p;
761 return p;
758 }
762 }
759
763
760 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
764 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
761 {
765 {
762 PythonQtObjectPtr code = parseFile(filename);
766 PythonQtObjectPtr code = parseFile(filename);
763 PythonQtObjectPtr module = _p->createModule(name, code);
767 PythonQtObjectPtr module = _p->createModule(name, code);
764 return module;
768 return module;
765 }
769 }
766
770
767 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
771 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
768 {
772 {
769 PyErr_Clear();
773 PyErr_Clear();
770 QString scriptCode = script;
774 QString scriptCode = script;
771 if (scriptCode.isEmpty()) {
775 if (scriptCode.isEmpty()) {
772 // we always need at least a linefeed
776 // we always need at least a linefeed
773 scriptCode = "\n";
777 scriptCode = "\n";
774 }
778 }
775 PythonQtObjectPtr pycode;
779 PythonQtObjectPtr pycode;
776 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
780 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
777 PythonQtObjectPtr module = _p->createModule(name, pycode);
781 PythonQtObjectPtr module = _p->createModule(name, pycode);
778 return module;
782 return module;
779 }
783 }
780
784
781 PythonQtObjectPtr PythonQt::createUniqueModule()
785 PythonQtObjectPtr PythonQt::createUniqueModule()
782 {
786 {
783 static QString pyQtStr("PythonQt_module");
787 static QString pyQtStr("PythonQt_module");
784 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
788 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
785 return createModuleFromScript(moduleName);
789 return createModuleFromScript(moduleName);
786 }
790 }
787
791
788 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
792 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
789 {
793 {
790 if (PyModule_Check(object)) {
794 if (PyModule_Check(object)) {
791 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
795 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
792 } else if (PyDict_Check(object)) {
796 } else if (PyDict_Check(object)) {
793 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
797 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
794 } else {
798 } else {
795 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
799 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
796 }
800 }
797 }
801 }
798
802
799 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
803 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
800 {
804 {
801 if (PyModule_Check(object)) {
805 if (PyModule_Check(object)) {
802 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
806 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
803 } else if (PyDict_Check(object)) {
807 } else if (PyDict_Check(object)) {
804 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
808 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
805 } else {
809 } else {
806 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
810 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
807 }
811 }
808 }
812 }
809
813
810 void PythonQt::removeVariable(PyObject* object, const QString& name)
814 void PythonQt::removeVariable(PyObject* object, const QString& name)
811 {
815 {
812 if (PyDict_Check(object)) {
816 if (PyDict_Check(object)) {
813 PyDict_DelItemString(object, name.toLatin1().data());
817 PyDict_DelItemString(object, name.toLatin1().data());
814 } else {
818 } else {
815 PyObject_DelAttrString(object, name.toLatin1().data());
819 PyObject_DelAttrString(object, name.toLatin1().data());
816 }
820 }
817 }
821 }
818
822
819 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
823 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
820 {
824 {
821 QVariant result;
825 QVariant result;
822 PythonQtObjectPtr obj = lookupObject(object, objectname);
826 PythonQtObjectPtr obj = lookupObject(object, objectname);
823 if (obj) {
827 if (obj) {
824 result = PythonQtConv::PyObjToQVariant(obj);
828 result = PythonQtConv::PyObjToQVariant(obj);
825 }
829 }
826 return result;
830 return result;
827 }
831 }
828
832
829 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
833 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
830 {
834 {
831 QStringList results;
835 QStringList results;
832
836
833 PythonQtObjectPtr object;
837 PythonQtObjectPtr object;
834 if (objectname.isEmpty()) {
838 if (objectname.isEmpty()) {
835 object = module;
839 object = module;
836 } else {
840 } else {
837 object = lookupObject(module, objectname);
841 object = lookupObject(module, objectname);
838 if (!object && type == CallOverloads) {
842 if (!object && type == CallOverloads) {
839 PyObject* dict = lookupObject(module, "__builtins__");
843 PyObject* dict = lookupObject(module, "__builtins__");
840 if (dict) {
844 if (dict) {
841 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
845 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
842 }
846 }
843 }
847 }
844 }
848 }
845
849
846 if (object) {
850 if (object) {
847 results = introspectObject(object, type);
851 results = introspectObject(object, type);
848 }
852 }
849
853
850 return results;
854 return results;
851 }
855 }
852
856
853 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
857 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
854 {
858 {
855 QStringList results;
859 QStringList results;
856
860
857 if (type == CallOverloads) {
861 if (type == CallOverloads) {
858 if (PythonQtSlotFunction_Check(object)) {
862 if (PythonQtSlotFunction_Check(object)) {
859 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
863 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
860 PythonQtSlotInfo* info = o->m_ml;
864 PythonQtSlotInfo* info = o->m_ml;
861
865
862 while (info) {
866 while (info) {
863 results << info->fullSignature();
867 results << info->fullSignature();
864 info = info->nextInfo();
868 info = info->nextInfo();
865 }
869 }
866 } else if (PythonQtSignalFunction_Check(object)) {
870 } else if (PythonQtSignalFunction_Check(object)) {
867 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
871 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
868 PythonQtSlotInfo* info = o->m_ml;
872 PythonQtSlotInfo* info = o->m_ml;
869
873
870 while (info) {
874 while (info) {
871 results << info->fullSignature();
875 results << info->fullSignature();
872 info = info->nextInfo();
876 info = info->nextInfo();
873 }
877 }
874 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
878 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
875 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
879 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
876 PythonQtSlotInfo* info = o->classInfo()->constructors();
880 PythonQtSlotInfo* info = o->classInfo()->constructors();
877
881
878 while (info) {
882 while (info) {
879 results << info->fullSignature();
883 results << info->fullSignature();
880 info = info->nextInfo();
884 info = info->nextInfo();
881 }
885 }
882 } else {
886 } else {
883 QString signature = _p->getSignature(object);
887 QString signature = _p->getSignature(object);
884 if (!signature.isEmpty()) {
888 if (!signature.isEmpty()) {
885 results << signature;
889 results << signature;
886 } else {
890 } else {
887 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
891 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
888 if (doc) {
892 if (doc) {
889 results << PyString_AsString(doc);
893 results << PyString_AsString(doc);
890 Py_DECREF(doc);
894 Py_DECREF(doc);
891 }
895 }
892 }
896 }
893 }
897 }
894 } else {
898 } else {
895 PyObject* keys = NULL;
899 PyObject* keys = NULL;
896 bool isDict = false;
900 bool isDict = false;
897 if (PyDict_Check(object)) {
901 if (PyDict_Check(object)) {
898 keys = PyDict_Keys(object);
902 keys = PyDict_Keys(object);
899 isDict = true;
903 isDict = true;
900 } else {
904 } else {
901 keys = PyObject_Dir(object);
905 keys = PyObject_Dir(object);
902 }
906 }
903 if (keys) {
907 if (keys) {
904 int count = PyList_Size(keys);
908 int count = PyList_Size(keys);
905 PyObject* key;
909 PyObject* key;
906 PyObject* value;
910 PyObject* value;
907 QString keystr;
911 QString keystr;
908 for (int i = 0;i<count;i++) {
912 for (int i = 0;i<count;i++) {
909 key = PyList_GetItem(keys,i);
913 key = PyList_GetItem(keys,i);
910 if (isDict) {
914 if (isDict) {
911 value = PyDict_GetItem(object, key);
915 value = PyDict_GetItem(object, key);
912 Py_INCREF(value);
916 Py_INCREF(value);
913 } else {
917 } else {
914 value = PyObject_GetAttr(object, key);
918 value = PyObject_GetAttr(object, key);
915 }
919 }
916 if (!value) continue;
920 if (!value) continue;
917 keystr = PyString_AsString(key);
921 keystr = PyString_AsString(key);
918 static const QString underscoreStr("__tmp");
922 static const QString underscoreStr("__tmp");
919 if (!keystr.startsWith(underscoreStr)) {
923 if (!keystr.startsWith(underscoreStr)) {
920 switch (type) {
924 switch (type) {
921 case Anything:
925 case Anything:
922 results << keystr;
926 results << keystr;
923 break;
927 break;
924 case Class:
928 case Class:
925 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
929 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
926 results << keystr;
930 results << keystr;
927 }
931 }
928 break;
932 break;
929 case Variable:
933 case Variable:
930 if (value->ob_type != &PyClass_Type
934 if (value->ob_type != &PyClass_Type
931 && value->ob_type != &PyCFunction_Type
935 && value->ob_type != &PyCFunction_Type
932 && value->ob_type != &PyFunction_Type
936 && value->ob_type != &PyFunction_Type
933 && value->ob_type != &PyMethod_Type
937 && value->ob_type != &PyMethod_Type
934 && value->ob_type != &PyModule_Type
938 && value->ob_type != &PyModule_Type
935 && value->ob_type != &PyType_Type
939 && value->ob_type != &PyType_Type
936 && value->ob_type != &PythonQtSlotFunction_Type
940 && value->ob_type != &PythonQtSlotFunction_Type
937 ) {
941 ) {
938 results << keystr;
942 results << keystr;
939 }
943 }
940 break;
944 break;
941 case Function:
945 case Function:
942 if (value->ob_type == &PyCFunction_Type ||
946 if (value->ob_type == &PyCFunction_Type ||
943 value->ob_type == &PyFunction_Type ||
947 value->ob_type == &PyFunction_Type ||
944 value->ob_type == &PyMethod_Type ||
948 value->ob_type == &PyMethod_Type ||
945 value->ob_type == &PythonQtSlotFunction_Type
949 value->ob_type == &PythonQtSlotFunction_Type
946 ) {
950 ) {
947 results << keystr;
951 results << keystr;
948 }
952 }
949 break;
953 break;
950 case Module:
954 case Module:
951 if (value->ob_type == &PyModule_Type) {
955 if (value->ob_type == &PyModule_Type) {
952 results << keystr;
956 results << keystr;
953 }
957 }
954 break;
958 break;
955 default:
959 default:
956 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
960 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
957 }
961 }
958 }
962 }
959 Py_DECREF(value);
963 Py_DECREF(value);
960 }
964 }
961 Py_DECREF(keys);
965 Py_DECREF(keys);
962 }
966 }
963 if ((type == Anything) || (type == Variable)) {
967 if ((type == Anything) || (type == Variable)) {
964 if (object->ob_type == &PythonQtClassWrapper_Type) {
968 if (object->ob_type == &PythonQtClassWrapper_Type) {
965 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
969 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
966 PythonQtClassInfo* info = o->classInfo();
970 PythonQtClassInfo* info = o->classInfo();
967 results += info->propertyList();
971 results += info->propertyList();
968 }
972 }
969 }
973 }
970 }
974 }
971 return results;
975 return results;
972 }
976 }
973
977
974 PyObject* PythonQt::getObjectByType(const QString& typeName)
978 PyObject* PythonQt::getObjectByType(const QString& typeName)
975 {
979 {
976 PythonQtObjectPtr sys;
980 PythonQtObjectPtr sys;
977 sys.setNewRef(PyImport_ImportModule("sys"));
981 sys.setNewRef(PyImport_ImportModule("sys"));
978 PythonQtObjectPtr modules = lookupObject(sys, "modules");
982 PythonQtObjectPtr modules = lookupObject(sys, "modules");
979 Q_ASSERT(PyDict_Check(modules));
983 Q_ASSERT(PyDict_Check(modules));
980
984
981 QStringList tmp = typeName.split(".");
985 QStringList tmp = typeName.split(".");
982 QString simpleTypeName = tmp.takeLast();
986 QString simpleTypeName = tmp.takeLast();
983 QString moduleName = tmp.join(".");
987 QString moduleName = tmp.join(".");
984
988
985 PyObject* object = NULL;
989 PyObject* object = NULL;
986 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
990 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
987 if (moduleObject) {
991 if (moduleObject) {
988 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
992 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
989 }
993 }
990
994
991 if (!object) {
995 if (!object) {
992 moduleObject = PyDict_GetItemString(modules, "__builtin__");
996 moduleObject = PyDict_GetItemString(modules, "__builtin__");
993 if (moduleObject) {
997 if (moduleObject) {
994 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
998 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
995 }
999 }
996 }
1000 }
997
1001
998 return object;
1002 return object;
999 }
1003 }
1000
1004
1001 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
1005 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
1002 {
1006 {
1003 QStringList results;
1007 QStringList results;
1004 PyObject* object = getObjectByType(typeName);
1008 PyObject* object = getObjectByType(typeName);
1005 if (!object) {
1009 if (!object) {
1006 // the last item may be a member, split it away and try again
1010 // the last item may be a member, split it away and try again
1007 QStringList tmp = typeName.split(".");
1011 QStringList tmp = typeName.split(".");
1008 QString memberName = tmp.takeLast();
1012 QString memberName = tmp.takeLast();
1009 QString typeName;
1013 QString typeName;
1010 if (tmp.isEmpty()) {
1014 if (tmp.isEmpty()) {
1011 typeName = memberName;
1015 typeName = memberName;
1012 memberName.clear();
1016 memberName.clear();
1013 } else {
1017 } else {
1014 typeName = tmp.takeLast();
1018 typeName = tmp.takeLast();
1015 }
1019 }
1016 PyObject* typeObject = getObjectByType(typeName);
1020 PyObject* typeObject = getObjectByType(typeName);
1017 if (typeObject) {
1021 if (typeObject) {
1018 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
1022 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
1019 }
1023 }
1020 }
1024 }
1021 if (object) {
1025 if (object) {
1022 results = introspectObject(object, type);
1026 results = introspectObject(object, type);
1023 Py_DECREF(object);
1027 Py_DECREF(object);
1024 }
1028 }
1025 return results;
1029 return results;
1026 }
1030 }
1027
1031
1028 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args, const QVariantMap& kwargs)
1032 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args, const QVariantMap& kwargs)
1029 {
1033 {
1030 PythonQtObjectPtr callable = lookupCallable(object, name);
1034 PythonQtObjectPtr callable = lookupCallable(object, name);
1031 if (callable) {
1035 if (callable) {
1032 return call(callable, args, kwargs);
1036 return call(callable, args, kwargs);
1033 } else {
1037 } else {
1034 return QVariant();
1038 return QVariant();
1035 }
1039 }
1036 }
1040 }
1037
1041
1038 QVariant PythonQt::call(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1042 QVariant PythonQt::call(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1039 {
1043 {
1040 QVariant r;
1044 QVariant r;
1041 PythonQtObjectPtr result;
1045 PythonQtObjectPtr result;
1042 result.setNewRef(callAndReturnPyObject(callable, args, kwargs));
1046 result.setNewRef(callAndReturnPyObject(callable, args, kwargs));
1047 clearError();
1043 if (result) {
1048 if (result) {
1044 r = PythonQtConv::PyObjToQVariant(result);
1049 r = PythonQtConv::PyObjToQVariant(result);
1045 } else {
1050 } else {
1046 PythonQt::self()->handleError();
1051 PythonQt::self()->handleError();
1047 }
1052 }
1048 return r;
1053 return r;
1049 }
1054 }
1050
1055
1051 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1056 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1052 {
1057 {
1053 PyObject* result = NULL;
1058 PyObject* result = NULL;
1054 if (callable) {
1059 if (callable) {
1055 bool err = false;
1060 bool err = false;
1056 PythonQtObjectPtr pargs;
1061 PythonQtObjectPtr pargs;
1057 int count = args.size();
1062 int count = args.size();
1058 if ((count > 0) || (kwargs.count() > 0)) { // create empty tuple if kwargs are given
1063 if ((count > 0) || (kwargs.count() > 0)) { // create empty tuple if kwargs are given
1059 pargs.setNewRef(PyTuple_New(count));
1064 pargs.setNewRef(PyTuple_New(count));
1060
1065
1061 // transform QVariant arguments to Python
1066 // transform QVariant arguments to Python
1062 for (int i = 0; i < count; i++) {
1067 for (int i = 0; i < count; i++) {
1063 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1068 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1064 if (arg) {
1069 if (arg) {
1065 // steals reference, no unref
1070 // steals reference, no unref
1066 PyTuple_SetItem(pargs, i,arg);
1071 PyTuple_SetItem(pargs, i,arg);
1067 } else {
1072 } else {
1068 err = true;
1073 err = true;
1069 break;
1074 break;
1070 }
1075 }
1071 }
1076 }
1072 }
1077 }
1073 if (!err) {
1078 if (!err) {
1074 if (kwargs.isEmpty()) {
1079 if (kwargs.isEmpty()) {
1075 // do a direct call if we have no keyword arguments
1080 // do a direct call if we have no keyword arguments
1076 PyErr_Clear();
1081 PyErr_Clear();
1077 result = PyObject_CallObject(callable, pargs);
1082 result = PyObject_CallObject(callable, pargs);
1078 } else {
1083 } else {
1079 // convert keyword arguments to Python
1084 // convert keyword arguments to Python
1080 PythonQtObjectPtr pkwargs;
1085 PythonQtObjectPtr pkwargs;
1081 pkwargs.setNewRef(PyDict_New());
1086 pkwargs.setNewRef(PyDict_New());
1082 QMapIterator<QString, QVariant> it(kwargs);
1087 QMapIterator<QString, QVariant> it(kwargs);
1083 while (it.hasNext()) {
1088 while (it.hasNext()) {
1084 it.next();
1089 it.next();
1085 PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
1090 PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
1086 if (arg) {
1091 if (arg) {
1087 PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg);
1092 PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg);
1088 } else {
1093 } else {
1089 err = true;
1094 err = true;
1090 break;
1095 break;
1091 }
1096 }
1092 }
1097 }
1093 if (!err) {
1098 if (!err) {
1094 // call with arguments and keyword arguments
1099 // call with arguments and keyword arguments
1095 PyErr_Clear();
1100 PyErr_Clear();
1096 result = PyObject_Call(callable, pargs, pkwargs);
1101 result = PyObject_Call(callable, pargs, pkwargs);
1097 }
1102 }
1098 }
1103 }
1099 }
1104 }
1100 }
1105 }
1101 return result;
1106 return result;
1102 }
1107 }
1103
1108
1104 void PythonQt::addInstanceDecorators(QObject* o)
1109 void PythonQt::addInstanceDecorators(QObject* o)
1105 {
1110 {
1106 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1111 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1107 }
1112 }
1108
1113
1109 void PythonQt::addClassDecorators(QObject* o)
1114 void PythonQt::addClassDecorators(QObject* o)
1110 {
1115 {
1111 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1116 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1112 }
1117 }
1113
1118
1114 void PythonQt::addDecorators(QObject* o)
1119 void PythonQt::addDecorators(QObject* o)
1115 {
1120 {
1116 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1121 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1117 }
1122 }
1118
1123
1119 void PythonQt::registerQObjectClassNames(const QStringList& names)
1124 void PythonQt::registerQObjectClassNames(const QStringList& names)
1120 {
1125 {
1121 _p->registerQObjectClassNames(names);
1126 _p->registerQObjectClassNames(names);
1122 }
1127 }
1123
1128
1124 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1129 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1125 {
1130 {
1126 _p->_importInterface = importInterface;
1131 _p->_importInterface = importInterface;
1127 PythonQtImport::init();
1132 PythonQtImport::init();
1128 }
1133 }
1129
1134
1130 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1135 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1131 {
1136 {
1132 _p->_importIgnorePaths = paths;
1137 _p->_importIgnorePaths = paths;
1133 }
1138 }
1134
1139
1135 const QStringList& PythonQt::getImporterIgnorePaths()
1140 const QStringList& PythonQt::getImporterIgnorePaths()
1136 {
1141 {
1137 return _p->_importIgnorePaths;
1142 return _p->_importIgnorePaths;
1138 }
1143 }
1139
1144
1140 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1145 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1141 {
1146 {
1142 _p->_cppWrapperFactories.append(factory);
1147 _p->_cppWrapperFactories.append(factory);
1143 }
1148 }
1144
1149
1145 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1150 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1146 {
1151 {
1147 _p->_foreignWrapperFactories.append(factory);
1152 _p->_foreignWrapperFactories.append(factory);
1148 }
1153 }
1149
1154
1150 //---------------------------------------------------------------------------------------------------
1155 //---------------------------------------------------------------------------------------------------
1151 PythonQtPrivate::PythonQtPrivate()
1156 PythonQtPrivate::PythonQtPrivate()
1152 {
1157 {
1153 _importInterface = NULL;
1158 _importInterface = NULL;
1154 _defaultImporter = new PythonQtQFileImporter;
1159 _defaultImporter = new PythonQtQFileImporter;
1155 _noLongerWrappedCB = NULL;
1160 _noLongerWrappedCB = NULL;
1156 _wrappedCB = NULL;
1161 _wrappedCB = NULL;
1157 _currentClassInfoForClassWrapperCreation = NULL;
1162 _currentClassInfoForClassWrapperCreation = NULL;
1158 _profilingCB = NULL;
1163 _profilingCB = NULL;
1164 _hadError = false;
1165 _systemExitExceptionHandlerEnabled = false;
1159 }
1166 }
1160
1167
1161 void PythonQtPrivate::setupSharedLibrarySuffixes()
1168 void PythonQtPrivate::setupSharedLibrarySuffixes()
1162 {
1169 {
1163 _sharedLibrarySuffixes.clear();
1170 _sharedLibrarySuffixes.clear();
1164 PythonQtObjectPtr imp;
1171 PythonQtObjectPtr imp;
1165 imp.setNewRef(PyImport_ImportModule("imp"));
1172 imp.setNewRef(PyImport_ImportModule("imp"));
1166 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1173 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1167 QVariant result = imp.call("get_suffixes");
1174 QVariant result = imp.call("get_suffixes");
1168 #ifdef __linux
1175 #ifdef __linux
1169 #ifdef _DEBUG
1176 #ifdef _DEBUG
1170 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1177 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1171 // This is a workaround, because python does not append the '_d' suffix on Linux
1178 // This is a workaround, because python does not append the '_d' suffix on Linux
1172 // and would always load the release library otherwise.
1179 // and would always load the release library otherwise.
1173 _sharedLibrarySuffixes << "_d.so";
1180 _sharedLibrarySuffixes << "_d.so";
1174 #endif
1181 #endif
1175 #endif
1182 #endif
1176 foreach (QVariant entry, result.toList()) {
1183 foreach (QVariant entry, result.toList()) {
1177 QVariantList suffixEntry = entry.toList();
1184 QVariantList suffixEntry = entry.toList();
1178 if (suffixEntry.count()==3) {
1185 if (suffixEntry.count()==3) {
1179 int code = suffixEntry.at(2).toInt();
1186 int code = suffixEntry.at(2).toInt();
1180 if (code == cExtensionCode) {
1187 if (code == cExtensionCode) {
1181 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1188 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1182 }
1189 }
1183 }
1190 }
1184 }
1191 }
1185 }
1192 }
1186
1193
1187 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1194 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1188 {
1195 {
1189 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1196 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1190 _currentClassInfoForClassWrapperCreation = NULL;
1197 _currentClassInfoForClassWrapperCreation = NULL;
1191 return info;
1198 return info;
1192 }
1199 }
1193
1200
1194 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1201 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1195 {
1202 {
1196 o->setParent(this);
1203 o->setParent(this);
1197 int numMethods = o->metaObject()->methodCount();
1204 int numMethods = o->metaObject()->methodCount();
1198 for (int i = 0; i < numMethods; i++) {
1205 for (int i = 0; i < numMethods; i++) {
1199 QMetaMethod m = o->metaObject()->method(i);
1206 QMetaMethod m = o->metaObject()->method(i);
1200 if ((m.methodType() == QMetaMethod::Method ||
1207 if ((m.methodType() == QMetaMethod::Method ||
1201 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1208 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1202 if (qstrncmp(m.signature(), "new_", 4)==0) {
1209 if (qstrncmp(m.signature(), "new_", 4)==0) {
1203 if ((decoTypes & ConstructorDecorator) == 0) continue;
1210 if ((decoTypes & ConstructorDecorator) == 0) continue;
1204 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1211 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1205 if (info->parameters().at(0).pointerCount == 1) {
1212 if (info->parameters().at(0).pointerCount == 1) {
1206 QByteArray signature = m.signature();
1213 QByteArray signature = m.signature();
1207 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1214 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1208 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1215 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1209 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1216 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1210 classInfo->addConstructor(newSlot);
1217 classInfo->addConstructor(newSlot);
1211 }
1218 }
1212 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1219 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1213 if ((decoTypes & DestructorDecorator) == 0) continue;
1220 if ((decoTypes & DestructorDecorator) == 0) continue;
1214 QByteArray signature = m.signature();
1221 QByteArray signature = m.signature();
1215 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1222 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1216 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1223 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1217 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1224 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1218 classInfo->setDestructor(newSlot);
1225 classInfo->setDestructor(newSlot);
1219 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1226 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1220 if ((decoTypes & StaticDecorator) == 0) continue;
1227 if ((decoTypes & StaticDecorator) == 0) continue;
1221 QByteArray signature = m.signature();
1228 QByteArray signature = m.signature();
1222 QByteArray nameOfClass = signature.mid(7);
1229 QByteArray nameOfClass = signature.mid(7);
1223 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1230 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1224 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1231 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1225 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1232 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1226 classInfo->addDecoratorSlot(newSlot);
1233 classInfo->addDecoratorSlot(newSlot);
1227 } else {
1234 } else {
1228 if ((decoTypes & InstanceDecorator) == 0) continue;
1235 if ((decoTypes & InstanceDecorator) == 0) continue;
1229 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1236 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1230 if (info->parameters().count()>1) {
1237 if (info->parameters().count()>1) {
1231 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1238 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1232 if (p.pointerCount==1) {
1239 if (p.pointerCount==1) {
1233 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1240 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1234 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1241 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1235 classInfo->addDecoratorSlot(newSlot);
1242 classInfo->addDecoratorSlot(newSlot);
1236 }
1243 }
1237 }
1244 }
1238 }
1245 }
1239 }
1246 }
1240 }
1247 }
1241 }
1248 }
1242
1249
1243 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1250 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1244 {
1251 {
1245 foreach(QString name, names) {
1252 foreach(QString name, names) {
1246 _knownQObjectClassNames.insert(name.toLatin1(), true);
1253 _knownQObjectClassNames.insert(name.toLatin1(), true);
1247 }
1254 }
1248 }
1255 }
1249
1256
1250 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1257 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1251 {
1258 {
1252 _signalReceivers.remove(obj);
1259 _signalReceivers.remove(obj);
1253 }
1260 }
1254
1261
1262 namespace
1263 {
1264 //! adapted from python source file "pythonrun.c", function "handle_system_exit"
1265 //! return the exitcode instead of calling "Py_Exit".
1266 //! it gives the application an opportunity to properly terminate.
1267 int custom_system_exit_exception_handler()
1268 {
1269 PyObject *exception, *value, *tb;
1270 int exitcode = 0;
1271
1272 // if (Py_InspectFlag)
1273 // /* Don't exit if -i flag was given. This flag is set to 0
1274 // * when entering interactive mode for inspecting. */
1275 // return exitcode;
1276
1277 PyErr_Fetch(&exception, &value, &tb);
1278 if (Py_FlushLine())
1279 PyErr_Clear();
1280 fflush(stdout);
1281 if (value == NULL || value == Py_None)
1282 goto done;
1283 if (PyExceptionInstance_Check(value)) {
1284 /* The error code should be in the `code' attribute. */
1285 PyObject *code = PyObject_GetAttrString(value, "code");
1286 if (code) {
1287 Py_DECREF(value);
1288 value = code;
1289 if (value == Py_None)
1290 goto done;
1291 }
1292 /* If we failed to dig out the 'code' attribute,
1293 just let the else clause below print the error. */
1294 }
1295 if (PyInt_Check(value))
1296 exitcode = (int)PyInt_AsLong(value);
1297 else {
1298 PyObject *sys_stderr = PySys_GetObject(const_cast<char*>("stderr"));
1299 if (sys_stderr != NULL && sys_stderr != Py_None) {
1300 PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
1301 } else {
1302 PyObject_Print(value, stderr, Py_PRINT_RAW);
1303 fflush(stderr);
1304 }
1305 PySys_WriteStderr("\n");
1306 exitcode = 1;
1307 }
1308 done:
1309 /* Restore and clear the exception info, in order to properly decref
1310 * the exception, value, and traceback. If we just exit instead,
1311 * these leak, which confuses PYTHONDUMPREFS output, and may prevent
1312 * some finalizers from running.
1313 */
1314 PyErr_Restore(exception, value, tb);
1315 PyErr_Clear();
1316 return exitcode;
1317 //Py_Exit(exitcode);
1318 }
1319 }
1320
1255 bool PythonQt::handleError()
1321 bool PythonQt::handleError()
1256 {
1322 {
1257 bool flag = false;
1323 bool flag = false;
1258 if (PyErr_Occurred()) {
1324 if (PyErr_Occurred()) {
1259
1325
1260 // currently we just print the error and the stderr handler parses the errors
1326 if (_p->_systemExitExceptionHandlerEnabled &&
1261 PyErr_Print();
1327 PyErr_ExceptionMatches(PyExc_SystemExit)) {
1262
1328 int exitcode = custom_system_exit_exception_handler();
1263 /*
1329 emit PythonQt::self()->systemExitExceptionRaised(exitcode);
1264 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1330 }
1265 PyObject *ptype;
1331 else
1266 PyObject *pvalue;
1332 {
1267 PyObject *ptraceback;
1333 // currently we just print the error and the stderr handler parses the errors
1268 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1334 PyErr_Print();
1269
1335
1270 Py_XDECREF(ptype);
1336 /*
1271 Py_XDECREF(pvalue);
1337 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1272 Py_XDECREF(ptraceback);
1338 PyObject *ptype;
1273 */
1339 PyObject *pvalue;
1274 PyErr_Clear();
1340 PyObject *ptraceback;
1341 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1342
1343 Py_XDECREF(ptype);
1344 Py_XDECREF(pvalue);
1345 Py_XDECREF(ptraceback);
1346 */
1347 PyErr_Clear();
1348 }
1275 flag = true;
1349 flag = true;
1276 }
1350 }
1351 _p->_hadError = flag;
1277 return flag;
1352 return flag;
1278 }
1353 }
1279
1354
1355 bool PythonQt::hadError()const
1356 {
1357 return _p->_hadError;
1358 }
1359
1360 void PythonQt::clearError()
1361 {
1362 _p->_hadError = false;
1363 }
1364
1365 void PythonQt::setSystemExitExceptionHandlerEnabled(bool value)
1366 {
1367 _p->_systemExitExceptionHandlerEnabled = value;
1368 }
1369
1370 bool PythonQt::systemExitExceptionHandlerEnabled() const
1371 {
1372 return _p->_systemExitExceptionHandlerEnabled;
1373 }
1374
1280 void PythonQt::addSysPath(const QString& path)
1375 void PythonQt::addSysPath(const QString& path)
1281 {
1376 {
1282 PythonQtObjectPtr sys;
1377 PythonQtObjectPtr sys;
1283 sys.setNewRef(PyImport_ImportModule("sys"));
1378 sys.setNewRef(PyImport_ImportModule("sys"));
1284 PythonQtObjectPtr obj = lookupObject(sys, "path");
1379 PythonQtObjectPtr obj = lookupObject(sys, "path");
1285 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1380 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1286 }
1381 }
1287
1382
1288 void PythonQt::overwriteSysPath(const QStringList& paths)
1383 void PythonQt::overwriteSysPath(const QStringList& paths)
1289 {
1384 {
1290 PythonQtObjectPtr sys;
1385 PythonQtObjectPtr sys;
1291 sys.setNewRef(PyImport_ImportModule("sys"));
1386 sys.setNewRef(PyImport_ImportModule("sys"));
1292 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1387 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1293 }
1388 }
1294
1389
1295 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1390 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1296 {
1391 {
1297 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1392 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1298 }
1393 }
1299
1394
1300 void PythonQt::stdOutRedirectCB(const QString& str)
1395 void PythonQt::stdOutRedirectCB(const QString& str)
1301 {
1396 {
1302 if (!PythonQt::self()) {
1397 if (!PythonQt::self()) {
1303 std::cout << str.toLatin1().data() << std::endl;
1398 std::cout << str.toLatin1().data() << std::endl;
1304 return;
1399 return;
1305 }
1400 }
1306 emit PythonQt::self()->pythonStdOut(str);
1401 emit PythonQt::self()->pythonStdOut(str);
1307 }
1402 }
1308
1403
1309 void PythonQt::stdErrRedirectCB(const QString& str)
1404 void PythonQt::stdErrRedirectCB(const QString& str)
1310 {
1405 {
1311 if (!PythonQt::self()) {
1406 if (!PythonQt::self()) {
1312 std::cerr << str.toLatin1().data() << std::endl;
1407 std::cerr << str.toLatin1().data() << std::endl;
1313 return;
1408 return;
1314 }
1409 }
1315 emit PythonQt::self()->pythonStdErr(str);
1410 emit PythonQt::self()->pythonStdErr(str);
1316 }
1411 }
1317
1412
1318 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1413 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1319 {
1414 {
1320 _p->_wrappedCB = cb;
1415 _p->_wrappedCB = cb;
1321 }
1416 }
1322
1417
1323 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1418 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1324 {
1419 {
1325 _p->_noLongerWrappedCB = cb;
1420 _p->_noLongerWrappedCB = cb;
1326 }
1421 }
1327
1422
1328 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1423 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1329 {
1424 {
1330 _p->_profilingCB = cb;
1425 _p->_profilingCB = cb;
1331 }
1426 }
1332
1427
1333
1428
1334 static PyMethodDef PythonQtMethods[] = {
1429 static PyMethodDef PythonQtMethods[] = {
1335 {NULL, NULL, 0, NULL}
1430 {NULL, NULL, 0, NULL}
1336 };
1431 };
1337
1432
1338 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1433 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1339 {
1434 {
1340 QByteArray name = "PythonQt";
1435 QByteArray name = "PythonQt";
1341 if (!pythonQtModuleName.isEmpty()) {
1436 if (!pythonQtModuleName.isEmpty()) {
1342 name = pythonQtModuleName;
1437 name = pythonQtModuleName;
1343 }
1438 }
1344 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1439 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1345 _p->_pythonQtModuleName = name;
1440 _p->_pythonQtModuleName = name;
1346
1441
1347 if (redirectStdOut) {
1442 if (redirectStdOut) {
1348 PythonQtObjectPtr sys;
1443 PythonQtObjectPtr sys;
1349 PythonQtObjectPtr out;
1444 PythonQtObjectPtr out;
1350 PythonQtObjectPtr err;
1445 PythonQtObjectPtr err;
1351 sys.setNewRef(PyImport_ImportModule("sys"));
1446 sys.setNewRef(PyImport_ImportModule("sys"));
1352 // create a redirection object for stdout and stderr
1447 // create a redirection object for stdout and stderr
1353 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1448 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1354 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1449 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1355 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1450 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1356 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1451 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1357 // replace the built in file objects with our own objects
1452 // replace the built in file objects with our own objects
1358 PyModule_AddObject(sys, "stdout", out);
1453 PyModule_AddObject(sys, "stdout", out);
1359 PyModule_AddObject(sys, "stderr", err);
1454 PyModule_AddObject(sys, "stderr", err);
1360 }
1455 }
1361 }
1456 }
1362
1457
1363 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1458 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1364 {
1459 {
1365 QStringList tmp = name.split(".");
1460 QStringList tmp = name.split(".");
1366 QString methodName = tmp.takeLast();
1461 QString methodName = tmp.takeLast();
1367 QString variableName = tmp.join(".");
1462 QString variableName = tmp.join(".");
1368 // TODO: the variableName may be a type name, this needs to be handled differently,
1463 // TODO: the variableName may be a type name, this needs to be handled differently,
1369 // because it is not necessarily known in the module context
1464 // because it is not necessarily known in the module context
1370 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1465 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1371 if (variableObject.isNull()) {
1466 if (variableObject.isNull()) {
1372 return "";
1467 return "";
1373 }
1468 }
1374
1469
1375 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1470 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1376 }
1471 }
1377
1472
1378 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1473 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1379 {
1474 {
1380 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1475 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1381 if (typeObject.isNull()) {
1476 if (typeObject.isNull()) {
1382 return "";
1477 return "";
1383 }
1478 }
1384 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1479 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1385 }
1480 }
1386
1481
1387 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1482 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1388 {
1483 {
1389 PythonQtObjectPtr methodObject;
1484 PythonQtObjectPtr methodObject;
1390 if (PyDict_Check(variableObject)) {
1485 if (PyDict_Check(variableObject)) {
1391 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1486 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1392 } else {
1487 } else {
1393 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1488 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1394 }
1489 }
1395 if (methodObject.isNull()) {
1490 if (methodObject.isNull()) {
1396 return "";
1491 return "";
1397 }
1492 }
1398
1493
1399 QString type;
1494 QString type;
1400
1495
1401 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1496 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1402 // the methodObject is not a method, but the name of a type/class. This means
1497 // the methodObject is not a method, but the name of a type/class. This means
1403 // a constructor is called. Return the context.
1498 // a constructor is called. Return the context.
1404 type = context;
1499 type = context;
1405 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1500 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1406 QString className;
1501 QString className;
1407
1502
1408 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1503 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1409 // the type name of wrapped instance is the class name
1504 // the type name of wrapped instance is the class name
1410 className = variableObject->ob_type->tp_name;
1505 className = variableObject->ob_type->tp_name;
1411 } else {
1506 } else {
1412 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1507 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1413 if (classNameObject) {
1508 if (classNameObject) {
1414 Q_ASSERT(PyString_Check(classNameObject));
1509 Q_ASSERT(PyString_Check(classNameObject));
1415 className = PyString_AsString(classNameObject);
1510 className = PyString_AsString(classNameObject);
1416 Py_DECREF(classNameObject);
1511 Py_DECREF(classNameObject);
1417 }
1512 }
1418 }
1513 }
1419
1514
1420 if (!className.isEmpty()) {
1515 if (!className.isEmpty()) {
1421 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1516 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1422 if (info) {
1517 if (info) {
1423 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1518 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1424 if (slotInfo) {
1519 if (slotInfo) {
1425 if (slotInfo->metaMethod()) {
1520 if (slotInfo->metaMethod()) {
1426 type = slotInfo->metaMethod()->typeName();
1521 type = slotInfo->metaMethod()->typeName();
1427 if (!type.isEmpty()) {
1522 if (!type.isEmpty()) {
1428 QChar c = type.at(type.length()-1);
1523 QChar c = type.at(type.length()-1);
1429 while (c == '*' || c == '&') {
1524 while (c == '*' || c == '&') {
1430 type.truncate(type.length()-1);
1525 type.truncate(type.length()-1);
1431 if (!type.isEmpty()) {
1526 if (!type.isEmpty()) {
1432 c = type.at(type.length()-1);
1527 c = type.at(type.length()-1);
1433 } else {
1528 } else {
1434 break;
1529 break;
1435 }
1530 }
1436 }
1531 }
1437 // split away template arguments
1532 // split away template arguments
1438 type = type.split("<").first();
1533 type = type.split("<").first();
1439 // split away const
1534 // split away const
1440 type = type.split(" ").last().trimmed();
1535 type = type.split(" ").last().trimmed();
1441
1536
1442 // if the type is a known class info, then create the full type name, i.e. include the
1537 // if the type is a known class info, then create the full type name, i.e. include the
1443 // module name. For example, the slot may return a QDate, then this looks up the
1538 // module name. For example, the slot may return a QDate, then this looks up the
1444 // name _PythonQt.QtCore.QDate.
1539 // name _PythonQt.QtCore.QDate.
1445 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1540 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1446 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1541 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1447 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1542 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1448 Q_ASSERT(PyString_Check(s));
1543 Q_ASSERT(PyString_Check(s));
1449 type = QString(PyString_AsString(s)) + "." + type;
1544 type = QString(PyString_AsString(s)) + "." + type;
1450 Py_DECREF(s);
1545 Py_DECREF(s);
1451 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1546 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1452 Q_ASSERT(PyString_Check(s));
1547 Q_ASSERT(PyString_Check(s));
1453 Py_DECREF(s);
1548 Py_DECREF(s);
1454 }
1549 }
1455 }
1550 }
1456 }
1551 }
1457 }
1552 }
1458 }
1553 }
1459 }
1554 }
1460 }
1555 }
1461 return type;
1556 return type;
1462 }
1557 }
1463
1558
1464 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1559 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1465 {
1560 {
1466 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1561 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1467 }
1562 }
1468
1563
1469
1564
1470 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1565 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1471 {
1566 {
1472 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1567 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1473 if (!info) {
1568 if (!info) {
1474 info = new PythonQtClassInfo();
1569 info = new PythonQtClassInfo();
1475 info->setupCPPObject(typeName);
1570 info->setupCPPObject(typeName);
1476 _knownClassInfos.insert(typeName, info);
1571 _knownClassInfos.insert(typeName, info);
1477 }
1572 }
1478 return info;
1573 return info;
1479 }
1574 }
1480
1575
1481 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1576 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1482 {
1577 {
1483 _p->addPolymorphicHandler(typeName, cb);
1578 _p->addPolymorphicHandler(typeName, cb);
1484 }
1579 }
1485
1580
1486 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1581 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1487 {
1582 {
1488 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1583 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1489 info->addPolymorphicHandler(cb);
1584 info->addPolymorphicHandler(cb);
1490 }
1585 }
1491
1586
1492 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1587 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1493 {
1588 {
1494 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1589 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1495 }
1590 }
1496
1591
1497 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1592 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1498 {
1593 {
1499 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1594 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1500 if (info) {
1595 if (info) {
1501 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1596 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1502 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1597 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1503 return true;
1598 return true;
1504 } else {
1599 } else {
1505 return false;
1600 return false;
1506 }
1601 }
1507 }
1602 }
1508
1603
1509 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1604 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1510 {
1605 {
1511 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1606 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1512 if (!info->pythonQtClassWrapper()) {
1607 if (!info->pythonQtClassWrapper()) {
1513 info->setTypeSlots(typeSlots);
1608 info->setTypeSlots(typeSlots);
1514 info->setupCPPObject(typeName);
1609 info->setupCPPObject(typeName);
1515 createPythonQtClassWrapper(info, package, module);
1610 createPythonQtClassWrapper(info, package, module);
1516 }
1611 }
1517 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1612 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1518 addParentClass(typeName, parentTypeName, 0);
1613 addParentClass(typeName, parentTypeName, 0);
1519 }
1614 }
1520 if (wrapperCreator) {
1615 if (wrapperCreator) {
1521 info->setDecoratorProvider(wrapperCreator);
1616 info->setDecoratorProvider(wrapperCreator);
1522 }
1617 }
1523 if (shell) {
1618 if (shell) {
1524 info->setShellSetInstanceWrapperCB(shell);
1619 info->setShellSetInstanceWrapperCB(shell);
1525 }
1620 }
1526 }
1621 }
1527
1622
1528 PyObject* PythonQtPrivate::packageByName(const char* name)
1623 PyObject* PythonQtPrivate::packageByName(const char* name)
1529 {
1624 {
1530 if (name==NULL || name[0]==0) {
1625 if (name==NULL || name[0]==0) {
1531 name = "private";
1626 name = "private";
1532 }
1627 }
1533 PyObject* v = _packages.value(name);
1628 PyObject* v = _packages.value(name);
1534 if (!v) {
1629 if (!v) {
1535 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1630 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1536 _packages.insert(name, v);
1631 _packages.insert(name, v);
1537 // AddObject steals the reference, so increment it!
1632 // AddObject steals the reference, so increment it!
1538 Py_INCREF(v);
1633 Py_INCREF(v);
1539 PyModule_AddObject(_pythonQtModule, name, v);
1634 PyModule_AddObject(_pythonQtModule, name, v);
1540 }
1635 }
1541 return v;
1636 return v;
1542 }
1637 }
1543
1638
1544 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1639 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1545 {
1640 {
1546 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;
1641 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;
1547 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1642 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1548 PythonQt::self()->handleError();
1643 PythonQt::self()->handleError();
1549 }
1644 }
1550
1645
1551 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1646 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1552 {
1647 {
1553 if (_p->_initFlags & ExternalHelp) {
1648 if (_p->_initFlags & ExternalHelp) {
1554 emit pythonHelpRequest(QByteArray(info->className()));
1649 emit pythonHelpRequest(QByteArray(info->className()));
1555 return Py_BuildValue("");
1650 return Py_BuildValue("");
1556 } else {
1651 } else {
1557 return PyString_FromString(info->help().toLatin1().data());
1652 return PyString_FromString(info->help().toLatin1().data());
1558 }
1653 }
1559 }
1654 }
1560
1655
1561 void PythonQt::clearNotFoundCachedMembers()
1656 void PythonQt::clearNotFoundCachedMembers()
1562 {
1657 {
1563 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1658 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1564 info->clearNotFoundCachedMembers();
1659 info->clearNotFoundCachedMembers();
1565 }
1660 }
1566 }
1661 }
1567
1662
1568 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1663 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1569 {
1664 {
1570 _p->_cppWrapperFactories.removeAll(factory);
1665 _p->_cppWrapperFactories.removeAll(factory);
1571 }
1666 }
1572
1667
1573 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1668 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1574 {
1669 {
1575 _p->_foreignWrapperFactories.removeAll(factory);
1670 _p->_foreignWrapperFactories.removeAll(factory);
1576 }
1671 }
1577
1672
1578 void PythonQtPrivate::removeWrapperPointer(void* obj)
1673 void PythonQtPrivate::removeWrapperPointer(void* obj)
1579 {
1674 {
1580 _wrappedObjects.remove(obj);
1675 _wrappedObjects.remove(obj);
1581 }
1676 }
1582
1677
1583 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1678 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1584 {
1679 {
1585 _wrappedObjects.insert(obj, wrapper);
1680 _wrappedObjects.insert(obj, wrapper);
1586 }
1681 }
1587
1682
1588 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1683 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1589 {
1684 {
1590 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1685 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1591 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1686 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1592 // this is a wrapper whose QObject was already removed due to destruction
1687 // this is a wrapper whose QObject was already removed due to destruction
1593 // so the obj pointer has to be a new QObject with the same address...
1688 // so the obj pointer has to be a new QObject with the same address...
1594 // we remove the old one and set the copy to NULL
1689 // we remove the old one and set the copy to NULL
1595 wrap->_objPointerCopy = NULL;
1690 wrap->_objPointerCopy = NULL;
1596 removeWrapperPointer(obj);
1691 removeWrapperPointer(obj);
1597 wrap = NULL;
1692 wrap = NULL;
1598 }
1693 }
1599 return wrap;
1694 return wrap;
1600 }
1695 }
1601
1696
1602 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1697 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1603 {
1698 {
1604 PythonQtObjectPtr result;
1699 PythonQtObjectPtr result;
1700 PythonQt::self()->clearError();
1605 if (pycode) {
1701 if (pycode) {
1606 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1702 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1607 } else {
1703 } else {
1608 PythonQt::self()->handleError();
1704 PythonQt::self()->handleError();
1609 }
1705 }
1610 return result;
1706 return result;
1611 }
1707 }
1612
1708
1613 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1709 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1614 {
1710 {
1615 void* foreignObject = NULL;
1711 void* foreignObject = NULL;
1616 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1712 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1617 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1713 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1618 if (foreignObject) {
1714 if (foreignObject) {
1619 return foreignObject;
1715 return foreignObject;
1620 }
1716 }
1621 }
1717 }
1622 return NULL;
1718 return NULL;
1623 }
1719 }
1624
1720
1625 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1721 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1626 {
1722 {
1627 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1723 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1628 if (PyObject_HasAttrString(object, "__get__") &&
1724 if (PyObject_HasAttrString(object, "__get__") &&
1629 !PyObject_HasAttrString(object, "__set__") &&
1725 !PyObject_HasAttrString(object, "__set__") &&
1630 !PyMethod_Check(object) &&
1726 !PyMethod_Check(object) &&
1631 !PyFunction_Check(object) &&
1727 !PyFunction_Check(object) &&
1632 !PyClass_Check(object)) {
1728 !PyClass_Check(object)) {
1633 return true;
1729 return true;
1634 }
1730 }
1635 return false;
1731 return false;
1636 }
1732 }
1637
1733
1638 QString PythonQtPrivate::getSignature(PyObject* object)
1734 QString PythonQtPrivate::getSignature(PyObject* object)
1639 {
1735 {
1640 QString signature;
1736 QString signature;
1641
1737
1642 if (object) {
1738 if (object) {
1643 PyMethodObject* method = NULL;
1739 PyMethodObject* method = NULL;
1644 PyFunctionObject* func = NULL;
1740 PyFunctionObject* func = NULL;
1645
1741
1646 bool decrefMethod = false;
1742 bool decrefMethod = false;
1647
1743
1648 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1744 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1649 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1745 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1650 decrefMethod = true;
1746 decrefMethod = true;
1651 } else if (object->ob_type == &PyFunction_Type) {
1747 } else if (object->ob_type == &PyFunction_Type) {
1652 func = (PyFunctionObject*)object;
1748 func = (PyFunctionObject*)object;
1653 } else if (object->ob_type == &PyMethod_Type) {
1749 } else if (object->ob_type == &PyMethod_Type) {
1654 method = (PyMethodObject*)object;
1750 method = (PyMethodObject*)object;
1655 }
1751 }
1656 if (method) {
1752 if (method) {
1657 if (PyFunction_Check(method->im_func)) {
1753 if (PyFunction_Check(method->im_func)) {
1658 func = (PyFunctionObject*)method->im_func;
1754 func = (PyFunctionObject*)method->im_func;
1659 } else if (isMethodDescriptor((PyObject*)method)) {
1755 } else if (isMethodDescriptor((PyObject*)method)) {
1660 QString docstr;
1756 QString docstr;
1661 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1757 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1662 if (doc) {
1758 if (doc) {
1663 docstr = PyString_AsString(doc);
1759 docstr = PyString_AsString(doc);
1664 Py_DECREF(doc);
1760 Py_DECREF(doc);
1665 }
1761 }
1666
1762
1667 PyObject* s = PyObject_GetAttrString(object, "__name__");
1763 PyObject* s = PyObject_GetAttrString(object, "__name__");
1668 if (s) {
1764 if (s) {
1669 Q_ASSERT(PyString_Check(s));
1765 Q_ASSERT(PyString_Check(s));
1670 signature = PyString_AsString(s);
1766 signature = PyString_AsString(s);
1671 if (docstr.startsWith(signature + "(")) {
1767 if (docstr.startsWith(signature + "(")) {
1672 signature = docstr;
1768 signature = docstr;
1673 } else {
1769 } else {
1674 signature += "(...)";
1770 signature += "(...)";
1675 if (!docstr.isEmpty()) {
1771 if (!docstr.isEmpty()) {
1676 signature += "\n\n" + docstr;
1772 signature += "\n\n" + docstr;
1677 }
1773 }
1678 }
1774 }
1679 Py_DECREF(s);
1775 Py_DECREF(s);
1680 }
1776 }
1681 }
1777 }
1682 }
1778 }
1683
1779
1684 if (func) {
1780 if (func) {
1685 QString funcName;
1781 QString funcName;
1686 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1782 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1687 if (s) {
1783 if (s) {
1688 Q_ASSERT(PyString_Check(s));
1784 Q_ASSERT(PyString_Check(s));
1689 funcName = PyString_AsString(s);
1785 funcName = PyString_AsString(s);
1690 Py_DECREF(s);
1786 Py_DECREF(s);
1691 }
1787 }
1692 if (method && funcName == "__init__") {
1788 if (method && funcName == "__init__") {
1693 PyObject* s = PyObject_GetAttrString(object, "__name__");
1789 PyObject* s = PyObject_GetAttrString(object, "__name__");
1694 if (s) {
1790 if (s) {
1695 Q_ASSERT(PyString_Check(s));
1791 Q_ASSERT(PyString_Check(s));
1696 funcName = PyString_AsString(s);
1792 funcName = PyString_AsString(s);
1697 Py_DECREF(s);
1793 Py_DECREF(s);
1698 }
1794 }
1699 }
1795 }
1700
1796
1701 QStringList arguments;
1797 QStringList arguments;
1702 QStringList defaults;
1798 QStringList defaults;
1703 QString varargs;
1799 QString varargs;
1704 QString varkeywords;
1800 QString varkeywords;
1705 // NOTE: This implementation is based on function getargs() in inspect.py.
1801 // NOTE: This implementation is based on function getargs() in inspect.py.
1706 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1802 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1707 // It can be implemented, but it may be rarely needed and not necessary.
1803 // It can be implemented, but it may be rarely needed and not necessary.
1708 PyCodeObject* code = (PyCodeObject*)func->func_code;
1804 PyCodeObject* code = (PyCodeObject*)func->func_code;
1709 if (code->co_varnames) {
1805 if (code->co_varnames) {
1710 int nargs = code->co_argcount;
1806 int nargs = code->co_argcount;
1711 Q_ASSERT(PyTuple_Check(code->co_varnames));
1807 Q_ASSERT(PyTuple_Check(code->co_varnames));
1712 for (int i=0; i<nargs; i++) {
1808 for (int i=0; i<nargs; i++) {
1713 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1809 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1714 Q_ASSERT(PyString_Check(name));
1810 Q_ASSERT(PyString_Check(name));
1715 arguments << PyString_AsString(name);
1811 arguments << PyString_AsString(name);
1716 }
1812 }
1717 if (code->co_flags & CO_VARARGS) {
1813 if (code->co_flags & CO_VARARGS) {
1718 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1814 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1719 Q_ASSERT(PyString_Check(s));
1815 Q_ASSERT(PyString_Check(s));
1720 varargs = PyString_AsString(s);
1816 varargs = PyString_AsString(s);
1721 nargs += 1;
1817 nargs += 1;
1722 }
1818 }
1723 if (code->co_flags & CO_VARKEYWORDS) {
1819 if (code->co_flags & CO_VARKEYWORDS) {
1724 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1820 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1725 Q_ASSERT(PyString_Check(s));
1821 Q_ASSERT(PyString_Check(s));
1726 varkeywords = PyString_AsString(s);
1822 varkeywords = PyString_AsString(s);
1727 }
1823 }
1728 }
1824 }
1729
1825
1730 PyObject* defaultsTuple = func->func_defaults;
1826 PyObject* defaultsTuple = func->func_defaults;
1731 if (defaultsTuple) {
1827 if (defaultsTuple) {
1732 Q_ASSERT(PyTuple_Check(defaultsTuple));
1828 Q_ASSERT(PyTuple_Check(defaultsTuple));
1733 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1829 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1734 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1830 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1735 PyObject* s = PyObject_Repr(d);
1831 PyObject* s = PyObject_Repr(d);
1736 Q_ASSERT(PyString_Check(s));
1832 Q_ASSERT(PyString_Check(s));
1737 defaults << PyString_AsString(s);
1833 defaults << PyString_AsString(s);
1738 Py_DECREF(s);
1834 Py_DECREF(s);
1739 }
1835 }
1740 }
1836 }
1741
1837
1742 int firstdefault = arguments.size() - defaults.size();
1838 int firstdefault = arguments.size() - defaults.size();
1743 for (int i=0; i<arguments.size(); i++) {
1839 for (int i=0; i<arguments.size(); i++) {
1744 if (!signature.isEmpty()) { signature += ", "; }
1840 if (!signature.isEmpty()) { signature += ", "; }
1745 if (!method || i>0 || arguments[i] != "self") {
1841 if (!method || i>0 || arguments[i] != "self") {
1746 signature += arguments[i];
1842 signature += arguments[i];
1747 if (i >= firstdefault) {
1843 if (i >= firstdefault) {
1748 signature += "=" + defaults[i-firstdefault];
1844 signature += "=" + defaults[i-firstdefault];
1749 }
1845 }
1750 }
1846 }
1751 }
1847 }
1752 if (!varargs.isEmpty()) {
1848 if (!varargs.isEmpty()) {
1753 if (!signature.isEmpty()) { signature += ", "; }
1849 if (!signature.isEmpty()) { signature += ", "; }
1754 signature += "*" + varargs;
1850 signature += "*" + varargs;
1755 }
1851 }
1756 if (!varkeywords.isEmpty()) {
1852 if (!varkeywords.isEmpty()) {
1757 if (!signature.isEmpty()) { signature += ", "; }
1853 if (!signature.isEmpty()) { signature += ", "; }
1758 signature += "**" + varkeywords;
1854 signature += "**" + varkeywords;
1759 }
1855 }
1760 signature = funcName + "(" + signature + ")";
1856 signature = funcName + "(" + signature + ")";
1761 }
1857 }
1762
1858
1763 if (method && decrefMethod) {
1859 if (method && decrefMethod) {
1764 Py_DECREF(method);
1860 Py_DECREF(method);
1765 }
1861 }
1766 }
1862 }
1767
1863
1768 return signature;
1864 return signature;
1769 }
1865 }
1770
1866
1771 void PythonQtPrivate::shellClassDeleted( void* shellClass )
1867 void PythonQtPrivate::shellClassDeleted( void* shellClass )
1772 {
1868 {
1773 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
1869 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
1774 if (wrap && wrap->_wrappedPtr) {
1870 if (wrap && wrap->_wrappedPtr) {
1775 // this is a pure C++ wrapper and the shell has gone, so we need
1871 // this is a pure C++ wrapper and the shell has gone, so we need
1776 // to set the _wrappedPtr to NULL on the wrapper
1872 // to set the _wrappedPtr to NULL on the wrapper
1777 wrap->_wrappedPtr = NULL;
1873 wrap->_wrappedPtr = NULL;
1778 // and then we remove the wrapper, since the wrapped class is gone
1874 // and then we remove the wrapper, since the wrapped class is gone
1779 _wrappedObjects.remove(shellClass);
1875 _wrappedObjects.remove(shellClass);
1780 }
1876 }
1781 // if the wrapper is a QObject, we do not handle this here,
1877 // if the wrapper is a QObject, we do not handle this here,
1782 // it will be handled by the QPointer<> to the QObject, which becomes NULL
1878 // it will be handled by the QPointer<> to the QObject, which becomes NULL
1783 // via the QObject destructor.
1879 // via the QObject destructor.
1784 }
1880 }
1785
1881
1786 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( const void* data, Py_ssize_t size )
1882 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( const void* data, Py_ssize_t size )
1787 {
1883 {
1788 // P3K port needed later on!
1884 // P3K port needed later on!
1789 return PyBuffer_FromMemory((void*)data, size);
1885 return PyBuffer_FromMemory((void*)data, size);
1790 }
1886 }
1791
1887
1792 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( void* data, Py_ssize_t size )
1888 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( void* data, Py_ssize_t size )
1793 {
1889 {
1794 // P3K port needed later on!
1890 // P3K port needed later on!
1795 return PyBuffer_FromReadWriteMemory(data, size);
1891 return PyBuffer_FromReadWriteMemory(data, size);
1796 } No newline at end of file
1892 }
@@ -1,720 +1,743
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 //! read vars etc. in scope of the given \c object
336 //! read vars etc. in scope of the given \c object
337 QStringList introspectObject(PyObject* object, ObjectType type);
337 QStringList introspectObject(PyObject* object, ObjectType type);
338 //! read vars etc. in scope of the type object called \c typename. First the typename
338 //! read vars etc. in scope of the type object called \c typename. First the typename
339 //! of the form module.type is split into module and type. Then the module is looked up
339 //! of the form module.type is split into module and type. Then the module is looked up
340 //! in sys.modules. If the module or type is not found there, then the type is looked up in
340 //! in sys.modules. If the module or type is not found there, then the type is looked up in
341 //! the __builtin__ module.
341 //! the __builtin__ module.
342 QStringList introspectType(const QString& typeName, ObjectType type);
342 QStringList introspectType(const QString& typeName, ObjectType type);
343
343
344 //! returns the found callable object or NULL
344 //! returns the found callable object or NULL
345 //! @return new reference
345 //! @return new reference
346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
347
347
348 //! returns the return type of the method of a wrapped c++ object referenced by \c objectname
348 //! returns the return type of the method of a wrapped c++ object referenced by \c objectname
349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
350 //! returns the return type of the method \c methodName of a wrapped c++ type referenced by \c typeName
350 //! returns the return type of the method \c methodName of a wrapped c++ type referenced by \c typeName
351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
352 //@}
352 //@}
353
353
354 //---------------------------------------------------------------------------
354 //---------------------------------------------------------------------------
355 //! \name Calling Python Objects
355 //! \name Calling Python Objects
356 //@{
356 //@{
357
357
358 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
358 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
360
360
361 //! call the given python object, returns the result converted to a QVariant
361 //! call the given python object, returns the result converted to a QVariant
362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
363
363
364 //! call the given python object, returns the result as new PyObject
364 //! call the given python object, returns the result as new PyObject
365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap());
366
366
367 //@}
367 //@}
368
368
369 //---------------------------------------------------------------------------
369 //---------------------------------------------------------------------------
370 //! \name Decorations, Constructors, Wrappers...
370 //! \name Decorations, Constructors, Wrappers...
371 //@{
371 //@{
372
372
373 //! add an object whose slots will be used as decorator slots for
373 //! add an object whose slots will be used as decorator slots for
374 //! other QObjects or CPP classes. The slots need to follow the
374 //! other QObjects or CPP classes. The slots need to follow the
375 //! convention that the first argument is a pointer to the wrapped object.
375 //! convention that the first argument is a pointer to the wrapped object.
376 //! (ownership is passed to PythonQt)
376 //! (ownership is passed to PythonQt)
377 /*!
377 /*!
378 Example:
378 Example:
379
379
380 A slot with the signature
380 A slot with the signature
381
381
382 \code
382 \code
383 bool doSomething(QWidget* w, int a)
383 bool doSomething(QWidget* w, int a)
384 \endcode
384 \endcode
385
385
386 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
386 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
387 that will be called with the concrete instance as first argument.
387 that will be called with the concrete instance as first argument.
388 So in Python you can now e.g. call
388 So in Python you can now e.g. call
389
389
390 \code
390 \code
391 someWidget.doSomething(12)
391 someWidget.doSomething(12)
392 \endcode
392 \endcode
393
393
394 without QWidget really having this method. This allows to easily make normal methods
394 without QWidget really having this method. This allows to easily make normal methods
395 of Qt classes callable by forwarding them with such decorator slots
395 of Qt classes callable by forwarding them with such decorator slots
396 or to make CPP classes (which are not derived from QObject) callable from Python.
396 or to make CPP classes (which are not derived from QObject) callable from Python.
397 */
397 */
398 void addInstanceDecorators(QObject* o);
398 void addInstanceDecorators(QObject* o);
399
399
400 //! add an object whose slots will be used as decorator slots for
400 //! add an object whose slots will be used as decorator slots for
401 //! class objects (ownership is passed to PythonQt)
401 //! class objects (ownership is passed to PythonQt)
402 /*!
402 /*!
403 The slots need to follow the following convention:
403 The slots need to follow the following convention:
404 - SomeClass* new_SomeClass(...)
404 - SomeClass* new_SomeClass(...)
405 - QVariant new_SomeClass(...)
405 - QVariant new_SomeClass(...)
406 - void delete_SomeClass(SomeClass*)
406 - void delete_SomeClass(SomeClass*)
407 - ... static_SomeClass_someName(...)
407 - ... static_SomeClass_someName(...)
408
408
409 This will add:
409 This will add:
410 - a constructor
410 - a constructor
411 - a constructor which generates a QVariant
411 - a constructor which generates a QVariant
412 - a destructor (only useful for CPP objects)
412 - a destructor (only useful for CPP objects)
413 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
413 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
414
414
415 */
415 */
416 void addClassDecorators(QObject* o);
416 void addClassDecorators(QObject* o);
417
417
418 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
418 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
419 void addDecorators(QObject* o);
419 void addDecorators(QObject* o);
420
420
421 //! add the given factory to PythonQt (ownership stays with caller)
421 //! add the given factory to PythonQt (ownership stays with caller)
422 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
422 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
423
423
424 //! add the given factory to PythonQt (ownership stays with caller)
424 //! add the given factory to PythonQt (ownership stays with caller)
425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
426
426
427 //! remove the wrapper factory
427 //! remove the wrapper factory
428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
429
429
430 //! remove the wrapper factory
430 //! remove the wrapper factory
431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
432
432
433 //@}
433 //@}
434
434
435 //---------------------------------------------------------------------------
435 //---------------------------------------------------------------------------
436 //! \name Custom Importer
436 //! \name Custom Importer
437 //@{
437 //@{
438
438
439 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
439 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
440 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
440 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
441 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
441 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
442 //! This is not reversible, so even setting setImporter(NULL) afterwards will
442 //! This is not reversible, so even setting setImporter(NULL) afterwards will
443 //! keep the custom PythonQt importer with a QFile default import interface.
443 //! keep the custom PythonQt importer with a QFile default import interface.
444 //! Subsequent python import calls will make use of the passed importInterface
444 //! Subsequent python import calls will make use of the passed importInterface
445 //! which forwards all import calls to the given \c importInterface.
445 //! which forwards all import calls to the given \c importInterface.
446 //! Passing NULL will install a default QFile importer.
446 //! Passing NULL will install a default QFile importer.
447 //! (\c importInterface ownership stays with caller)
447 //! (\c importInterface ownership stays with caller)
448 void setImporter(PythonQtImportFileInterface* importInterface);
448 void setImporter(PythonQtImportFileInterface* importInterface);
449
449
450 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
450 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
451 //! (without calling setImporter or installDefaultImporter at least once, the default python import
451 //! (without calling setImporter or installDefaultImporter at least once, the default python import
452 //! mechanism is in place)
452 //! mechanism is in place)
453 //! the default importer allows to import files from anywhere QFile can read from,
453 //! the default importer allows to import files from anywhere QFile can read from,
454 //! including the Qt resource system using ":". Keep in mind that you need to extend
454 //! including the Qt resource system using ":". Keep in mind that you need to extend
455 //! "sys.path" with ":" to be able to import from the Qt resources.
455 //! "sys.path" with ":" to be able to import from the Qt resources.
456 void installDefaultImporter() { setImporter(NULL); }
456 void installDefaultImporter() { setImporter(NULL); }
457
457
458 //! set paths that the importer should ignore
458 //! set paths that the importer should ignore
459 void setImporterIgnorePaths(const QStringList& paths);
459 void setImporterIgnorePaths(const QStringList& paths);
460
460
461 //! get paths that the importer should ignore
461 //! get paths that the importer should ignore
462 const QStringList& getImporterIgnorePaths();
462 const QStringList& getImporterIgnorePaths();
463
463
464 //! get access to the file importer (if set)
464 //! get access to the file importer (if set)
465 static PythonQtImportFileInterface* importInterface();
465 static PythonQtImportFileInterface* importInterface();
466
466
467 //@}
467 //@}
468
468
469 //---------------------------------------------------------------------------
469 //---------------------------------------------------------------------------
470 //! \name Other Stuff
470 //! \name Other Stuff
471 //@{
471 //@{
472
472
473 //! get access to internal data (should not be used on the public API, but is used by some C functions)
473 //! get access to internal data (should not be used on the public API, but is used by some C functions)
474 static PythonQtPrivate* priv() { return _self->_p; }
474 static PythonQtPrivate* priv() { return _self->_p; }
475
475
476 //! clear all NotFound entries on all class infos, to ensure that
477 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
478 void clearNotFoundCachedMembers();
479
476 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
480 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
477 //! The error is currently just output to the python stderr, future version might implement better trace printing
481 //! The error is currently just output to the python stderr, future version might implement better trace printing
478 bool handleError();
482 bool handleError();
479
483
480 //! clear all NotFound entries on all class infos, to ensure that
484 //! return \a true if \a handleError() has been called and an error occured.
481 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
485 bool hadError()const;
482 void clearNotFoundCachedMembers();
486
487 //! reset error flag. After calling this, hadError() will return false.
488 //! \sa hadError()
489 void clearError();
490
491 //! if set to true, the systemExitExceptionRaised signal will be emitted if exception SystemExit is caught
492 //! \sa handleError()
493 void setSystemExitExceptionHandlerEnabled(bool value);
483
494
484 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
495 //! return \a true if SystemExit exception is handled by PythonQt
496 //! \sa setSystemExitExceptionHandlerEnabled()
497 bool systemExitExceptionHandlerEnabled() const;
498
499 //! set a callback that is called when a QObject with parent == NULL is wrapped by PythonQt
485 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
500 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
486 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
501 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by PythonQt
487 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
502 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
488
503
489 //! call the callback if it is set
504 //! call the callback if it is set
490 static void qObjectNoLongerWrappedCB(QObject* o);
505 static void qObjectNoLongerWrappedCB(QObject* o);
491
506
492 //! called by internal help methods
507 //! called by internal help methods
493 PyObject* helpCalled(PythonQtClassInfo* info);
508 PyObject* helpCalled(PythonQtClassInfo* info);
494
509
495 //! returns the found object or NULL
510 //! returns the found object or NULL
496 //! @return new reference
511 //! @return new reference
497 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
512 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
498
513
499 //! sets a callback that is called before and after function calls for profiling
514 //! sets a callback that is called before and after function calls for profiling
500 void setProfilingCallback(ProfilingCB* cb);
515 void setProfilingCallback(ProfilingCB* cb);
501
516
502 //@}
517 //@}
503
518
504 signals:
519 signals:
505 //! emitted when python outputs something to stdout (and redirection is turned on)
520 //! emitted when python outputs something to stdout (and redirection is turned on)
506 void pythonStdOut(const QString& str);
521 void pythonStdOut(const QString& str);
507 //! emitted when python outputs something to stderr (and redirection is turned on)
522 //! emitted when python outputs something to stderr (and redirection is turned on)
508 void pythonStdErr(const QString& str);
523 void pythonStdErr(const QString& str);
509
524
510 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
525 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
511 void pythonHelpRequest(const QByteArray& cppClassName);
526 void pythonHelpRequest(const QByteArray& cppClassName);
512
527
528 //! emitted when both custom SystemExit exception handler is enabled and a SystemExit
529 //! exception is raised.
530 //! \sa setSystemExitExceptionHandlerEnabled(bool)
531 void systemExitExceptionRaised(int exitCode);
532
513 private:
533 private:
514 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
534 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
515
535
516 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
536 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
517
537
518 PyObject* getObjectByType(const QString& typeName);
538 PyObject* getObjectByType(const QString& typeName);
519
539
520 //! callback for stdout redirection, emits pythonStdOut signal
540 //! callback for stdout redirection, emits pythonStdOut signal
521 static void stdOutRedirectCB(const QString& str);
541 static void stdOutRedirectCB(const QString& str);
522 //! callback for stderr redirection, emits pythonStdErr signal
542 //! callback for stderr redirection, emits pythonStdErr signal
523 static void stdErrRedirectCB(const QString& str);
543 static void stdErrRedirectCB(const QString& str);
524
544
525 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
545 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
526 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
546 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
527
547
528 PythonQt(int flags, const QByteArray& pythonQtModuleName);
548 PythonQt(int flags, const QByteArray& pythonQtModuleName);
529 ~PythonQt();
549 ~PythonQt();
530
550
531 static PythonQt* _self;
551 static PythonQt* _self;
532 static int _uniqueModuleCount;
552 static int _uniqueModuleCount;
533
553
534 PythonQtPrivate* _p;
554 PythonQtPrivate* _p;
535
555
536 };
556 };
537
557
538 //! internal PythonQt details
558 //! internal PythonQt details
539 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
559 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
540
560
541 Q_OBJECT
561 Q_OBJECT
542
562
543 public:
563 public:
544 PythonQtPrivate();
564 PythonQtPrivate();
545 ~PythonQtPrivate();
565 ~PythonQtPrivate();
546
566
547 enum DecoratorTypes {
567 enum DecoratorTypes {
548 StaticDecorator = 1,
568 StaticDecorator = 1,
549 ConstructorDecorator = 2,
569 ConstructorDecorator = 2,
550 DestructorDecorator = 4,
570 DestructorDecorator = 4,
551 InstanceDecorator = 8,
571 InstanceDecorator = 8,
552 AllDecorators = 0xffff
572 AllDecorators = 0xffff
553 };
573 };
554
574
555 //! get the suffixes that are used for shared libraries
575 //! get the suffixes that are used for shared libraries
556 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
576 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
557
577
558 //! returns if the id is the id for PythonQtObjectPtr
578 //! returns if the id is the id for PythonQtObjectPtr
559 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
579 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
560
580
561 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
581 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
562 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
582 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
563 //! remove the wrapper ptr again
583 //! remove the wrapper ptr again
564 void removeWrapperPointer(void* obj);
584 void removeWrapperPointer(void* obj);
565
585
566 //! called by destructor of shells to allow invalidation of the Python wrapper
586 //! called by destructor of shells to allow invalidation of the Python wrapper
567 void shellClassDeleted(void* shellClass);
587 void shellClassDeleted(void* shellClass);
568
588
569 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
589 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
570 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
590 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
571
591
572 //! add parent class relation
592 //! add parent class relation
573 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
593 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
574
594
575 //! add a handler for polymorphic downcasting
595 //! add a handler for polymorphic downcasting
576 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
596 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
577
597
578 //! lookup existing classinfo and return new if not yet present
598 //! lookup existing classinfo and return new if not yet present
579 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
599 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
580
600
581 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
601 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
582 void removeSignalEmitter(QObject* obj);
602 void removeSignalEmitter(QObject* obj);
583
603
584 //! wrap the given QObject into a Python object (or return existing wrapper!)
604 //! wrap the given QObject into a Python object (or return existing wrapper!)
585 PyObject* wrapQObject(QObject* obj);
605 PyObject* wrapQObject(QObject* obj);
586
606
587 //! 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
607 //! 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
588 PyObject* wrapPtr(void* ptr, const QByteArray& name);
608 PyObject* wrapPtr(void* ptr, const QByteArray& name);
589
609
590 //! create a read-only buffer object from the given memory
610 //! create a read-only buffer object from the given memory
591 static PyObject* wrapMemoryAsBuffer(const void* data, Py_ssize_t size);
611 static PyObject* wrapMemoryAsBuffer(const void* data, Py_ssize_t size);
592
612
593 //! create a read-write buffer object from the given memory
613 //! create a read-write buffer object from the given memory
594 static PyObject* wrapMemoryAsBuffer(void* data, Py_ssize_t size);
614 static PyObject* wrapMemoryAsBuffer(void* data, Py_ssize_t size);
595
615
596 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
616 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
597 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
617 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
598 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
618 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
599 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
619 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
600
620
601 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
621 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
602 //! (ownership of wrapper is passed to PythonQt)
622 //! (ownership of wrapper is passed to PythonQt)
603 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
623 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
604
624
605 This will add a wrapper object that is used to make calls to the given classname \c typeName.
625 This will add a wrapper object that is used to make calls to the given classname \c typeName.
606 All slots that take a pointer to typeName as the first argument will be callable from Python on
626 All slots that take a pointer to typeName as the first argument will be callable from Python on
607 a variant object that contains such a type.
627 a variant object that contains such a type.
608 */
628 */
609 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);
629 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);
610
630
611 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
631 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
612 //! and it will register the classes when it first sees a pointer to such a derived class
632 //! and it will register the classes when it first sees a pointer to such a derived class
613 void registerQObjectClassNames(const QStringList& names);
633 void registerQObjectClassNames(const QStringList& names);
614
634
615 //! add a decorator object
635 //! add a decorator object
616 void addDecorators(QObject* o, int decoTypes);
636 void addDecorators(QObject* o, int decoTypes);
617
637
618 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
638 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
619 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
639 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
620
640
621 //! create a new instance of the given enum type with given value (returns a new reference)
641 //! create a new instance of the given enum type with given value (returns a new reference)
622 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
642 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
623
643
624 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
644 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
625 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
645 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
626
646
627 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
647 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
628 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
648 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
629
649
630 //! get the class info for a meta object (if available)
650 //! get the class info for a meta object (if available)
631 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
651 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
632
652
633 //! get the class info for a meta object (if available)
653 //! get the class info for a meta object (if available)
634 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
654 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
635
655
636 //! creates the new module from the given pycode
656 //! creates the new module from the given pycode
637 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
657 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
638
658
639 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
659 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
640 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
660 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
641
661
642 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
662 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
643 static PyObject* dummyTuple();
663 static PyObject* dummyTuple();
644
664
645 //! called by virtual overloads when a python return value can not be converted to the required Qt type
665 //! called by virtual overloads when a python return value can not be converted to the required Qt type
646 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
666 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
647
667
648 //! get access to the PythonQt module
668 //! get access to the PythonQt module
649 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
669 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
650
670
651 //! returns the profiling callback, which may be NULL
671 //! returns the profiling callback, which may be NULL
652 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
672 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
653
673
654 //! determines the signature of the given callable object (similar as pydoc)
674 //! determines the signature of the given callable object (similar as pydoc)
655 QString getSignature(PyObject* object);
675 QString getSignature(PyObject* object);
656
676
657 //! returns true if the object is a method descriptor (same as inspect.ismethoddescriptor() in inspect.py)
677 //! returns true if the object is a method descriptor (same as inspect.ismethoddescriptor() in inspect.py)
658 bool isMethodDescriptor(PyObject* object) const;
678 bool isMethodDescriptor(PyObject* object) const;
659
679
660 private:
680 private:
661 //! Setup the shared library suffixes by getting them from the "imp" module.
681 //! Setup the shared library suffixes by getting them from the "imp" module.
662 void setupSharedLibrarySuffixes();
682 void setupSharedLibrarySuffixes();
663
683
664 //! create a new pythonqt class wrapper and place it in the pythonqt module
684 //! create a new pythonqt class wrapper and place it in the pythonqt module
665 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
685 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
666
686
667 //! get/create new package module (the returned object is a borrowed reference)
687 //! get/create new package module (the returned object is a borrowed reference)
668 PyObject* packageByName(const char* name);
688 PyObject* packageByName(const char* name);
669
689
670 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
690 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
671 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
691 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
672
692
673 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
693 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
674 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
694 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
675
695
676 //! stores the meta info of known Qt classes
696 //! stores the meta info of known Qt classes
677 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
697 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
678
698
679 //! names of qobject derived classes that can be casted to qobject savely
699 //! names of qobject derived classes that can be casted to qobject savely
680 QHash<QByteArray, bool> _knownQObjectClassNames;
700 QHash<QByteArray, bool> _knownQObjectClassNames;
681
701
682 //! stores signal receivers for QObjects
702 //! stores signal receivers for QObjects
683 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
703 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
684
704
685 //! the PythonQt python module
705 //! the PythonQt python module
686 PythonQtObjectPtr _pythonQtModule;
706 PythonQtObjectPtr _pythonQtModule;
687
707
688 //! the name of the PythonQt python module
708 //! the name of the PythonQt python module
689 QByteArray _pythonQtModuleName;
709 QByteArray _pythonQtModuleName;
690
710
691 //! the importer interface (if set)
711 //! the importer interface (if set)
692 PythonQtImportFileInterface* _importInterface;
712 PythonQtImportFileInterface* _importInterface;
693
713
694 //! the default importer
714 //! the default importer
695 PythonQtQFileImporter* _defaultImporter;
715 PythonQtQFileImporter* _defaultImporter;
696
716
697 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
717 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
698 PythonQtQObjectWrappedCB* _wrappedCB;
718 PythonQtQObjectWrappedCB* _wrappedCB;
699
719
700 QStringList _importIgnorePaths;
720 QStringList _importIgnorePaths;
701 QStringList _sharedLibrarySuffixes;
721 QStringList _sharedLibrarySuffixes;
702
722
703 //! the cpp object wrapper factories
723 //! the cpp object wrapper factories
704 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
724 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
705
725
706 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
726 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
707
727
708 QHash<QByteArray, PyObject*> _packages;
728 QHash<QByteArray, PyObject*> _packages;
709
729
710 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
730 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
711
731
712 PythonQt::ProfilingCB* _profilingCB;
732 PythonQt::ProfilingCB* _profilingCB;
713
733
714 int _initFlags;
734 int _initFlags;
715 int _PythonQtObjectPtr_metaId;
735 int _PythonQtObjectPtr_metaId;
716
736
737 bool _hadError;
738 bool _systemExitExceptionHandlerEnabled;
739
717 friend class PythonQt;
740 friend class PythonQt;
718 };
741 };
719
742
720 #endif
743 #endif
@@ -1,55 +1,56
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2011 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2011 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 #ifndef __PythonQtPythonInclude_h
33 #ifndef __PythonQtPythonInclude_h
34 #define __PythonQtPythonInclude_h
34 #define __PythonQtPythonInclude_h
35
35
36 // Undefine macros that Python.h defines to avoid redefinition warning.
36 // Undefine macros that Python.h defines to avoid redefinition warning.
37 #undef _POSIX_C_SOURCE
37 #undef _POSIX_C_SOURCE
38 #undef _POSIX_THREADS
38 #undef _POSIX_THREADS
39 #undef _XOPEN_SOURCE
39 #undef _XOPEN_SOURCE
40
40
41 // If PYTHONQT_USE_RELEASE_PYTHON_FALLBACK is enabled, try to link
41 // If PYTHONQT_USE_RELEASE_PYTHON_FALLBACK is enabled, try to link
42 // release Python DLL if it is available by undefining _DEBUG while
42 // release Python DLL if it is available by undefining _DEBUG while
43 // including Python.h
43 // including Python.h
44 #if defined(PYTHONQT_USE_RELEASE_PYTHON_FALLBACK) && defined(_DEBUG)
44 #if defined(PYTHONQT_USE_RELEASE_PYTHON_FALLBACK) && defined(_DEBUG)
45 #undef _DEBUG
45 #undef _DEBUG
46 #if defined(_MSC_VER) && _MSC_VER >= 1400
46 #if defined(_MSC_VER) && _MSC_VER >= 1400
47 #define _CRT_NOFORCE_MANIFEST 1
47 #define _CRT_NOFORCE_MANIFEST 1
48 #define _STL_NOFORCE_MANIFEST 1
48 #endif
49 #endif
49 #include <Python.h>
50 #include <Python.h>
50 #define _DEBUG
51 #define _DEBUG
51 #else
52 #else
52 #include <Python.h>
53 #include <Python.h>
53 #endif
54 #endif
54
55
55 #endif
56 #endif
@@ -1,152 +1,159
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtStdOut.cpp
35 // \file PythonQtStdOut.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdOut.h"
42 #include "PythonQtStdOut.h"
43
43
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
45 {
45 {
46 PythonQtStdOutRedirect *self;
46 PythonQtStdOutRedirect *self;
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
48
48
49 self->softspace = 0;
49 self->softspace = 0;
50 self->_cb = NULL;
50 self->_cb = NULL;
51
51
52 return (PyObject *)self;
52 return (PyObject *)self;
53 }
53 }
54
54
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
56 {
56 {
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
58 if (s->_cb) {
58 if (s->_cb) {
59 QString output;
59 QString output;
60 if (PyTuple_GET_SIZE(args)>=1) {
60 if (PyTuple_GET_SIZE(args)>=1) {
61 PyObject* obj = PyTuple_GET_ITEM(args,0);
61 PyObject* obj = PyTuple_GET_ITEM(args,0);
62 if (PyUnicode_Check(obj)) {
62 if (PyUnicode_Check(obj)) {
63 PyObject *tmp = PyUnicode_AsUTF8String(obj);
63 PyObject *tmp = PyUnicode_AsUTF8String(obj);
64 if(tmp) {
64 if(tmp) {
65 output = QString::fromUtf8(PyString_AS_STRING(tmp));
65 output = QString::fromUtf8(PyString_AS_STRING(tmp));
66 Py_DECREF(tmp);
66 Py_DECREF(tmp);
67 } else {
67 } else {
68 return NULL;
68 return NULL;
69 }
69 }
70 } else {
70 } else {
71 char *string;
71 char *string;
72 if (!PyArg_ParseTuple(args, "s", &string)) {
72 if (!PyArg_ParseTuple(args, "s", &string)) {
73 return NULL;
73 return NULL;
74 }
74 }
75 output = QString::fromLatin1(string);
75 output = QString::fromLatin1(string);
76 }
76 }
77 }
77 }
78
78
79 if (s->softspace > 0) {
79 if (s->softspace > 0) {
80 (*s->_cb)(QString(""));
80 (*s->_cb)(QString(""));
81 s->softspace = 0;
81 s->softspace = 0;
82 }
82 }
83
83
84 (*s->_cb)(output);
84 (*s->_cb)(output);
85 }
85 }
86 return Py_BuildValue("");
86 return Py_BuildValue("");
87 }
87 }
88
88
89 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
89 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
90 {
90 {
91 return Py_BuildValue("");
91 return Py_BuildValue("");
92 }
92 }
93
93
94
94 static PyObject *PythonQtStdOutRedirect_isatty(PyObject * /*self*/, PyObject * /*args*/)
95 {
96 Py_INCREF(Py_False);
97 return Py_False;
98 }
95
99
96 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
100 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
97 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
101 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
98 "redirect the writing to a callback"},
102 "redirect the writing to a callback"},
99 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
103 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
100 "flush the output, currently not implemented but needed for logging framework"
104 "flush the output, currently not implemented but needed for logging framework"
101 },
105 },
106 {"isatty", (PyCFunction)PythonQtStdOutRedirect_isatty, METH_NOARGS,
107 "return False since this object is not a tty-like device. Needed for logging framework"
108 },
102 {NULL, NULL, 0 , NULL} /* sentinel */
109 {NULL, NULL, 0 , NULL} /* sentinel */
103 };
110 };
104
111
105 static PyMemberDef PythonQtStdOutRedirect_members[] = {
112 static PyMemberDef PythonQtStdOutRedirect_members[] = {
106 {const_cast<char*>("softspace"), T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
113 {const_cast<char*>("softspace"), T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
107 const_cast<char*>("soft space flag")
114 const_cast<char*>("soft space flag")
108 },
115 },
109 {NULL} /* Sentinel */
116 {NULL} /* Sentinel */
110 };
117 };
111
118
112 PyTypeObject PythonQtStdOutRedirectType = {
119 PyTypeObject PythonQtStdOutRedirectType = {
113 PyObject_HEAD_INIT(NULL)
120 PyObject_HEAD_INIT(NULL)
114 0, /*ob_size*/
121 0, /*ob_size*/
115 "PythonQtStdOutRedirect", /*tp_name*/
122 "PythonQtStdOutRedirect", /*tp_name*/
116 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
123 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
117 0, /*tp_itemsize*/
124 0, /*tp_itemsize*/
118 0, /*tp_dealloc*/
125 0, /*tp_dealloc*/
119 0, /*tp_print*/
126 0, /*tp_print*/
120 0, /*tp_getattr*/
127 0, /*tp_getattr*/
121 0, /*tp_setattr*/
128 0, /*tp_setattr*/
122 0, /*tp_compare*/
129 0, /*tp_compare*/
123 0, /*tp_repr*/
130 0, /*tp_repr*/
124 0, /*tp_as_number*/
131 0, /*tp_as_number*/
125 0, /*tp_as_sequence*/
132 0, /*tp_as_sequence*/
126 0, /*tp_as_mapping*/
133 0, /*tp_as_mapping*/
127 0, /*tp_hash */
134 0, /*tp_hash */
128 0, /*tp_call*/
135 0, /*tp_call*/
129 0, /*tp_str*/
136 0, /*tp_str*/
130 0, /*tp_getattro*/
137 0, /*tp_getattro*/
131 0, /*tp_setattro*/
138 0, /*tp_setattro*/
132 0, /*tp_as_buffer*/
139 0, /*tp_as_buffer*/
133 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
140 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
134 "PythonQtStdOutRedirect", /* tp_doc */
141 "PythonQtStdOutRedirect", /* tp_doc */
135 0, /* tp_traverse */
142 0, /* tp_traverse */
136 0, /* tp_clear */
143 0, /* tp_clear */
137 0, /* tp_richcompare */
144 0, /* tp_richcompare */
138 0, /* tp_weaklistoffset */
145 0, /* tp_weaklistoffset */
139 0, /* tp_iter */
146 0, /* tp_iter */
140 0, /* tp_iternext */
147 0, /* tp_iternext */
141 PythonQtStdOutRedirect_methods, /* tp_methods */
148 PythonQtStdOutRedirect_methods, /* tp_methods */
142 PythonQtStdOutRedirect_members, /* tp_members */
149 PythonQtStdOutRedirect_members, /* tp_members */
143 0, /* tp_getset */
150 0, /* tp_getset */
144 0, /* tp_base */
151 0, /* tp_base */
145 0, /* tp_dict */
152 0, /* tp_dict */
146 0, /* tp_descr_get */
153 0, /* tp_descr_get */
147 0, /* tp_descr_set */
154 0, /* tp_descr_set */
148 0, /* tp_dictoffset */
155 0, /* tp_dictoffset */
149 0, /* tp_init */
156 0, /* tp_init */
150 0, /* tp_alloc */
157 0, /* tp_alloc */
151 PythonQtStdOutRedirect_new, /* tp_new */
158 PythonQtStdOutRedirect_new, /* tp_new */
152 };
159 };
General Comments 0
You need to be logged in to leave comments. Login now