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