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