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