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