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