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