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