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