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