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