##// END OF EJS Templates
improved docs...
florianlink -
r144:d6f318e43301
parent child
Show More
@@ -1,1220 +1,1230
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 "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
61
61
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 {
63 {
64 if (!_self) {
64 if (!_self) {
65 _self = new PythonQt(flags, pythonQtModuleName);
65 _self = new PythonQt(flags, pythonQtModuleName);
66
66
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69
69
70 PythonQtRegisterToolClassesTemplateConverter(int);
70 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(float);
71 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(double);
72 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 // TODO: which other POD types should be available for QList etc.
77 // TODO: which other POD types should be available for QList etc.
78
78
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
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 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
84 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
85 PythonQtRegisterToolClassesTemplateConverter(QDate);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
86 PythonQtRegisterToolClassesTemplateConverter(QTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
87 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
88 PythonQtRegisterToolClassesTemplateConverter(QUrl);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
89 PythonQtRegisterToolClassesTemplateConverter(QLocale);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
90 PythonQtRegisterToolClassesTemplateConverter(QRect);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
91 PythonQtRegisterToolClassesTemplateConverter(QRectF);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
92 PythonQtRegisterToolClassesTemplateConverter(QSize);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
93 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
94 PythonQtRegisterToolClassesTemplateConverter(QLine);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
95 PythonQtRegisterToolClassesTemplateConverter(QLineF);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
96 PythonQtRegisterToolClassesTemplateConverter(QPoint);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
97 PythonQtRegisterToolClassesTemplateConverter(QPointF);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
98 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
99
99
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
100 PythonQtRegisterToolClassesTemplateConverter(QFont);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
101 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
102 PythonQtRegisterToolClassesTemplateConverter(QBrush);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
103 PythonQtRegisterToolClassesTemplateConverter(QColor);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
104 PythonQtRegisterToolClassesTemplateConverter(QPalette);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
105 PythonQtRegisterToolClassesTemplateConverter(QIcon);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
106 PythonQtRegisterToolClassesTemplateConverter(QImage);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
107 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
108 PythonQtRegisterToolClassesTemplateConverter(QRegion);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
109 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
110 PythonQtRegisterToolClassesTemplateConverter(QCursor);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
111 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
112 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
113 PythonQtRegisterToolClassesTemplateConverter(QPen);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
114 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
115 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
116 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
117
117
118
118
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
119 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
120 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
121 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
122 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
123 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
124 for (unsigned int i = 0;i<16; i++) {
124 for (unsigned int i = 0;i<16; i++) {
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
125 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
126 if (obj) {
126 if (obj) {
127 PyModule_AddObject(pack, names[i], obj);
127 PyModule_AddObject(pack, names[i], obj);
128 Py_INCREF(obj);
128 Py_INCREF(obj);
129 PyModule_AddObject(pack2, names[i], obj);
129 PyModule_AddObject(pack2, names[i], obj);
130 } else {
130 } else {
131 std::cerr << "method not found " << names[i];
131 std::cerr << "method not found " << names[i];
132 }
132 }
133 }
133 }
134 }
134 }
135 }
135 }
136
136
137 void PythonQt::cleanup()
137 void PythonQt::cleanup()
138 {
138 {
139 if (_self) {
139 if (_self) {
140 delete _self;
140 delete _self;
141 _self = NULL;
141 _self = NULL;
142 }
142 }
143 }
143 }
144
144
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
145 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
146 {
146 {
147 _p = new PythonQtPrivate;
147 _p = new PythonQtPrivate;
148 _p->_initFlags = flags;
148 _p->_initFlags = flags;
149
149
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
150 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
151
151
152 if (flags & PythonAlreadyInitialized == 0) {
152 Py_SetProgramName("PythonQt");
153 Py_SetProgramName("PythonQt");
153 if (flags & IgnoreSiteModule) {
154 if (flags & IgnoreSiteModule) {
154 // this prevents the automatic importing of Python site files
155 // this prevents the automatic importing of Python site files
155 Py_NoSiteFlag = 1;
156 Py_NoSiteFlag = 1;
156 }
157 }
157 Py_Initialize();
158 Py_Initialize();
159 }
158
160
159 // add our own python object types for qt object slots
161 // add our own python object types for qt object slots
160 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
162 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
161 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
163 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
162 }
164 }
163 Py_INCREF(&PythonQtSlotFunction_Type);
165 Py_INCREF(&PythonQtSlotFunction_Type);
164
166
165 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
167 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
166 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
168 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
167 // add our own python object types for classes
169 // add our own python object types for classes
168 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
170 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
169 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
171 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 }
172 }
171 Py_INCREF(&PythonQtClassWrapper_Type);
173 Py_INCREF(&PythonQtClassWrapper_Type);
172
174
173 // add our own python object types for CPP instances
175 // add our own python object types for CPP instances
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
176 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
175 PythonQt::handleError();
177 PythonQt::handleError();
176 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 }
179 }
178 Py_INCREF(&PythonQtInstanceWrapper_Type);
180 Py_INCREF(&PythonQtInstanceWrapper_Type);
179
181
180 // add our own python object types for redirection of stdout
182 // add our own python object types for redirection of stdout
181 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
183 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
182 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
183 }
185 }
184 Py_INCREF(&PythonQtStdOutRedirectType);
186 Py_INCREF(&PythonQtStdOutRedirectType);
185
187
186 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
188 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
187
189
188 _p->setupSharedLibrarySuffixes();
190 _p->setupSharedLibrarySuffixes();
189
191
190 }
192 }
191
193
192 PythonQt::~PythonQt() {
194 PythonQt::~PythonQt() {
193 delete _p;
195 delete _p;
194 _p = NULL;
196 _p = NULL;
195 }
197 }
196
198
197 PythonQtPrivate::~PythonQtPrivate() {
199 PythonQtPrivate::~PythonQtPrivate() {
198 delete _defaultImporter;
200 delete _defaultImporter;
199 _defaultImporter = NULL;
201 _defaultImporter = NULL;
200
202
201 {
203 {
202 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
204 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
203 while (i.hasNext()) {
205 while (i.hasNext()) {
204 delete i.next().value();
206 delete i.next().value();
205 }
207 }
206 }
208 }
207 PythonQtConv::global_valueStorage.clear();
209 PythonQtConv::global_valueStorage.clear();
208 PythonQtConv::global_ptrStorage.clear();
210 PythonQtConv::global_ptrStorage.clear();
209 PythonQtConv::global_variantStorage.clear();
211 PythonQtConv::global_variantStorage.clear();
210
212
211 PythonQtMethodInfo::cleanupCachedMethodInfos();
213 PythonQtMethodInfo::cleanupCachedMethodInfos();
212 }
214 }
213
215
214 PythonQtImportFileInterface* PythonQt::importInterface()
216 PythonQtImportFileInterface* PythonQt::importInterface()
215 {
217 {
216 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
218 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
217 }
219 }
218
220
219 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
221 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
220 {
222 {
221 if (_self->_p->_noLongerWrappedCB) {
223 if (_self->_p->_noLongerWrappedCB) {
222 (*_self->_p->_noLongerWrappedCB)(o);
224 (*_self->_p->_noLongerWrappedCB)(o);
223 };
225 };
224 }
226 }
225
227
226 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
228 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
227 {
229 {
228 _p->registerClass(metaobject, package, wrapperCreator, shell);
230 _p->registerClass(metaobject, package, wrapperCreator, shell);
229 }
231 }
230
232
231 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
233 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
232 {
234 {
233 // we register all classes in the hierarchy
235 // we register all classes in the hierarchy
234 const QMetaObject* m = metaobject;
236 const QMetaObject* m = metaobject;
235 bool first = true;
237 bool first = true;
236 while (m) {
238 while (m) {
237 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
239 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
238 if (!info->pythonQtClassWrapper()) {
240 if (!info->pythonQtClassWrapper()) {
239 info->setTypeSlots(typeSlots);
241 info->setTypeSlots(typeSlots);
240 info->setupQObject(m);
242 info->setupQObject(m);
241 createPythonQtClassWrapper(info, package, module);
243 createPythonQtClassWrapper(info, package, module);
242 if (m->superClass()) {
244 if (m->superClass()) {
243 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
245 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
244 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
246 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
245 }
247 }
246 }
248 }
247 if (first) {
249 if (first) {
248 first = false;
250 first = false;
249 if (wrapperCreator) {
251 if (wrapperCreator) {
250 info->setDecoratorProvider(wrapperCreator);
252 info->setDecoratorProvider(wrapperCreator);
251 }
253 }
252 if (shell) {
254 if (shell) {
253 info->setShellSetInstanceWrapperCB(shell);
255 info->setShellSetInstanceWrapperCB(shell);
254 }
256 }
255 }
257 }
256 m = m->superClass();
258 m = m->superClass();
257 }
259 }
258 }
260 }
259
261
260 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
262 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
261 {
263 {
262 PyObject* pack = module?module:packageByName(package);
264 PyObject* pack = module?module:packageByName(package);
263 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
265 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
264 PyModule_AddObject(pack, info->className(), pyobj);
266 PyModule_AddObject(pack, info->className(), pyobj);
265 if (!module && package && strncmp(package,"Qt",2)==0) {
267 if (!module && package && strncmp(package,"Qt",2)==0) {
266 // since PyModule_AddObject steals the reference, we need a incref once more...
268 // since PyModule_AddObject steals the reference, we need a incref once more...
267 Py_INCREF(pyobj);
269 Py_INCREF(pyobj);
268 // put all qt objects into Qt as well
270 // put all qt objects into Qt as well
269 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
271 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
270 }
272 }
271 info->setPythonQtClassWrapper(pyobj);
273 info->setPythonQtClassWrapper(pyobj);
272 }
274 }
273
275
274 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
276 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
275 {
277 {
276 if (!obj) {
278 if (!obj) {
277 Py_INCREF(Py_None);
279 Py_INCREF(Py_None);
278 return Py_None;
280 return Py_None;
279 }
281 }
280 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
282 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
281 if (!wrap) {
283 if (!wrap) {
282 // smuggling it in...
284 // smuggling it in...
283 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
285 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
284 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
286 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
285 registerClass(obj->metaObject());
287 registerClass(obj->metaObject());
286 classInfo = _knownClassInfos.value(obj->metaObject()->className());
288 classInfo = _knownClassInfos.value(obj->metaObject()->className());
287 }
289 }
288 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
290 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
289 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
291 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
290 } else {
292 } else {
291 Py_INCREF(wrap);
293 Py_INCREF(wrap);
292 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
294 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
293 }
295 }
294 return (PyObject*)wrap;
296 return (PyObject*)wrap;
295 }
297 }
296
298
297 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
299 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
298 {
300 {
299 if (!ptr) {
301 if (!ptr) {
300 Py_INCREF(Py_None);
302 Py_INCREF(Py_None);
301 return Py_None;
303 return Py_None;
302 }
304 }
303
305
304 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
306 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
305 if (!wrap) {
307 if (!wrap) {
306 PythonQtClassInfo* info = _knownClassInfos.value(name);
308 PythonQtClassInfo* info = _knownClassInfos.value(name);
307 if (!info) {
309 if (!info) {
308 // maybe it is a PyObject, which we can return directly
310 // maybe it is a PyObject, which we can return directly
309 if (name == "PyObject") {
311 if (name == "PyObject") {
310 PyObject* p = (PyObject*)ptr;
312 PyObject* p = (PyObject*)ptr;
311 Py_INCREF(p);
313 Py_INCREF(p);
312 return p;
314 return p;
313 }
315 }
314
316
315 // we do not know the metaobject yet, but we might know it by it's name:
317 // we do not know the metaobject yet, but we might know it by it's name:
316 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
318 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
317 // yes, we know it, so we can convert to QObject
319 // yes, we know it, so we can convert to QObject
318 QObject* qptr = (QObject*)ptr;
320 QObject* qptr = (QObject*)ptr;
319 registerClass(qptr->metaObject());
321 registerClass(qptr->metaObject());
320 info = _knownClassInfos.value(qptr->metaObject()->className());
322 info = _knownClassInfos.value(qptr->metaObject()->className());
321 }
323 }
322 }
324 }
323 if (info && info->isQObject()) {
325 if (info && info->isQObject()) {
324 QObject* qptr = (QObject*)ptr;
326 QObject* qptr = (QObject*)ptr;
325 // if the object is a derived object, we want to switch the class info to the one of the derived class:
327 // if the object is a derived object, we want to switch the class info to the one of the derived class:
326 if (name!=(qptr->metaObject()->className())) {
328 if (name!=(qptr->metaObject()->className())) {
327 registerClass(qptr->metaObject());
329 registerClass(qptr->metaObject());
328 info = _knownClassInfos.value(qptr->metaObject()->className());
330 info = _knownClassInfos.value(qptr->metaObject()->className());
329 }
331 }
330 wrap = createNewPythonQtInstanceWrapper(qptr, info);
332 wrap = createNewPythonQtInstanceWrapper(qptr, info);
331 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
333 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
332 return (PyObject*)wrap;
334 return (PyObject*)wrap;
333 }
335 }
334
336
335 // not a known QObject, so try our wrapper factory:
337 // not a known QObject, so try our wrapper factory:
336 QObject* wrapper = NULL;
338 QObject* wrapper = NULL;
337 for (int i=0; i<_cppWrapperFactories.size(); i++) {
339 for (int i=0; i<_cppWrapperFactories.size(); i++) {
338 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
340 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
339 if (wrapper) {
341 if (wrapper) {
340 break;
342 break;
341 }
343 }
342 }
344 }
343
345
344 if (info) {
346 if (info) {
345 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
347 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
346 ptr = info->castDownIfPossible(ptr, &info);
348 ptr = info->castDownIfPossible(ptr, &info);
347 }
349 }
348
350
349 if (!info || info->pythonQtClassWrapper()==NULL) {
351 if (!info || info->pythonQtClassWrapper()==NULL) {
350 // still unknown, register as CPP class
352 // still unknown, register as CPP class
351 registerCPPClass(name.constData());
353 registerCPPClass(name.constData());
352 info = _knownClassInfos.value(name);
354 info = _knownClassInfos.value(name);
353 }
355 }
354 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
356 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
355 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
357 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
356 info->setMetaObject(wrapper->metaObject());
358 info->setMetaObject(wrapper->metaObject());
357 }
359 }
358 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
360 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
359 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
361 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
360 } else {
362 } else {
361 Py_INCREF(wrap);
363 Py_INCREF(wrap);
362 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
364 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
363 }
365 }
364 return (PyObject*)wrap;
366 return (PyObject*)wrap;
365 }
367 }
366
368
367 PyObject* PythonQtPrivate::dummyTuple() {
369 PyObject* PythonQtPrivate::dummyTuple() {
368 static PyObject* dummyTuple = NULL;
370 static PyObject* dummyTuple = NULL;
369 if (dummyTuple==NULL) {
371 if (dummyTuple==NULL) {
370 dummyTuple = PyTuple_New(1);
372 dummyTuple = PyTuple_New(1);
371 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
373 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
372 }
374 }
373 return dummyTuple;
375 return dummyTuple;
374 }
376 }
375
377
376
378
377 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
379 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
378 // call the associated class type to create a new instance...
380 // call the associated class type to create a new instance...
379 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
381 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
380
382
381 result->setQObject(obj);
383 result->setQObject(obj);
382 result->_wrappedPtr = wrappedPtr;
384 result->_wrappedPtr = wrappedPtr;
383 result->_ownedByPythonQt = false;
385 result->_ownedByPythonQt = false;
384 result->_useQMetaTypeDestroy = false;
386 result->_useQMetaTypeDestroy = false;
385
387
386 if (wrappedPtr) {
388 if (wrappedPtr) {
387 _wrappedObjects.insert(wrappedPtr, result);
389 _wrappedObjects.insert(wrappedPtr, result);
388 } else {
390 } else {
389 _wrappedObjects.insert(obj, result);
391 _wrappedObjects.insert(obj, result);
390 if (obj->parent()== NULL && _wrappedCB) {
392 if (obj->parent()== NULL && _wrappedCB) {
391 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
393 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
392 (*_wrappedCB)(obj);
394 (*_wrappedCB)(obj);
393 }
395 }
394 }
396 }
395 return result;
397 return result;
396 }
398 }
397
399
398 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
400 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
399 PythonQtClassWrapper* result;
401 PythonQtClassWrapper* result;
400
402
401 PyObject* className = PyString_FromString(info->className());
403 PyObject* className = PyString_FromString(info->className());
402
404
403 PyObject* baseClasses = PyTuple_New(1);
405 PyObject* baseClasses = PyTuple_New(1);
404 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
406 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
405
407
406 PyObject* typeDict = PyDict_New();
408 PyObject* typeDict = PyDict_New();
407 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
409 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
408 PyDict_SetItemString(typeDict, "__module__", moduleName);
410 PyDict_SetItemString(typeDict, "__module__", moduleName);
409
411
410 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
412 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
411
413
412 // set the class info so that PythonQtClassWrapper_new can read it
414 // set the class info so that PythonQtClassWrapper_new can read it
413 _currentClassInfoForClassWrapperCreation = info;
415 _currentClassInfoForClassWrapperCreation = info;
414 // create the new type object by calling the type
416 // create the new type object by calling the type
415 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
417 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
416
418
417 Py_DECREF(baseClasses);
419 Py_DECREF(baseClasses);
418 Py_DECREF(typeDict);
420 Py_DECREF(typeDict);
419 Py_DECREF(args);
421 Py_DECREF(args);
420 Py_DECREF(className);
422 Py_DECREF(className);
421
423
422 return result;
424 return result;
423 }
425 }
424
426
425 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
427 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
426 {
428 {
427 PyObject* args = Py_BuildValue("(i)", enumValue);
429 PyObject* args = Py_BuildValue("(i)", enumValue);
428 PyObject* result = PyObject_Call(enumType, args, NULL);
430 PyObject* result = PyObject_Call(enumType, args, NULL);
429 Py_DECREF(args);
431 Py_DECREF(args);
430 return result;
432 return result;
431 }
433 }
432
434
433 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
435 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
434 PyObject* result;
436 PyObject* result;
435
437
436 PyObject* className = PyString_FromString(enumName);
438 PyObject* className = PyString_FromString(enumName);
437
439
438 PyObject* baseClasses = PyTuple_New(1);
440 PyObject* baseClasses = PyTuple_New(1);
439 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
441 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
440
442
441 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
443 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
442 PyObject* typeDict = PyDict_New();
444 PyObject* typeDict = PyDict_New();
443 PyDict_SetItemString(typeDict, "__module__", module);
445 PyDict_SetItemString(typeDict, "__module__", module);
444
446
445 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
447 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
446
448
447 // create the new int derived type object by calling the core type
449 // create the new int derived type object by calling the core type
448 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
450 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
449
451
450 Py_DECREF(baseClasses);
452 Py_DECREF(baseClasses);
451 Py_DECREF(typeDict);
453 Py_DECREF(typeDict);
452 Py_DECREF(args);
454 Py_DECREF(args);
453 Py_DECREF(className);
455 Py_DECREF(className);
454
456
455 return result;
457 return result;
456 }
458 }
457
459
458 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
460 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
459 {
461 {
460 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
462 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
461 if (!r) {
463 if (!r) {
462 r = new PythonQtSignalReceiver(obj);
464 r = new PythonQtSignalReceiver(obj);
463 _p->_signalReceivers.insert(obj, r);
465 _p->_signalReceivers.insert(obj, r);
464 }
466 }
465 return r;
467 return r;
466 }
468 }
467
469
468 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
470 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
469 {
471 {
470 bool flag = false;
472 bool flag = false;
471 PythonQtObjectPtr callable = lookupCallable(module, objectname);
473 PythonQtObjectPtr callable = lookupCallable(module, objectname);
472 if (callable) {
474 if (callable) {
473 PythonQtSignalReceiver* r = getSignalReceiver(obj);
475 PythonQtSignalReceiver* r = getSignalReceiver(obj);
474 flag = r->addSignalHandler(signal, callable);
476 flag = r->addSignalHandler(signal, callable);
475 if (!flag) {
477 if (!flag) {
476 // signal not found
478 // signal not found
477 }
479 }
478 } else {
480 } else {
479 // callable not found
481 // callable not found
480 }
482 }
481 return flag;
483 return flag;
482 }
484 }
483
485
484 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
486 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
485 {
487 {
486 bool flag = false;
488 bool flag = false;
487 PythonQtSignalReceiver* r = getSignalReceiver(obj);
489 PythonQtSignalReceiver* r = getSignalReceiver(obj);
488 if (r) {
490 if (r) {
489 flag = r->addSignalHandler(signal, receiver);
491 flag = r->addSignalHandler(signal, receiver);
490 }
492 }
491 return flag;
493 return flag;
492 }
494 }
493
495
494 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
496 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
495 {
497 {
496 bool flag = false;
498 bool flag = false;
497 PythonQtObjectPtr callable = lookupCallable(module, objectname);
499 PythonQtObjectPtr callable = lookupCallable(module, objectname);
498 if (callable) {
500 if (callable) {
499 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
501 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
500 if (r) {
502 if (r) {
501 flag = r->removeSignalHandler(signal, callable);
503 flag = r->removeSignalHandler(signal, callable);
502 }
504 }
503 } else {
505 } else {
504 // callable not found
506 // callable not found
505 }
507 }
506 return flag;
508 return flag;
507 }
509 }
508
510
509 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
511 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
510 {
512 {
511 bool flag = false;
513 bool flag = false;
512 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
514 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
513 if (r) {
515 if (r) {
514 flag = r->removeSignalHandler(signal, receiver);
516 flag = r->removeSignalHandler(signal, receiver);
515 }
517 }
516 return flag;
518 return flag;
517 }
519 }
518
520
519 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
521 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
520 {
522 {
521 PythonQtObjectPtr p = lookupObject(module, name);
523 PythonQtObjectPtr p = lookupObject(module, name);
522 if (p) {
524 if (p) {
523 if (PyCallable_Check(p)) {
525 if (PyCallable_Check(p)) {
524 return p;
526 return p;
525 }
527 }
526 }
528 }
527 PyErr_Clear();
529 PyErr_Clear();
528 return NULL;
530 return NULL;
529 }
531 }
530
532
531 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
533 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
532 {
534 {
533 QStringList l = name.split('.');
535 QStringList l = name.split('.');
534 PythonQtObjectPtr p = module;
536 PythonQtObjectPtr p = module;
535 PythonQtObjectPtr prev;
537 PythonQtObjectPtr prev;
536 QString s;
538 QString s;
537 QByteArray b;
539 QByteArray b;
538 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
540 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
539 prev = p;
541 prev = p;
540 b = (*i).toLatin1();
542 b = (*i).toLatin1();
541 if (PyDict_Check(p)) {
543 if (PyDict_Check(p)) {
542 p = PyDict_GetItemString(p, b.data());
544 p = PyDict_GetItemString(p, b.data());
543 } else {
545 } else {
544 p.setNewRef(PyObject_GetAttrString(p, b.data()));
546 p.setNewRef(PyObject_GetAttrString(p, b.data()));
545 }
547 }
546 }
548 }
547 PyErr_Clear();
549 PyErr_Clear();
548 return p;
550 return p;
549 }
551 }
550
552
551 PythonQtObjectPtr PythonQt::getMainModule() {
553 PythonQtObjectPtr PythonQt::getMainModule() {
552 //both borrowed
554 //both borrowed
553 PythonQtObjectPtr dict = PyImport_GetModuleDict();
555 PythonQtObjectPtr dict = PyImport_GetModuleDict();
554 return PyDict_GetItemString(dict, "__main__");
556 return PyDict_GetItemString(dict, "__main__");
555 }
557 }
556
558
559 PythonQtObjectPtr PythonQt::importModule(const QString& name)
560 {
561 PythonQtObjectPtr mod;
562 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
563 return mod;
564 }
565
566
557 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
567 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
558 QVariant result;
568 QVariant result;
559 if (pycode) {
569 if (pycode) {
560 PyObject* dict = NULL;
570 PyObject* dict = NULL;
561 if (PyModule_Check(object)) {
571 if (PyModule_Check(object)) {
562 dict = PyModule_GetDict(object);
572 dict = PyModule_GetDict(object);
563 } else if (PyDict_Check(object)) {
573 } else if (PyDict_Check(object)) {
564 dict = object;
574 dict = object;
565 }
575 }
566 PyObject* r = NULL;
576 PyObject* r = NULL;
567 if (dict) {
577 if (dict) {
568 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
578 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
569 }
579 }
570 if (r) {
580 if (r) {
571 result = PythonQtConv::PyObjToQVariant(r);
581 result = PythonQtConv::PyObjToQVariant(r);
572 Py_DECREF(r);
582 Py_DECREF(r);
573 } else {
583 } else {
574 handleError();
584 handleError();
575 }
585 }
576 } else {
586 } else {
577 handleError();
587 handleError();
578 }
588 }
579 return result;
589 return result;
580 }
590 }
581
591
582 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
592 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
583 {
593 {
584 QVariant result;
594 QVariant result;
585 PythonQtObjectPtr p;
595 PythonQtObjectPtr p;
586 PyObject* dict = NULL;
596 PyObject* dict = NULL;
587 if (PyModule_Check(object)) {
597 if (PyModule_Check(object)) {
588 dict = PyModule_GetDict(object);
598 dict = PyModule_GetDict(object);
589 } else if (PyDict_Check(object)) {
599 } else if (PyDict_Check(object)) {
590 dict = object;
600 dict = object;
591 }
601 }
592 if (dict) {
602 if (dict) {
593 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
603 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
594 }
604 }
595 if (p) {
605 if (p) {
596 result = PythonQtConv::PyObjToQVariant(p);
606 result = PythonQtConv::PyObjToQVariant(p);
597 } else {
607 } else {
598 handleError();
608 handleError();
599 }
609 }
600 return result;
610 return result;
601 }
611 }
602
612
603 void PythonQt::evalFile(PyObject* module, const QString& filename)
613 void PythonQt::evalFile(PyObject* module, const QString& filename)
604 {
614 {
605 PythonQtObjectPtr code = parseFile(filename);
615 PythonQtObjectPtr code = parseFile(filename);
606 if (code) {
616 if (code) {
607 evalCode(module, code);
617 evalCode(module, code);
608 } else {
618 } else {
609 handleError();
619 handleError();
610 }
620 }
611 }
621 }
612
622
613 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
623 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
614 {
624 {
615 PythonQtObjectPtr p;
625 PythonQtObjectPtr p;
616 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
626 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
617 if (!p) {
627 if (!p) {
618 handleError();
628 handleError();
619 }
629 }
620 return p;
630 return p;
621 }
631 }
622
632
623 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
633 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
624 {
634 {
625 PythonQtObjectPtr code = parseFile(filename);
635 PythonQtObjectPtr code = parseFile(filename);
626 PythonQtObjectPtr module = _p->createModule(name, code);
636 PythonQtObjectPtr module = _p->createModule(name, code);
627 return module;
637 return module;
628 }
638 }
629
639
630 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
640 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
631 {
641 {
632 PyErr_Clear();
642 PyErr_Clear();
633 QString scriptCode = script;
643 QString scriptCode = script;
634 if (scriptCode.isEmpty()) {
644 if (scriptCode.isEmpty()) {
635 // we always need at least a linefeed
645 // we always need at least a linefeed
636 scriptCode = "\n";
646 scriptCode = "\n";
637 }
647 }
638 PythonQtObjectPtr pycode;
648 PythonQtObjectPtr pycode;
639 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
649 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
640 PythonQtObjectPtr module = _p->createModule(name, pycode);
650 PythonQtObjectPtr module = _p->createModule(name, pycode);
641 return module;
651 return module;
642 }
652 }
643
653
644 PythonQtObjectPtr PythonQt::createUniqueModule()
654 PythonQtObjectPtr PythonQt::createUniqueModule()
645 {
655 {
646 static QString pyQtStr("PythonQt_module");
656 static QString pyQtStr("PythonQt_module");
647 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
657 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
648 return createModuleFromScript(moduleName);
658 return createModuleFromScript(moduleName);
649 }
659 }
650
660
651 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
661 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
652 {
662 {
653 if (PyModule_Check(object)) {
663 if (PyModule_Check(object)) {
654 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
664 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 } else if (PyDict_Check(object)) {
665 } else if (PyDict_Check(object)) {
656 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
666 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 } else {
667 } else {
658 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
668 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
659 }
669 }
660 }
670 }
661
671
662 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
672 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
663 {
673 {
664 if (PyModule_Check(object)) {
674 if (PyModule_Check(object)) {
665 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
675 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 } else if (PyDict_Check(object)) {
676 } else if (PyDict_Check(object)) {
667 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
677 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 } else {
678 } else {
669 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
679 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
670 }
680 }
671 }
681 }
672
682
673 void PythonQt::removeVariable(PyObject* object, const QString& name)
683 void PythonQt::removeVariable(PyObject* object, const QString& name)
674 {
684 {
675 if (PyDict_Check(object)) {
685 if (PyDict_Check(object)) {
676 PyDict_DelItemString(object, name.toLatin1().data());
686 PyDict_DelItemString(object, name.toLatin1().data());
677 } else {
687 } else {
678 PyObject_DelAttrString(object, name.toLatin1().data());
688 PyObject_DelAttrString(object, name.toLatin1().data());
679 }
689 }
680 }
690 }
681
691
682 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
692 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
683 {
693 {
684 QVariant result;
694 QVariant result;
685 PythonQtObjectPtr obj = lookupObject(object, objectname);
695 PythonQtObjectPtr obj = lookupObject(object, objectname);
686 if (obj) {
696 if (obj) {
687 result = PythonQtConv::PyObjToQVariant(obj);
697 result = PythonQtConv::PyObjToQVariant(obj);
688 }
698 }
689 return result;
699 return result;
690 }
700 }
691
701
692 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
702 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
693 {
703 {
694 QStringList results;
704 QStringList results;
695
705
696 PythonQtObjectPtr object;
706 PythonQtObjectPtr object;
697 if (objectname.isEmpty()) {
707 if (objectname.isEmpty()) {
698 object = module;
708 object = module;
699 } else {
709 } else {
700 object = lookupObject(module, objectname);
710 object = lookupObject(module, objectname);
701 if (!object && type == CallOverloads) {
711 if (!object && type == CallOverloads) {
702 PyObject* dict = lookupObject(module, "__builtins__");
712 PyObject* dict = lookupObject(module, "__builtins__");
703 if (dict) {
713 if (dict) {
704 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
714 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
705 }
715 }
706 }
716 }
707 }
717 }
708
718
709 if (object) {
719 if (object) {
710 if (type == CallOverloads) {
720 if (type == CallOverloads) {
711 if (PythonQtSlotFunction_Check(object)) {
721 if (PythonQtSlotFunction_Check(object)) {
712 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
722 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
713 PythonQtSlotInfo* info = o->m_ml;
723 PythonQtSlotInfo* info = o->m_ml;
714
724
715 while (info) {
725 while (info) {
716 results << info->fullSignature();
726 results << info->fullSignature();
717 info = info->nextInfo();
727 info = info->nextInfo();
718 }
728 }
719 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
729 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
720 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
730 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
721 PythonQtSlotInfo* info = o->classInfo()->constructors();
731 PythonQtSlotInfo* info = o->classInfo()->constructors();
722
732
723 while (info) {
733 while (info) {
724 results << info->fullSignature();
734 results << info->fullSignature();
725 info = info->nextInfo();
735 info = info->nextInfo();
726 }
736 }
727 } else {
737 } else {
728 //TODO: use pydoc!
738 //TODO: use pydoc!
729 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
739 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
730 if (doc) {
740 if (doc) {
731 results << PyString_AsString(doc);
741 results << PyString_AsString(doc);
732 Py_DECREF(doc);
742 Py_DECREF(doc);
733 }
743 }
734 }
744 }
735 } else {
745 } else {
736 PyObject* keys = NULL;
746 PyObject* keys = NULL;
737 bool isDict = false;
747 bool isDict = false;
738 if (PyDict_Check(object)) {
748 if (PyDict_Check(object)) {
739 keys = PyDict_Keys(object);
749 keys = PyDict_Keys(object);
740 isDict = true;
750 isDict = true;
741 } else {
751 } else {
742 keys = PyObject_Dir(object);
752 keys = PyObject_Dir(object);
743 }
753 }
744 if (keys) {
754 if (keys) {
745 int count = PyList_Size(keys);
755 int count = PyList_Size(keys);
746 PyObject* key;
756 PyObject* key;
747 PyObject* value;
757 PyObject* value;
748 QString keystr;
758 QString keystr;
749 for (int i = 0;i<count;i++) {
759 for (int i = 0;i<count;i++) {
750 key = PyList_GetItem(keys,i);
760 key = PyList_GetItem(keys,i);
751 if (isDict) {
761 if (isDict) {
752 value = PyDict_GetItem(object, key);
762 value = PyDict_GetItem(object, key);
753 Py_INCREF(value);
763 Py_INCREF(value);
754 } else {
764 } else {
755 value = PyObject_GetAttr(object, key);
765 value = PyObject_GetAttr(object, key);
756 }
766 }
757 if (!value) continue;
767 if (!value) continue;
758 keystr = PyString_AsString(key);
768 keystr = PyString_AsString(key);
759 static const QString underscoreStr("__tmp");
769 static const QString underscoreStr("__tmp");
760 if (!keystr.startsWith(underscoreStr)) {
770 if (!keystr.startsWith(underscoreStr)) {
761 switch (type) {
771 switch (type) {
762 case Anything:
772 case Anything:
763 results << keystr;
773 results << keystr;
764 break;
774 break;
765 case Class:
775 case Class:
766 if (value->ob_type == &PyClass_Type) {
776 if (value->ob_type == &PyClass_Type) {
767 results << keystr;
777 results << keystr;
768 }
778 }
769 break;
779 break;
770 case Variable:
780 case Variable:
771 if (value->ob_type != &PyClass_Type
781 if (value->ob_type != &PyClass_Type
772 && value->ob_type != &PyCFunction_Type
782 && value->ob_type != &PyCFunction_Type
773 && value->ob_type != &PyFunction_Type
783 && value->ob_type != &PyFunction_Type
774 && value->ob_type != &PyModule_Type
784 && value->ob_type != &PyModule_Type
775 ) {
785 ) {
776 results << keystr;
786 results << keystr;
777 }
787 }
778 break;
788 break;
779 case Function:
789 case Function:
780 if (value->ob_type == &PyFunction_Type ||
790 if (value->ob_type == &PyFunction_Type ||
781 value->ob_type == &PyMethod_Type
791 value->ob_type == &PyMethod_Type
782 ) {
792 ) {
783 results << keystr;
793 results << keystr;
784 }
794 }
785 break;
795 break;
786 case Module:
796 case Module:
787 if (value->ob_type == &PyModule_Type) {
797 if (value->ob_type == &PyModule_Type) {
788 results << keystr;
798 results << keystr;
789 }
799 }
790 break;
800 break;
791 default:
801 default:
792 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
802 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
793 }
803 }
794 }
804 }
795 Py_DECREF(value);
805 Py_DECREF(value);
796 }
806 }
797 Py_DECREF(keys);
807 Py_DECREF(keys);
798 }
808 }
799 }
809 }
800 }
810 }
801 return results;
811 return results;
802 }
812 }
803
813
804 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
814 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
805 {
815 {
806 PythonQtObjectPtr callable = lookupCallable(object, name);
816 PythonQtObjectPtr callable = lookupCallable(object, name);
807 if (callable) {
817 if (callable) {
808 return call(callable, args);
818 return call(callable, args);
809 } else {
819 } else {
810 return QVariant();
820 return QVariant();
811 }
821 }
812 }
822 }
813
823
814 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
824 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
815 {
825 {
816 QVariant r;
826 QVariant r;
817 PythonQtObjectPtr result;
827 PythonQtObjectPtr result;
818 result.setNewRef(callAndReturnPyObject(callable, args));
828 result.setNewRef(callAndReturnPyObject(callable, args));
819 if (result) {
829 if (result) {
820 r = PythonQtConv::PyObjToQVariant(result);
830 r = PythonQtConv::PyObjToQVariant(result);
821 } else {
831 } else {
822 PythonQt::self()->handleError();
832 PythonQt::self()->handleError();
823 }
833 }
824 return r;
834 return r;
825 }
835 }
826
836
827 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
837 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
828 {
838 {
829 PyObject* result = NULL;
839 PyObject* result = NULL;
830 if (callable) {
840 if (callable) {
831 PythonQtObjectPtr pargs;
841 PythonQtObjectPtr pargs;
832 int count = args.size();
842 int count = args.size();
833 if (count>0) {
843 if (count>0) {
834 pargs.setNewRef(PyTuple_New(count));
844 pargs.setNewRef(PyTuple_New(count));
835 }
845 }
836 bool err = false;
846 bool err = false;
837 // transform QVariants to Python
847 // transform QVariants to Python
838 for (int i = 0; i < count; i++) {
848 for (int i = 0; i < count; i++) {
839 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
849 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
840 if (arg) {
850 if (arg) {
841 // steals reference, no unref
851 // steals reference, no unref
842 PyTuple_SetItem(pargs, i,arg);
852 PyTuple_SetItem(pargs, i,arg);
843 } else {
853 } else {
844 err = true;
854 err = true;
845 break;
855 break;
846 }
856 }
847 }
857 }
848
858
849 if (!err) {
859 if (!err) {
850 PyErr_Clear();
860 PyErr_Clear();
851 result = PyObject_CallObject(callable, pargs);
861 result = PyObject_CallObject(callable, pargs);
852 }
862 }
853 }
863 }
854 return result;
864 return result;
855 }
865 }
856
866
857 void PythonQt::addInstanceDecorators(QObject* o)
867 void PythonQt::addInstanceDecorators(QObject* o)
858 {
868 {
859 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
869 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
860 }
870 }
861
871
862 void PythonQt::addClassDecorators(QObject* o)
872 void PythonQt::addClassDecorators(QObject* o)
863 {
873 {
864 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
874 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
865 }
875 }
866
876
867 void PythonQt::addDecorators(QObject* o)
877 void PythonQt::addDecorators(QObject* o)
868 {
878 {
869 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
879 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
870 }
880 }
871
881
872 void PythonQt::registerQObjectClassNames(const QStringList& names)
882 void PythonQt::registerQObjectClassNames(const QStringList& names)
873 {
883 {
874 _p->registerQObjectClassNames(names);
884 _p->registerQObjectClassNames(names);
875 }
885 }
876
886
877 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
887 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
878 {
888 {
879 _p->_importInterface = importInterface;
889 _p->_importInterface = importInterface;
880 PythonQtImport::init();
890 PythonQtImport::init();
881 }
891 }
882
892
883 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
893 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
884 {
894 {
885 _p->_importIgnorePaths = paths;
895 _p->_importIgnorePaths = paths;
886 }
896 }
887
897
888 const QStringList& PythonQt::getImporterIgnorePaths()
898 const QStringList& PythonQt::getImporterIgnorePaths()
889 {
899 {
890 return _p->_importIgnorePaths;
900 return _p->_importIgnorePaths;
891 }
901 }
892
902
893 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
903 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
894 {
904 {
895 _p->_cppWrapperFactories.append(factory);
905 _p->_cppWrapperFactories.append(factory);
896 }
906 }
897
907
898 //---------------------------------------------------------------------------------------------------
908 //---------------------------------------------------------------------------------------------------
899 PythonQtPrivate::PythonQtPrivate()
909 PythonQtPrivate::PythonQtPrivate()
900 {
910 {
901 _importInterface = NULL;
911 _importInterface = NULL;
902 _defaultImporter = new PythonQtQFileImporter;
912 _defaultImporter = new PythonQtQFileImporter;
903 _noLongerWrappedCB = NULL;
913 _noLongerWrappedCB = NULL;
904 _wrappedCB = NULL;
914 _wrappedCB = NULL;
905 _currentClassInfoForClassWrapperCreation = NULL;
915 _currentClassInfoForClassWrapperCreation = NULL;
906 }
916 }
907
917
908 void PythonQtPrivate::setupSharedLibrarySuffixes()
918 void PythonQtPrivate::setupSharedLibrarySuffixes()
909 {
919 {
910 _sharedLibrarySuffixes.clear();
920 _sharedLibrarySuffixes.clear();
911 PythonQtObjectPtr imp;
921 PythonQtObjectPtr imp;
912 imp.setNewRef(PyImport_ImportModule("imp"));
922 imp.setNewRef(PyImport_ImportModule("imp"));
913 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
923 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
914 QVariant result = imp.call("get_suffixes");
924 QVariant result = imp.call("get_suffixes");
915 foreach (QVariant entry, result.toList()) {
925 foreach (QVariant entry, result.toList()) {
916 QVariantList suffixEntry = entry.toList();
926 QVariantList suffixEntry = entry.toList();
917 if (suffixEntry.count()==3) {
927 if (suffixEntry.count()==3) {
918 int code = suffixEntry.at(2).toInt();
928 int code = suffixEntry.at(2).toInt();
919 if (code == cExtensionCode) {
929 if (code == cExtensionCode) {
920 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
930 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
921 }
931 }
922 }
932 }
923 }
933 }
924 }
934 }
925
935
926 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
936 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
927 {
937 {
928 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
938 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
929 _currentClassInfoForClassWrapperCreation = NULL;
939 _currentClassInfoForClassWrapperCreation = NULL;
930 return info;
940 return info;
931 }
941 }
932
942
933 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
943 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
934 {
944 {
935 o->setParent(this);
945 o->setParent(this);
936 int numMethods = o->metaObject()->methodCount();
946 int numMethods = o->metaObject()->methodCount();
937 for (int i = 0; i < numMethods; i++) {
947 for (int i = 0; i < numMethods; i++) {
938 QMetaMethod m = o->metaObject()->method(i);
948 QMetaMethod m = o->metaObject()->method(i);
939 if ((m.methodType() == QMetaMethod::Method ||
949 if ((m.methodType() == QMetaMethod::Method ||
940 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
950 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
941 if (qstrncmp(m.signature(), "new_", 4)==0) {
951 if (qstrncmp(m.signature(), "new_", 4)==0) {
942 if ((decoTypes & ConstructorDecorator) == 0) continue;
952 if ((decoTypes & ConstructorDecorator) == 0) continue;
943 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
953 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
944 if (info->parameters().at(0).pointerCount == 1) {
954 if (info->parameters().at(0).pointerCount == 1) {
945 QByteArray signature = m.signature();
955 QByteArray signature = m.signature();
946 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
956 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
947 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
957 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
948 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
958 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
949 classInfo->addConstructor(newSlot);
959 classInfo->addConstructor(newSlot);
950 }
960 }
951 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
961 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
952 if ((decoTypes & DestructorDecorator) == 0) continue;
962 if ((decoTypes & DestructorDecorator) == 0) continue;
953 QByteArray signature = m.signature();
963 QByteArray signature = m.signature();
954 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
964 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
955 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
965 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
956 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
966 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
957 classInfo->setDestructor(newSlot);
967 classInfo->setDestructor(newSlot);
958 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
968 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
959 if ((decoTypes & StaticDecorator) == 0) continue;
969 if ((decoTypes & StaticDecorator) == 0) continue;
960 QByteArray signature = m.signature();
970 QByteArray signature = m.signature();
961 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
971 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
962 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
972 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
963 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
973 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
964 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
974 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
965 classInfo->addDecoratorSlot(newSlot);
975 classInfo->addDecoratorSlot(newSlot);
966 } else {
976 } else {
967 if ((decoTypes & InstanceDecorator) == 0) continue;
977 if ((decoTypes & InstanceDecorator) == 0) continue;
968 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
978 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
969 if (info->parameters().count()>1) {
979 if (info->parameters().count()>1) {
970 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
980 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
971 if (p.pointerCount==1) {
981 if (p.pointerCount==1) {
972 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
982 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
973 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
983 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
974 classInfo->addDecoratorSlot(newSlot);
984 classInfo->addDecoratorSlot(newSlot);
975 }
985 }
976 }
986 }
977 }
987 }
978 }
988 }
979 }
989 }
980 }
990 }
981
991
982 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
992 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
983 {
993 {
984 foreach(QString name, names) {
994 foreach(QString name, names) {
985 _knownQObjectClassNames.insert(name.toLatin1(), true);
995 _knownQObjectClassNames.insert(name.toLatin1(), true);
986 }
996 }
987 }
997 }
988
998
989 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
999 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
990 {
1000 {
991 _signalReceivers.remove(obj);
1001 _signalReceivers.remove(obj);
992 }
1002 }
993
1003
994 bool PythonQt::handleError()
1004 bool PythonQt::handleError()
995 {
1005 {
996 bool flag = false;
1006 bool flag = false;
997 if (PyErr_Occurred()) {
1007 if (PyErr_Occurred()) {
998
1008
999 // currently we just print the error and the stderr handler parses the errors
1009 // currently we just print the error and the stderr handler parses the errors
1000 PyErr_Print();
1010 PyErr_Print();
1001
1011
1002 /*
1012 /*
1003 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1013 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1004 PyObject *ptype;
1014 PyObject *ptype;
1005 PyObject *pvalue;
1015 PyObject *pvalue;
1006 PyObject *ptraceback;
1016 PyObject *ptraceback;
1007 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1017 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1008
1018
1009 Py_XDECREF(ptype);
1019 Py_XDECREF(ptype);
1010 Py_XDECREF(pvalue);
1020 Py_XDECREF(pvalue);
1011 Py_XDECREF(ptraceback);
1021 Py_XDECREF(ptraceback);
1012 */
1022 */
1013 PyErr_Clear();
1023 PyErr_Clear();
1014 flag = true;
1024 flag = true;
1015 }
1025 }
1016 return flag;
1026 return flag;
1017 }
1027 }
1018
1028
1019 void PythonQt::addSysPath(const QString& path)
1029 void PythonQt::addSysPath(const QString& path)
1020 {
1030 {
1021 PythonQtObjectPtr sys;
1031 PythonQtObjectPtr sys;
1022 sys.setNewRef(PyImport_ImportModule("sys"));
1032 sys.setNewRef(PyImport_ImportModule("sys"));
1023 PythonQtObjectPtr obj = lookupObject(sys, "path");
1033 PythonQtObjectPtr obj = lookupObject(sys, "path");
1024 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1034 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1025 }
1035 }
1026
1036
1027 void PythonQt::overwriteSysPath(const QStringList& paths)
1037 void PythonQt::overwriteSysPath(const QStringList& paths)
1028 {
1038 {
1029 PythonQtObjectPtr sys;
1039 PythonQtObjectPtr sys;
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1040 sys.setNewRef(PyImport_ImportModule("sys"));
1031 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1041 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1032 }
1042 }
1033
1043
1034 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1044 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1035 {
1045 {
1036 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1046 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1037 }
1047 }
1038
1048
1039 void PythonQt::stdOutRedirectCB(const QString& str)
1049 void PythonQt::stdOutRedirectCB(const QString& str)
1040 {
1050 {
1041 emit PythonQt::self()->pythonStdOut(str);
1051 emit PythonQt::self()->pythonStdOut(str);
1042 }
1052 }
1043
1053
1044 void PythonQt::stdErrRedirectCB(const QString& str)
1054 void PythonQt::stdErrRedirectCB(const QString& str)
1045 {
1055 {
1046 emit PythonQt::self()->pythonStdErr(str);
1056 emit PythonQt::self()->pythonStdErr(str);
1047 }
1057 }
1048
1058
1049 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1059 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1050 {
1060 {
1051 _p->_wrappedCB = cb;
1061 _p->_wrappedCB = cb;
1052 }
1062 }
1053
1063
1054 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1064 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1055 {
1065 {
1056 _p->_noLongerWrappedCB = cb;
1066 _p->_noLongerWrappedCB = cb;
1057 }
1067 }
1058
1068
1059
1069
1060
1070
1061 static PyMethodDef PythonQtMethods[] = {
1071 static PyMethodDef PythonQtMethods[] = {
1062 {NULL, NULL, 0, NULL}
1072 {NULL, NULL, 0, NULL}
1063 };
1073 };
1064
1074
1065 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1075 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1066 {
1076 {
1067 QByteArray name = "PythonQt";
1077 QByteArray name = "PythonQt";
1068 if (!pythonQtModuleName.isEmpty()) {
1078 if (!pythonQtModuleName.isEmpty()) {
1069 name = pythonQtModuleName;
1079 name = pythonQtModuleName;
1070 }
1080 }
1071 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1081 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1072 _p->_pythonQtModuleName = name;
1082 _p->_pythonQtModuleName = name;
1073
1083
1074 if (redirectStdOut) {
1084 if (redirectStdOut) {
1075 PythonQtObjectPtr sys;
1085 PythonQtObjectPtr sys;
1076 PythonQtObjectPtr out;
1086 PythonQtObjectPtr out;
1077 PythonQtObjectPtr err;
1087 PythonQtObjectPtr err;
1078 sys.setNewRef(PyImport_ImportModule("sys"));
1088 sys.setNewRef(PyImport_ImportModule("sys"));
1079 // create a redirection object for stdout and stderr
1089 // create a redirection object for stdout and stderr
1080 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1090 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1081 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1091 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1082 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1092 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1083 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1093 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1084 // replace the built in file objects with our own objects
1094 // replace the built in file objects with our own objects
1085 PyModule_AddObject(sys, "stdout", out);
1095 PyModule_AddObject(sys, "stdout", out);
1086 PyModule_AddObject(sys, "stderr", err);
1096 PyModule_AddObject(sys, "stderr", err);
1087 }
1097 }
1088 }
1098 }
1089
1099
1090 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1100 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1091 {
1101 {
1092 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1102 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1093 }
1103 }
1094
1104
1095
1105
1096 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1106 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1097 {
1107 {
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1108 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1099 if (!info) {
1109 if (!info) {
1100 info = new PythonQtClassInfo();
1110 info = new PythonQtClassInfo();
1101 info->setupCPPObject(typeName);
1111 info->setupCPPObject(typeName);
1102 _knownClassInfos.insert(typeName, info);
1112 _knownClassInfos.insert(typeName, info);
1103 }
1113 }
1104 return info;
1114 return info;
1105 }
1115 }
1106
1116
1107 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1117 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1108 {
1118 {
1109 _p->addPolymorphicHandler(typeName, cb);
1119 _p->addPolymorphicHandler(typeName, cb);
1110 }
1120 }
1111
1121
1112 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1122 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1113 {
1123 {
1114 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1124 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1115 info->addPolymorphicHandler(cb);
1125 info->addPolymorphicHandler(cb);
1116 }
1126 }
1117
1127
1118 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1128 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1119 {
1129 {
1120 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1130 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1121 }
1131 }
1122
1132
1123 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1133 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1124 {
1134 {
1125 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1135 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1126 if (info) {
1136 if (info) {
1127 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1137 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1128 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1138 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1129 return true;
1139 return true;
1130 } else {
1140 } else {
1131 return false;
1141 return false;
1132 }
1142 }
1133 }
1143 }
1134
1144
1135 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1145 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1136 {
1146 {
1137 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1147 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1138 if (!info->pythonQtClassWrapper()) {
1148 if (!info->pythonQtClassWrapper()) {
1139 info->setTypeSlots(typeSlots);
1149 info->setTypeSlots(typeSlots);
1140 info->setupCPPObject(typeName);
1150 info->setupCPPObject(typeName);
1141 createPythonQtClassWrapper(info, package, module);
1151 createPythonQtClassWrapper(info, package, module);
1142 }
1152 }
1143 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1153 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1144 addParentClass(typeName, parentTypeName, 0);
1154 addParentClass(typeName, parentTypeName, 0);
1145 }
1155 }
1146 if (wrapperCreator) {
1156 if (wrapperCreator) {
1147 info->setDecoratorProvider(wrapperCreator);
1157 info->setDecoratorProvider(wrapperCreator);
1148 }
1158 }
1149 if (shell) {
1159 if (shell) {
1150 info->setShellSetInstanceWrapperCB(shell);
1160 info->setShellSetInstanceWrapperCB(shell);
1151 }
1161 }
1152 }
1162 }
1153
1163
1154 PyObject* PythonQtPrivate::packageByName(const char* name)
1164 PyObject* PythonQtPrivate::packageByName(const char* name)
1155 {
1165 {
1156 if (name==NULL || name[0]==0) {
1166 if (name==NULL || name[0]==0) {
1157 name = "private";
1167 name = "private";
1158 }
1168 }
1159 PyObject* v = _packages.value(name);
1169 PyObject* v = _packages.value(name);
1160 if (!v) {
1170 if (!v) {
1161 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1171 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1162 _packages.insert(name, v);
1172 _packages.insert(name, v);
1163 // AddObject steals the reference, so increment it!
1173 // AddObject steals the reference, so increment it!
1164 Py_INCREF(v);
1174 Py_INCREF(v);
1165 PyModule_AddObject(_pythonQtModule, name, v);
1175 PyModule_AddObject(_pythonQtModule, name, v);
1166 }
1176 }
1167 return v;
1177 return v;
1168 }
1178 }
1169
1179
1170 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1180 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1171 {
1181 {
1172 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;
1182 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;
1173 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1183 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1174 PythonQt::self()->handleError();
1184 PythonQt::self()->handleError();
1175 }
1185 }
1176
1186
1177 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1187 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1178 {
1188 {
1179 if (_p->_initFlags & ExternalHelp) {
1189 if (_p->_initFlags & ExternalHelp) {
1180 emit pythonHelpRequest(QByteArray(info->className()));
1190 emit pythonHelpRequest(QByteArray(info->className()));
1181 return Py_BuildValue("");
1191 return Py_BuildValue("");
1182 } else {
1192 } else {
1183 return PyString_FromString(info->help().toLatin1().data());
1193 return PyString_FromString(info->help().toLatin1().data());
1184 }
1194 }
1185 }
1195 }
1186
1196
1187 void PythonQtPrivate::removeWrapperPointer(void* obj)
1197 void PythonQtPrivate::removeWrapperPointer(void* obj)
1188 {
1198 {
1189 _wrappedObjects.remove(obj);
1199 _wrappedObjects.remove(obj);
1190 }
1200 }
1191
1201
1192 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1202 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1193 {
1203 {
1194 _wrappedObjects.insert(obj, wrapper);
1204 _wrappedObjects.insert(obj, wrapper);
1195 }
1205 }
1196
1206
1197 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1207 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1198 {
1208 {
1199 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1209 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1200 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1210 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1201 // this is a wrapper whose QObject was already removed due to destruction
1211 // this is a wrapper whose QObject was already removed due to destruction
1202 // so the obj pointer has to be a new QObject with the same address...
1212 // so the obj pointer has to be a new QObject with the same address...
1203 // we remove the old one and set the copy to NULL
1213 // we remove the old one and set the copy to NULL
1204 wrap->_objPointerCopy = NULL;
1214 wrap->_objPointerCopy = NULL;
1205 removeWrapperPointer(obj);
1215 removeWrapperPointer(obj);
1206 wrap = NULL;
1216 wrap = NULL;
1207 }
1217 }
1208 return wrap;
1218 return wrap;
1209 }
1219 }
1210
1220
1211 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1221 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1212 {
1222 {
1213 PythonQtObjectPtr result;
1223 PythonQtObjectPtr result;
1214 if (pycode) {
1224 if (pycode) {
1215 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1225 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1216 } else {
1226 } else {
1217 PythonQt::self()->handleError();
1227 PythonQt::self()->handleError();
1218 }
1228 }
1219 return result;
1229 return result;
1220 }
1230 }
@@ -1,579 +1,634
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 <QObject>
50 #include <QObject>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QList>
52 #include <QList>
53 #include <QHash>
53 #include <QHash>
54 #include <QByteArray>
54 #include <QByteArray>
55 #include <QStringList>
55 #include <QStringList>
56 #include <QtDebug>
56 #include <QtDebug>
57 #include <iostream>
57 #include <iostream>
58
58
59
59
60 class PythonQtClassInfo;
60 class PythonQtClassInfo;
61 class PythonQtPrivate;
61 class PythonQtPrivate;
62 class PythonQtMethodInfo;
62 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
67
67
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
71
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
73
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75
75
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
79 }
79 }
80
80
81 //! callback to create a QObject lazily
81 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
83
84 //! helper template to create a derived QObject class
84 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
86
87 //! the main interface to the Python Qt binding, realized as a singleton
87 //! The main interface to the Python Qt binding, realized as a singleton
88 /*!
89 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
90 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
91 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
92 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
93 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
94 code in the scope of a dict.
95 */
88 class PYTHONQT_EXPORT PythonQt : public QObject {
96 class PYTHONQT_EXPORT PythonQt : public QObject {
89
97
90 Q_OBJECT
98 Q_OBJECT
91
99
92 public:
100 public:
101
102 //! flags that can be passed to PythonQt::init()
93 enum InitFlags {
103 enum InitFlags {
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
104 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
105 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
106 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
107 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
97 };
108 };
98
109
99 //! flags that tell PythonQt which operators to expect on the registered type
110 //! flags that tell PythonQt which operators to expect on the registered type
100 enum TypeSlots {
111 enum TypeSlots {
101 Type_Add = 1,
112 Type_Add = 1,
102 Type_Subtract = 1 << 1,
113 Type_Subtract = 1 << 1,
103 Type_Multiply = 1 << 2,
114 Type_Multiply = 1 << 2,
104 Type_Divide = 1 << 3,
115 Type_Divide = 1 << 3,
105 Type_Mod = 1 << 4,
116 Type_Mod = 1 << 4,
106 Type_And = 1 << 5,
117 Type_And = 1 << 5,
107 Type_Or = 1 << 6,
118 Type_Or = 1 << 6,
108 Type_Xor = 1 << 7,
119 Type_Xor = 1 << 7,
109 Type_LShift = 1 << 8,
120 Type_LShift = 1 << 8,
110 Type_RShift = 1 << 9,
121 Type_RShift = 1 << 9,
111
122
112 Type_InplaceAdd = 1 << 10,
123 Type_InplaceAdd = 1 << 10,
113 Type_InplaceSubtract = 1 << 11,
124 Type_InplaceSubtract = 1 << 11,
114 Type_InplaceMultiply = 1 << 12,
125 Type_InplaceMultiply = 1 << 12,
115 Type_InplaceDivide = 1 << 13,
126 Type_InplaceDivide = 1 << 13,
116 Type_InplaceMod = 1 << 14,
127 Type_InplaceMod = 1 << 14,
117 Type_InplaceAnd = 1 << 15,
128 Type_InplaceAnd = 1 << 15,
118 Type_InplaceOr = 1 << 16,
129 Type_InplaceOr = 1 << 16,
119 Type_InplaceXor = 1 << 17,
130 Type_InplaceXor = 1 << 17,
120 Type_InplaceLShift = 1 << 18,
131 Type_InplaceLShift = 1 << 18,
121 Type_InplaceRShift = 1 << 19,
132 Type_InplaceRShift = 1 << 19,
122
133
123 // Not yet needed/nicely mappable/generated...
134 // Not yet needed/nicely mappable/generated...
124 //Type_Positive = 1 << 29,
135 //Type_Positive = 1 << 29,
125 //Type_Negative = 1 << 29,
136 //Type_Negative = 1 << 29,
126 //Type_Abs = 1 << 29,
137 //Type_Abs = 1 << 29,
127 //Type_Hash = 1 << 29,
138 //Type_Hash = 1 << 29,
128
139
129 Type_Invert = 1 << 29,
140 Type_Invert = 1 << 29,
130 Type_RichCompare = 1 << 30,
141 Type_RichCompare = 1 << 30,
131 Type_NonZero = 1 << 31,
142 Type_NonZero = 1 << 31,
132
143
133 };
144 };
134
145
135 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
146 //---------------------------------------------------------------------------
147 //! \name Singleton Initialization
148 //@{
149
150 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
136 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
151 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
137 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
152 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
138 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
153 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
139
154
140 //! cleanup
155 //! cleanup of the singleton
141 static void cleanup();
156 static void cleanup();
142
157
143 //! get the singleton instance
158 //! get the singleton instance
144 static PythonQt* self() { return _self; }
159 static PythonQt* self() { return _self; }
145
160
146 //-----------------------------------------------------------------------------
161 //@}
147 // Public API:
148
162
149 //! defines the object types for introspection
163 //! defines the object types for introspection
150 enum ObjectType {
164 enum ObjectType {
151 Class,
165 Class,
152 Function,
166 Function,
153 Variable,
167 Variable,
154 Module,
168 Module,
155 Anything,
169 Anything,
156 CallOverloads
170 CallOverloads
157 };
171 };
158
172
173 //---------------------------------------------------------------------------
174 //! \name Modules
175 //@{
176
177 //! get the __main__ module of python
178 PythonQtObjectPtr getMainModule();
179
180 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
181 //! If a module is already imported, this returns the already imported module.
182 PythonQtObjectPtr importModule(const QString& name);
183
184 //! creates the new module \c name and evaluates the given file in the context of that module
185 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
186 //! to a module later on.
187 //! The user needs to make sure that the \c name is unique in the python module dictionary.
188 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
189
190 //! creates the new module \c name and evaluates the given script in the context of that module.
191 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
192 //! to a module later on.
193 //! The user needs to make sure that the \c name is unique in the python module dictionary.
194 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
195
196 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
197 //! script code
198 PythonQtObjectPtr createUniqueModule();
199
200 //@}
201
202 //---------------------------------------------------------------------------
203 //! \name Importing/Paths
204 //@{
205
159 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
206 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
160 void overwriteSysPath(const QStringList& paths);
207 void overwriteSysPath(const QStringList& paths);
161
208
162 //! prepend a path to sys.path to allow importing from it
209 //! prepend a path to sys.path to allow importing from it
163 void addSysPath(const QString& path);
210 void addSysPath(const QString& path);
164
211
165 //! sets the __path__ list of a module to the given list (important for local imports)
212 //! sets the __path__ list of a module to the given list (important for local imports)
166 void setModuleImportPath(PyObject* module, const QStringList& paths);
213 void setModuleImportPath(PyObject* module, const QStringList& paths);
167
214
168 //! get the __main__ module of python
215 //@}
169 PythonQtObjectPtr getMainModule();
216
217 //---------------------------------------------------------------------------
218 //! \name Registering Classes
219 //@{
170
220
171 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
221 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
172 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
222 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
173 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
223 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
174 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
224 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
175
225
176 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
226 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
177 //! (ownership of wrapper is passed to PythonQt)
227 //! (ownership of wrapper is passed to PythonQt)
178 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
228 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
179
229
180 This will add a wrapper object that is used to make calls to the given classname \c typeName.
230 This will add a wrapper object that is used to make calls to the given classname \c typeName.
181 All slots that take a pointer to typeName as the first argument will be callable from Python on
231 All slots that take a pointer to typeName as the first argument will be callable from Python on
182 a variant object that contains such a type.
232 a variant object that contains such a type.
183 */
233 */
184 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
234 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
185
235
186 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
236 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
187 //! and it will register the classes when it first sees a pointer to such a derived class
237 //! and it will register the classes when it first sees a pointer to such a derived class
188 void registerQObjectClassNames(const QStringList& names);
238 void registerQObjectClassNames(const QStringList& names);
189
239
190 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
240 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
191 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
241 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
192 //! type is really derived from parentType.
242 //! type is really derived from parentType.
193 //! Returns false if the typeName was not yet registered.
243 //! Returns false if the typeName was not yet registered.
194 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
244 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
195
245
196 //! add a handler for polymorphic downcasting
246 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
247 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
198
248
249 //@}
250
251 //---------------------------------------------------------------------------
252 //! \name Script Parsing and Evaluation
253 //@{
254
199 //! parses the given file and returns the python code object, this can then be used to call evalCode()
255 //! parses the given file and returns the python code object, this can then be used to call evalCode()
200 PythonQtObjectPtr parseFile(const QString& filename);
256 PythonQtObjectPtr parseFile(const QString& filename);
201
257
202 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
258 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
203 //! If pycode is NULL, a python error is printed.
259 //! If pycode is NULL, a python error is printed.
204 QVariant evalCode(PyObject* object, PyObject* pycode);
260 QVariant evalCode(PyObject* object, PyObject* pycode);
205
261
206 //! evaluates the given script code and returns the result value
262 //! evaluates the given script code and returns the result value
207 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
263 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
208
264
209 //! evaluates the given script code from file
265 //! evaluates the given script code from file
210 void evalFile(PyObject* object, const QString& filename);
266 void evalFile(PyObject* object, const QString& filename);
211
267
212 //! creates the new module \c name and evaluates the given file in the context of that module
268 //@}
213 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
214 //! to a module later on.
215 //! The user needs to make sure that the \c name is unique in the python module dictionary.
216 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
217
218 //! creates the new module \c name and evaluates the given script in the context of that module.
219 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
220 //! to a module later on.
221 //! The user needs to make sure that the \c name is unique in the python module dictionary.
222 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
223
224 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
225 //! script code
226 PythonQtObjectPtr createUniqueModule();
227
269
228 //@{ Signal handlers
270 //---------------------------------------------------------------------------
271 //! \name Signal Handlers
272 //@{
229
273
230 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
274 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
231 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
275 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
232
276
233 //! remove a signal handler from the given \c signal of \c obj
277 //! remove a signal handler from the given \c signal of \c obj
234 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
278 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
235
279
236 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
280 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
237 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
281 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
238
282
239 //! remove a signal handler from the given \c signal of \c obj
283 //! remove a signal handler from the given \c signal of \c obj
240 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
284 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
241
285
242 //@}
286 //@}
243
287
244 //@{ Variable access
288 //---------------------------------------------------------------------------
289 //! \name Variable access
290 //@{
245
291
246 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
292 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
247 void addObject(PyObject* object, const QString& name, QObject* qObject);
293 void addObject(PyObject* object, const QString& name, QObject* qObject);
248
294
249 //! add the given variable to the object
295 //! add the given variable to the object
250 void addVariable(PyObject* object, const QString& name, const QVariant& v);
296 void addVariable(PyObject* object, const QString& name, const QVariant& v);
251
297
252 //! remove the given variable
298 //! remove the given variable
253 void removeVariable(PyObject* module, const QString& name);
299 void removeVariable(PyObject* module, const QString& name);
254
300
255 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
301 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
256 QVariant getVariable(PyObject* object, const QString& name);
302 QVariant getVariable(PyObject* object, const QString& name);
257
303
258 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
304 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
259 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
305 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
260
306
261 //! returns the found callable object or NULL
307 //! returns the found callable object or NULL
262 //! @return new reference
308 //! @return new reference
263 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
309 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
264
310
265 //@}
311 //@}
266
312
267 //@{ Calling of python callables
313 //---------------------------------------------------------------------------
314 //! \name Calling Python Objects
315 //@{
268
316
269 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
317 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
270 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
318 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
271
319
272 //! call the given python object, returns the result converted to a QVariant
320 //! call the given python object, returns the result converted to a QVariant
273 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
321 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
274
322
275 //! call the given python object, returns the result as new PyObject
323 //! call the given python object, returns the result as new PyObject
276 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
324 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
277
325
278 //@}
326 //@}
279
327
280 //@{ Decorations, constructors, wrappers...
328 //---------------------------------------------------------------------------
281
329 //! \name Decorations, Constructors, Wrappers...
330 //@{
282
331
283 //! add an object whose slots will be used as decorator slots for
332 //! add an object whose slots will be used as decorator slots for
284 //! other QObjects or CPP classes. The slots need to follow the
333 //! other QObjects or CPP classes. The slots need to follow the
285 //! convention that the first argument is a pointer to the wrapped object.
334 //! convention that the first argument is a pointer to the wrapped object.
286 //! (ownership is passed to PythonQt)
335 //! (ownership is passed to PythonQt)
287 /*!
336 /*!
288 Example:
337 Example:
289
338
290 A slot with the signature
339 A slot with the signature
291
340
292 \code
341 \code
293 bool doSomething(QWidget* w, int a)
342 bool doSomething(QWidget* w, int a)
294 \endcode
343 \endcode
295
344
296 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
345 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
297 that will be called with the concrete instance as first argument.
346 that will be called with the concrete instance as first argument.
298 So in Python you can now e.g. call
347 So in Python you can now e.g. call
299
348
300 \code
349 \code
301 someWidget.doSomething(12)
350 someWidget.doSomething(12)
302 \endcode
351 \endcode
303
352
304 without QWidget really having this method. This allows to easily make normal methods
353 without QWidget really having this method. This allows to easily make normal methods
305 of Qt classes callable by forwarding them with such decorator slots
354 of Qt classes callable by forwarding them with such decorator slots
306 or to make CPP classes (which are not derived from QObject) callable from Python.
355 or to make CPP classes (which are not derived from QObject) callable from Python.
307 */
356 */
308 void addInstanceDecorators(QObject* o);
357 void addInstanceDecorators(QObject* o);
309
358
310 //! add an object whose slots will be used as decorator slots for
359 //! add an object whose slots will be used as decorator slots for
311 //! class objects (ownership is passed to PythonQt)
360 //! class objects (ownership is passed to PythonQt)
312 /*!
361 /*!
313 The slots need to follow the following convention:
362 The slots need to follow the following convention:
314 - SomeClass* new_SomeClass(...)
363 - SomeClass* new_SomeClass(...)
315 - QVariant new_SomeClass(...)
364 - QVariant new_SomeClass(...)
316 - void delete_SomeClass(SomeClass*)
365 - void delete_SomeClass(SomeClass*)
317 - ... static_SomeClass_someName(...)
366 - ... static_SomeClass_someName(...)
318
367
319 This will add:
368 This will add:
320 - a constructor
369 - a constructor
321 - a constructor which generates a QVariant
370 - a constructor which generates a QVariant
322 - a destructor (only useful for CPP objects)
371 - a destructor (only useful for CPP objects)
323 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
372 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
324
373
325 */
374 */
326 void addClassDecorators(QObject* o);
375 void addClassDecorators(QObject* o);
327
376
328 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
377 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
329 void addDecorators(QObject* o);
378 void addDecorators(QObject* o);
330
379
331 //! add the given factory to PythonQt (ownership stays with caller)
380 //! add the given factory to PythonQt (ownership stays with caller)
332 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
381 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
333
382
334 //@}
383 //@}
335
384
336 //@{ Custom importer (to replace internal import implementation of python)
385 //---------------------------------------------------------------------------
386 //! \name Custom Importer
387 //@{
337
388
338 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
389 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
339 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
390 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
340 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
391 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
341 //! This is not reversible, so even setting setImporter(NULL) afterwards will
392 //! This is not reversible, so even setting setImporter(NULL) afterwards will
342 //! keep the custom PythonQt importer with a QFile default import interface.
393 //! keep the custom PythonQt importer with a QFile default import interface.
343 //! Subsequent python import calls will make use of the passed importInterface
394 //! Subsequent python import calls will make use of the passed importInterface
344 //! which forwards all import calls to the given \c importInterface.
395 //! which forwards all import calls to the given \c importInterface.
345 //! Passing NULL will install a default QFile importer.
396 //! Passing NULL will install a default QFile importer.
346 //! (\c importInterface ownership stays with caller)
397 //! (\c importInterface ownership stays with caller)
347 void setImporter(PythonQtImportFileInterface* importInterface);
398 void setImporter(PythonQtImportFileInterface* importInterface);
348
399
349 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
400 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
350 //! (without calling setImporter or installDefaultImporter at least once, the default python import
401 //! (without calling setImporter or installDefaultImporter at least once, the default python import
351 //! mechanism is in place)
402 //! mechanism is in place)
352 //! the default importer allows to import files from anywhere QFile can read from,
403 //! the default importer allows to import files from anywhere QFile can read from,
353 //! including the Qt resource system using ":". Keep in mind that you need to extend
404 //! including the Qt resource system using ":". Keep in mind that you need to extend
354 //! "sys.path" with ":" to be able to import from the Qt resources.
405 //! "sys.path" with ":" to be able to import from the Qt resources.
355 void installDefaultImporter() { setImporter(NULL); }
406 void installDefaultImporter() { setImporter(NULL); }
356
407
357 //! set paths that the importer should ignore
408 //! set paths that the importer should ignore
358 void setImporterIgnorePaths(const QStringList& paths);
409 void setImporterIgnorePaths(const QStringList& paths);
359
410
360 //! get paths that the importer should ignore
411 //! get paths that the importer should ignore
361 const QStringList& getImporterIgnorePaths();
412 const QStringList& getImporterIgnorePaths();
362
413
414 //! get access to the file importer (if set)
415 static PythonQtImportFileInterface* importInterface();
416
363 //@}
417 //@}
364
418
419 //---------------------------------------------------------------------------
420 //! \name Other Stuff
421 //@{
422
365 //! get access to internal data (should not be used on the public API, but is used by some C functions)
423 //! get access to internal data (should not be used on the public API, but is used by some C functions)
366 static PythonQtPrivate* priv() { return _self->_p; }
424 static PythonQtPrivate* priv() { return _self->_p; }
367
425
368 //! get access to the file importer (if set)
369 static PythonQtImportFileInterface* importInterface();
370
371 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
426 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
372 //! The error is currently just output to the python stderr, future version might implement better trace printing
427 //! The error is currently just output to the python stderr, future version might implement better trace printing
373 bool handleError();
428 bool handleError();
374
429
375 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
430 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
376 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
431 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
377 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
432 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
378 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
433 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
379
434
380 //! call the callback if it is set
435 //! call the callback if it is set
381 static void qObjectNoLongerWrappedCB(QObject* o);
436 static void qObjectNoLongerWrappedCB(QObject* o);
382
437
438 //! called by internal help methods
439 PyObject* helpCalled(PythonQtClassInfo* info);
440
441 //! returns the found object or NULL
442 //! @return new reference
443 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
444
445 //@}
446
383 signals:
447 signals:
384 //! emitted when python outputs something to stdout (and redirection is turned on)
448 //! emitted when python outputs something to stdout (and redirection is turned on)
385 void pythonStdOut(const QString& str);
449 void pythonStdOut(const QString& str);
386 //! emitted when python outputs something to stderr (and redirection is turned on)
450 //! emitted when python outputs something to stderr (and redirection is turned on)
387 void pythonStdErr(const QString& str);
451 void pythonStdErr(const QString& str);
388
452
389 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
453 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
390 void pythonHelpRequest(const QByteArray& cppClassName);
454 void pythonHelpRequest(const QByteArray& cppClassName);
391
455
392
393 public:
394 //! called by internal help methods
395 PyObject* helpCalled(PythonQtClassInfo* info);
396
397 //! returns the found object or NULL
398 //! @return new reference
399 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
400
401 private:
456 private:
402 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
457 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
403
458
404 //! callback for stdout redirection, emits pythonStdOut signal
459 //! callback for stdout redirection, emits pythonStdOut signal
405 static void stdOutRedirectCB(const QString& str);
460 static void stdOutRedirectCB(const QString& str);
406 //! callback for stderr redirection, emits pythonStdErr signal
461 //! callback for stderr redirection, emits pythonStdErr signal
407 static void stdErrRedirectCB(const QString& str);
462 static void stdErrRedirectCB(const QString& str);
408
463
409 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
464 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
410 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
465 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
411
466
412 PythonQt(int flags, const QByteArray& pythonQtModuleName);
467 PythonQt(int flags, const QByteArray& pythonQtModuleName);
413 ~PythonQt();
468 ~PythonQt();
414
469
415 static PythonQt* _self;
470 static PythonQt* _self;
416 static int _uniqueModuleCount;
471 static int _uniqueModuleCount;
417
472
418 PythonQtPrivate* _p;
473 PythonQtPrivate* _p;
419
474
420 };
475 };
421
476
422 //! internal PythonQt details
477 //! internal PythonQt details
423 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
478 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
424
479
425 Q_OBJECT
480 Q_OBJECT
426
481
427 public:
482 public:
428 PythonQtPrivate();
483 PythonQtPrivate();
429 ~PythonQtPrivate();
484 ~PythonQtPrivate();
430
485
431 enum DecoratorTypes {
486 enum DecoratorTypes {
432 StaticDecorator = 1,
487 StaticDecorator = 1,
433 ConstructorDecorator = 2,
488 ConstructorDecorator = 2,
434 DestructorDecorator = 4,
489 DestructorDecorator = 4,
435 InstanceDecorator = 8,
490 InstanceDecorator = 8,
436 AllDecorators = 0xffff
491 AllDecorators = 0xffff
437 };
492 };
438
493
439 //! get the suffixes that are used for shared libraries
494 //! get the suffixes that are used for shared libraries
440 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
495 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
441
496
442 //! returns if the id is the id for PythonQtObjectPtr
497 //! returns if the id is the id for PythonQtObjectPtr
443 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
498 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
444
499
445 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
500 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
446 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
501 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
447 //! remove the wrapper ptr again
502 //! remove the wrapper ptr again
448 void removeWrapperPointer(void* obj);
503 void removeWrapperPointer(void* obj);
449
504
450 //! add parent class relation
505 //! add parent class relation
451 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
506 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
452
507
453 //! add a handler for polymorphic downcasting
508 //! add a handler for polymorphic downcasting
454 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
509 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
455
510
456 //! lookup existing classinfo and return new if not yet present
511 //! lookup existing classinfo and return new if not yet present
457 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
512 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
458
513
459 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
514 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
460 void removeSignalEmitter(QObject* obj);
515 void removeSignalEmitter(QObject* obj);
461
516
462 //! wrap the given QObject into a Python object (or return existing wrapper!)
517 //! wrap the given QObject into a Python object (or return existing wrapper!)
463 PyObject* wrapQObject(QObject* obj);
518 PyObject* wrapQObject(QObject* obj);
464
519
465 //! 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
520 //! 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
466 PyObject* wrapPtr(void* ptr, const QByteArray& name);
521 PyObject* wrapPtr(void* ptr, const QByteArray& name);
467
522
468 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
523 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
469 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
524 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
470 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
525 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
471 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
526 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
472
527
473 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
528 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
474 //! (ownership of wrapper is passed to PythonQt)
529 //! (ownership of wrapper is passed to PythonQt)
475 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
530 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
476
531
477 This will add a wrapper object that is used to make calls to the given classname \c typeName.
532 This will add a wrapper object that is used to make calls to the given classname \c typeName.
478 All slots that take a pointer to typeName as the first argument will be callable from Python on
533 All slots that take a pointer to typeName as the first argument will be callable from Python on
479 a variant object that contains such a type.
534 a variant object that contains such a type.
480 */
535 */
481 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);
536 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);
482
537
483 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
538 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
484 //! and it will register the classes when it first sees a pointer to such a derived class
539 //! and it will register the classes when it first sees a pointer to such a derived class
485 void registerQObjectClassNames(const QStringList& names);
540 void registerQObjectClassNames(const QStringList& names);
486
541
487 //! add a decorator object
542 //! add a decorator object
488 void addDecorators(QObject* o, int decoTypes);
543 void addDecorators(QObject* o, int decoTypes);
489
544
490 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
545 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
491 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
546 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
492
547
493 //! create a new instance of the given enum type with given value (returns a new reference)
548 //! create a new instance of the given enum type with given value (returns a new reference)
494 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
549 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
495
550
496 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
551 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
497 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
552 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
498
553
499 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
554 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
500 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
555 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
501
556
502 //! get the class info for a meta object (if available)
557 //! get the class info for a meta object (if available)
503 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
558 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
504
559
505 //! get the class info for a meta object (if available)
560 //! get the class info for a meta object (if available)
506 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
561 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
507
562
508 //! creates the new module from the given pycode
563 //! creates the new module from the given pycode
509 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
564 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
510
565
511 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
566 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
512 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
567 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
513
568
514 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
569 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
515 static PyObject* dummyTuple();
570 static PyObject* dummyTuple();
516
571
517 //! called by virtual overloads when a python return value can not be converted to the required Qt type
572 //! called by virtual overloads when a python return value can not be converted to the required Qt type
518 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
573 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
519
574
520 //! get access to the PythonQt module
575 //! get access to the PythonQt module
521 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
576 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
522
577
523 private:
578 private:
524 //! Setup the shared library suffixes by getting them from the "imp" module.
579 //! Setup the shared library suffixes by getting them from the "imp" module.
525 void setupSharedLibrarySuffixes();
580 void setupSharedLibrarySuffixes();
526
581
527 //! create a new pythonqt class wrapper and place it in the pythonqt module
582 //! create a new pythonqt class wrapper and place it in the pythonqt module
528 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
583 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
529
584
530 //! get/create new package module (the returned object is a borrowed reference)
585 //! get/create new package module (the returned object is a borrowed reference)
531 PyObject* packageByName(const char* name);
586 PyObject* packageByName(const char* name);
532
587
533 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
588 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
534 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
589 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
535
590
536 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
591 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
537 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
592 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
538
593
539 //! stores the meta info of known Qt classes
594 //! stores the meta info of known Qt classes
540 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
595 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
541
596
542 //! names of qobject derived classes that can be casted to qobject savely
597 //! names of qobject derived classes that can be casted to qobject savely
543 QHash<QByteArray, bool> _knownQObjectClassNames;
598 QHash<QByteArray, bool> _knownQObjectClassNames;
544
599
545 //! stores signal receivers for QObjects
600 //! stores signal receivers for QObjects
546 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
601 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
547
602
548 //! the PythonQt python module
603 //! the PythonQt python module
549 PythonQtObjectPtr _pythonQtModule;
604 PythonQtObjectPtr _pythonQtModule;
550
605
551 //! the name of the PythonQt python module
606 //! the name of the PythonQt python module
552 QByteArray _pythonQtModuleName;
607 QByteArray _pythonQtModuleName;
553
608
554 //! the importer interface (if set)
609 //! the importer interface (if set)
555 PythonQtImportFileInterface* _importInterface;
610 PythonQtImportFileInterface* _importInterface;
556
611
557 //! the default importer
612 //! the default importer
558 PythonQtQFileImporter* _defaultImporter;
613 PythonQtQFileImporter* _defaultImporter;
559
614
560 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
615 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
561 PythonQtQObjectWrappedCB* _wrappedCB;
616 PythonQtQObjectWrappedCB* _wrappedCB;
562
617
563 QStringList _importIgnorePaths;
618 QStringList _importIgnorePaths;
564 QStringList _sharedLibrarySuffixes;
619 QStringList _sharedLibrarySuffixes;
565
620
566 //! the cpp object wrapper factories
621 //! the cpp object wrapper factories
567 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
622 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
568
623
569 QHash<QByteArray, PyObject*> _packages;
624 QHash<QByteArray, PyObject*> _packages;
570
625
571 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
626 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
572
627
573 int _initFlags;
628 int _initFlags;
574 int _PythonQtObjectPtr_metaId;
629 int _PythonQtObjectPtr_metaId;
575
630
576 friend class PythonQt;
631 friend class PythonQt;
577 };
632 };
578
633
579 #endif
634 #endif
General Comments 0
You need to be logged in to leave comments. Login now