##// END OF EJS Templates
- wrapped instances are now wrapped by class specific subtypes to facilitate future deriving from python...
florianlink -
r18:44e5ff2700cb
parent child
Show More
@@ -170,17 +170,20 PythonQt::PythonQt(int flags)
170 }
170 }
171 Py_INCREF(&PythonQtSlotFunction_Type);
171 Py_INCREF(&PythonQtSlotFunction_Type);
172
172
173 // add our own python object types for qt objects
173 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
174 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
174 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
175 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
175 // add our own python object types for classes
176 }
177 Py_INCREF(&PythonQtInstanceWrapper_Type);
178
179 // add our own python object types for qt objects
180 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
176 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
181 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 }
178 }
183 Py_INCREF(&PythonQtClassWrapper_Type);
179 Py_INCREF(&PythonQtClassWrapper_Type);
180
181 // add our own python object types for CPP instances
182 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
183 PythonQt::handleError();
184 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
186 Py_INCREF(&PythonQtInstanceWrapper_Type);
184
187
185 // add our own python object types for redirection of stdout
188 // add our own python object types for redirection of stdout
186 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
189 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
@@ -274,16 +277,8 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p
274 while (m) {
277 while (m) {
275 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
278 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
276 if (!info) {
279 if (!info) {
277 info = new PythonQtClassInfo(m);
280 info = createPythonQtClassInfo(m, NULL, package);
278 _knownQtClasses.insert(m->className(), info);
281 _knownQtClasses.insert(m->className(), info);
279 PythonQtObjectPtr pack = packageByName(package);
280 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info);
281 PyModule_AddObject(pack, m->className(), pyobj);
282 if (package && strncmp(package,"Qt",2)==0) {
283 // put all qt objects into Qt as well
284 PythonQtObjectPtr pack = packageByName("Qt");
285 PyModule_AddObject(pack, m->className(), pyobj);
286 }
287 }
282 }
288 if (first) {
283 if (first) {
289 first = false;
284 first = false;
@@ -295,6 +290,21 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p
295 }
290 }
296 }
291 }
297
292
293 PythonQtClassInfo* PythonQtPrivate::createPythonQtClassInfo(const QMetaObject* meta, const char* cppClassName, const char* package)
294 {
295 PythonQtClassInfo* info = new PythonQtClassInfo(meta, cppClassName);
296 PythonQtObjectPtr pack = packageByName(package);
297 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package);
298 PyModule_AddObject(pack, meta?meta->className():cppClassName, pyobj);
299 if (package && strncmp(package,"Qt",2)==0) {
300 // put all qt objects into Qt as well
301 PythonQtObjectPtr pack = packageByName("Qt");
302 PyModule_AddObject(pack, meta?meta->className():cppClassName, pyobj);
303 }
304 info->setPythonQtClassWrapper(pyobj);
305 return info;
306 }
307
298 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
308 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
299 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
309 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
300 if (i!=-1) {
310 if (i!=-1) {
@@ -337,10 +347,10 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
337 classInfo = _knownQtClasses.value(obj->metaObject()->className());
347 classInfo = _knownQtClasses.value(obj->metaObject()->className());
338 }
348 }
339 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
349 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
340 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
350 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
341 } else {
351 } else {
342 Py_INCREF(wrap);
352 Py_INCREF(wrap);
343 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
353 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
344 }
354 }
345 return (PyObject*)wrap;
355 return (PyObject*)wrap;
346 }
356 }
@@ -371,7 +381,7 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
371 info = _knownQtClasses.value(qptr->metaObject()->className());
381 info = _knownQtClasses.value(qptr->metaObject()->className());
372 }
382 }
373 wrap = createNewPythonQtInstanceWrapper(qptr, info);
383 wrap = createNewPythonQtInstanceWrapper(qptr, info);
374 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
384 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
375 } else {
385 } else {
376 // maybe it is a PyObject, which we can return directly
386 // maybe it is a PyObject, which we can return directly
377 if (name == "PyObject") {
387 if (name == "PyObject") {
@@ -389,32 +399,37 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
389 }
399 }
390 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
400 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
391 if (!info) {
401 if (!info) {
392 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():NULL, name);
402 registerCPPClass(name.constData());
393 _knownQtWrapperClasses.insert(name, info);
403 info = _knownQtWrapperClasses.value(name);
394 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtClassWrapper(info));
404 }
395 } else {
405 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
396 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
406 info->setMetaObject(wrapper->metaObject());
397 info->setMetaObject(wrapper->metaObject());
398 }
399 }
407 }
400 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
408 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
401 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
409 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
402 }
410 }
403 } else {
411 } else {
404 Py_INCREF(wrap);
412 Py_INCREF(wrap);
405 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
413 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
406 }
414 }
407 return (PyObject*)wrap;
415 return (PyObject*)wrap;
408 }
416 }
409
417
418 PyObject* PythonQtPrivate::dummyTuple() {
419 static PyObject* dummyTuple = NULL;
420 if (dummyTuple==NULL) {
421 dummyTuple = PyTuple_New(1);
422 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
423 }
424 return dummyTuple;
425 }
426
410
427
411 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
428 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
412 PythonQtInstanceWrapper* result;
429 // call the associated class type to create a new instance...
413 result = (PythonQtInstanceWrapper *)PythonQtInstanceWrapper_Type.tp_new(&PythonQtInstanceWrapper_Type,
430 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
414 NULL, NULL);
415
431
416 result->setQObject(obj);
432 result->setQObject(obj);
417 result->_info = info;
418 result->_wrappedPtr = wrappedPtr;
433 result->_wrappedPtr = wrappedPtr;
419 result->_ownedByPythonQt = false;
434 result->_ownedByPythonQt = false;
420 result->_useQMetaTypeDestroy = false;
435 result->_useQMetaTypeDestroy = false;
@@ -431,11 +446,36 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObje
431 return result;
446 return result;
432 }
447 }
433
448
434 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info) {
449 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
435 PythonQtClassWrapper* result;
450 PythonQtClassWrapper* result;
436 result = (PythonQtClassWrapper *)PythonQtClassWrapper_Type.tp_new(&PythonQtClassWrapper_Type,
451
437 NULL, NULL);
452 PyObject* className = PyString_FromString(info->className());
438 result->_info = info;
453
454 PyObject* baseClasses = PyTuple_New(1);
455 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
456
457 PyObject* typeDict = PyDict_New();
458 QByteArray moduleName("PythonQt");
459 if (package && strcmp(package, "")!=0) {
460 moduleName += ".";
461 moduleName += package;
462 }
463 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
464
465 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
466
467 // set the class info so that PythonQtClassWrapper_new can read it
468 _currentClassInfoForClassWrapperCreation = info;
469 // create the new type object by calling the type
470 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
471
472 Py_DECREF(baseClasses);
473 Py_DECREF(typeDict);
474 Py_DECREF(args);
475 Py_DECREF(className);
476
477 //TODO XXX why is this incref needed? It looks like the types get garbage collected somehow?!
478 Py_INCREF((PyObject*)result);
439 return result;
479 return result;
440 }
480 }
441
481
@@ -666,7 +706,7 QStringList PythonQt::introspection(PyObject* module, const QString& objectname,
666 }
706 }
667 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
707 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
668 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
708 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
669 PythonQtSlotInfo* info = o->_info->constructors();
709 PythonQtSlotInfo* info = o->classInfo()->constructors();
670
710
671 while (info) {
711 while (info) {
672 results << info->fullSignature(false);
712 results << info->fullSignature(false);
@@ -817,16 +857,6 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
817 _p->_cppWrapperFactories.append(factory);
857 _p->_cppWrapperFactories.append(factory);
818 }
858 }
819
859
820 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
821 {
822 _p->_constructorHandlers.append(factory);
823 }
824
825 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
826 {
827 return _p->_constructorHandlers;
828 };
829
830 //---------------------------------------------------------------------------------------------------
860 //---------------------------------------------------------------------------------------------------
831 PythonQtPrivate::PythonQtPrivate()
861 PythonQtPrivate::PythonQtPrivate()
832 {
862 {
@@ -834,6 +864,14 PythonQtPrivate::PythonQtPrivate()
834 _defaultImporter = new PythonQtQFileImporter;
864 _defaultImporter = new PythonQtQFileImporter;
835 _noLongerWrappedCB = NULL;
865 _noLongerWrappedCB = NULL;
836 _wrappedCB = NULL;
866 _wrappedCB = NULL;
867 _currentClassInfoForClassWrapperCreation = NULL;
868 }
869
870 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
871 {
872 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
873 _currentClassInfoForClassWrapperCreation = NULL;
874 return info;
837 }
875 }
838
876
839 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
877 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
@@ -1006,16 +1044,8 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentT
1006 {
1044 {
1007 PythonQtClassInfo* info = _knownQtWrapperClasses.value(typeName);
1045 PythonQtClassInfo* info = _knownQtWrapperClasses.value(typeName);
1008 if (!info) {
1046 if (!info) {
1009 info = new PythonQtClassInfo(NULL, typeName);
1047 info = createPythonQtClassInfo(NULL, typeName, package);
1010 _knownQtWrapperClasses.insert(typeName, info);
1048 _knownQtWrapperClasses.insert(typeName, info);
1011 PythonQtObjectPtr pack = packageByName(package);
1012 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info);
1013 PyModule_AddObject(pack, typeName, pyobj);
1014 if (package && strncmp(package,"Qt",2)==0) {
1015 // put all qt objects into Qt as well
1016 PythonQtObjectPtr pack = packageByName("Qt");
1017 PyModule_AddObject(pack, typeName, pyobj);
1018 }
1019 }
1049 }
1020 if (parentTypeName) {
1050 if (parentTypeName) {
1021 info->setWrappedParentClassName(parentTypeName);
1051 info->setWrappedParentClassName(parentTypeName);
@@ -1055,6 +1085,11 void PythonQtPrivate::removeWrapperPointer(void* obj)
1055 _wrappedObjects.remove(obj);
1085 _wrappedObjects.remove(obj);
1056 }
1086 }
1057
1087
1088 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1089 {
1090 _wrappedObjects.insert(obj, wrapper);
1091 }
1092
1058 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1093 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1059 {
1094 {
1060 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1095 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
@@ -63,7 +63,6 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtConstructorHandler;
67 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
68
67
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
@@ -269,12 +268,6 public:
269 //! add the given factory to PythonQt (ownership stays with caller)
268 //! add the given factory to PythonQt (ownership stays with caller)
270 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
269 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
271
270
272 //! add the given constructor handler to PythonQt (ownership stays with caller)
273 void addConstructorHandler(PythonQtConstructorHandler* handler);
274
275 //! get list of constructor handlers
276 const QList<PythonQtConstructorHandler*>& constructorHandlers();
277
278 //@}
271 //@}
279
272
280 //@{ Custom importer (to replace internal import implementation of python)
273 //@{ Custom importer (to replace internal import implementation of python)
@@ -383,6 +376,8 public:
383 //! returns if the id is the id for PythonQtObjectPtr
376 //! returns if the id is the id for PythonQtObjectPtr
384 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
377 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
385
378
379 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
380 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
386 //! remove the wrapper ptr again
381 //! remove the wrapper ptr again
387 void removeWrapperPointer(void* obj);
382 void removeWrapperPointer(void* obj);
388
383
@@ -425,7 +420,7 public:
425 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
420 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
426
421
427 //! helper method that creates a PythonQtClassWrapper object
422 //! helper method that creates a PythonQtClassWrapper object
428 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info);
423 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
429
424
430 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
425 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
431 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
426 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
@@ -445,7 +440,17 public:
445 //! creates the new module from the given pycode
440 //! creates the new module from the given pycode
446 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
441 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
447
442
443 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
444 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
445
446 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
447 static PyObject* dummyTuple();
448
448 private:
449 private:
450
451 //! create a new class info and python wrapper type
452 PythonQtClassInfo* createPythonQtClassInfo(const QMetaObject* meta, const char* cppClassName, const char* package);
453
449 //! get/create new package module
454 //! get/create new package module
450 PythonQtObjectPtr packageByName(const char* name);
455 PythonQtObjectPtr packageByName(const char* name);
451
456
@@ -487,14 +492,13 private:
487 //! the cpp object wrapper factories
492 //! the cpp object wrapper factories
488 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
493 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
489
494
490 //! the cpp object wrapper factories
491 QList<PythonQtConstructorHandler*> _constructorHandlers;
492
493 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
495 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
494 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
496 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
495
497
496 QHash<QByteArray, PythonQtObjectPtr> _packages;
498 QHash<QByteArray, PythonQtObjectPtr> _packages;
497
499
500 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
501
498 int _initFlags;
502 int _initFlags;
499 int _PythonQtObjectPtr_metaId;
503 int _PythonQtObjectPtr_metaId;
500
504
@@ -54,6 +54,7 PythonQtClassInfo::PythonQtClassInfo(const QMetaObject* meta, const QByteArray&
54 _parentClassInfoResolved = false;
54 _parentClassInfoResolved = false;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 if (wrappedClassName.isEmpty()) {
58 if (wrappedClassName.isEmpty()) {
58 _metaTypeId = -1;
59 _metaTypeId = -1;
59 } else {
60 } else {
@@ -125,6 +125,12 public:
125 //! check if the special method "hasOwner" is implemented and if it returns false, which means that the object may be destroyed
125 //! check if the special method "hasOwner" is implemented and if it returns false, which means that the object may be destroyed
126 bool hasOwnerMethodButNoOwner(void* object);
126 bool hasOwnerMethodButNoOwner(void* object);
127
127
128 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
129 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
130
131 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
132 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
133
128 private:
134 private:
129 //! resolve the parent class from either meta object or cpp parent class name
135 //! resolve the parent class from either meta object or cpp parent class name
130 void resolveParentClassInfo();
136 void resolveParentClassInfo();
@@ -150,6 +156,8 private:
150 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
156 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
151 PythonQtClassInfo* _parentClassInfo;
157 PythonQtClassInfo* _parentClassInfo;
152
158
159 PyObject* _pythonQtClassWrapper;
160
153 bool _parentClassInfoResolved;
161 bool _parentClassInfoResolved;
154 int _metaTypeId;
162 int _metaTypeId;
155
163
@@ -47,72 +47,50
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49
49
50 static void PythonQtClassWrapper_dealloc(PythonQtClassWrapper* self)
50 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
51 {
51 {
52 self->ob_type->tp_free((PyObject*)self);
52 // call the default type alloc
53 }
53 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
54
54
55 static PyObject* PythonQtClassWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
55 // take current class type, if we are called via newPythonQtClassWrapper()
56 {
56 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
57 PythonQtClassWrapper *self;
57 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
58
58
59 self = (PythonQtClassWrapper *)type->tp_alloc(type, 0);
59 return obj;
60 if (self != NULL) {
61 self->_info = NULL;
62 }
63 return (PyObject *)self;
64 }
60 }
65
61
66 static int PythonQtClassWrapper_init(PythonQtClassWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
67 {
68 return 0;
69 }
70
62
71 PyObject *PythonQtClassWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
63 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
72 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)func;
64 {
73 PyObject* result = NULL;
65 // call the default type init
74 QString error;
66 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
75 PyObject* err = NULL;
67 return -1;
76 if (wrapper->_info->constructors()) {
77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
78 err = PyErr_Occurred();
79 }
80 if (!result) {
81 QObject* v = NULL;
82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
83 while (!v && it.hasNext()) {
84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
85 }
86 if (v) {
87 result = PythonQt::priv()->wrapQObject(v);
88 }
89 }
68 }
90 if (result) {
69
91 // change ownershipflag to be owned by PythonQt
70 // if we have no CPP class information, try our base class
92 if (result->ob_type == &PythonQtInstanceWrapper_Type) {
71 if (!self->classInfo()) {
93 ((PythonQtInstanceWrapper*)result)->_ownedByPythonQt = true;
72 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
94 }
73
95 } else {
74 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
96 if (!wrapper->_info->constructors()) {
75 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
97 if (!err) {
76 return -1;
98 if (error.isEmpty()) {
99 error = QString("No constructors available for ") + wrapper->_info->className();
100 }
101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
102 }
103 }
77 }
78
79 // take the class info from the superType
80 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
104 }
81 }
105 return result;
82
83 return 0;
106 }
84 }
107
85
108 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
86 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
109 {
87 {
110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
88 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
111 }
89 }
112
90
113 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
91 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
114 {
92 {
115 return PythonQt::self()->helpCalled(type->_info);
93 return PythonQt::self()->helpCalled(type->classInfo());
116 }
94 }
117
95
118
96
@@ -127,7 +105,7 static PyMethodDef PythonQtClassWrapper_methods[] = {
127 };
105 };
128
106
129
107
130 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj,PyObject *name)
108 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
131 {
109 {
132 const char *attributeName;
110 const char *attributeName;
133 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
111 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
@@ -136,7 +114,7 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj,PyObject *name)
136 return NULL;
114 return NULL;
137 }
115 }
138
116
139 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
117 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
140 if (member._type == PythonQtMemberInfo::EnumValue) {
118 if (member._type == PythonQtMemberInfo::EnumValue) {
141 return PyInt_FromLong(member._enumValue);
119 return PyInt_FromLong(member._enumValue);
142 }
120 }
@@ -152,7 +130,7 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj,PyObject *name)
152 PyErr_Clear();
130 PyErr_Clear();
153
131
154 if (qstrcmp(attributeName, "__dict__")==0) {
132 if (qstrcmp(attributeName, "__dict__")==0) {
155 QStringList l = wrapper->_info->memberList(true);
133 QStringList l = wrapper->classInfo()->memberList(true);
156 PyObject* dict = PyDict_New();
134 PyObject* dict = PyDict_New();
157 foreach (QString name, l) {
135 foreach (QString name, l) {
158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
136 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
@@ -162,53 +140,47 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj,PyObject *name)
162 return dict;
140 return dict;
163 }
141 }
164
142
165 QString error = QString(wrapper->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
143 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
144 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
167 return NULL;
145 return NULL;
168 }
146 }
169
147
148 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject * /*value*/)
149 {
150 QString error;
151 char *attributeName;
152 if ((attributeName = PyString_AsString(name)) == NULL) {
153 return -1;
154 }
155 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
156
157 // TODO
158 return -1;
159 }
160
161 /*
170 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
162 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
171 {
163 {
172 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
164 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
173 if (wrapper->_info->isCPPWrapper()) {
165 if (wrapper->classInfo()->isCPPWrapper()) {
174 const QMetaObject* meta = wrapper->_info->metaObject();
166 const QMetaObject* meta = wrapper->classInfo()->metaObject();
175 if (!meta) {
167 if (!meta) {
176 QObject* decorator = wrapper->_info->decorator();
168 QObject* decorator = wrapper->classInfo()->decorator();
177 if (decorator) {
169 if (decorator) {
178 meta = decorator->metaObject();
170 meta = decorator->metaObject();
179 }
171 }
180 }
172 }
181 if (meta) {
173 if (meta) {
182 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->_info->className(), meta->className());
174 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
183 } else {
184 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->_info->className());
185 }
186 } else {
187 return PyString_FromFormat("%s Class", wrapper->_info->className());
188 }
189 }
190
191 static int PythonQtClassWrapper_compare(PyObject * obj1, PyObject * obj2)
192 {
193 if (obj1->ob_type == &PythonQtClassWrapper_Type &&
194 obj2->ob_type == &PythonQtClassWrapper_Type) {
195
196 PythonQtClassWrapper* w1 = (PythonQtClassWrapper*)obj1;
197 PythonQtClassWrapper* w2 = (PythonQtClassWrapper*)obj2;
198 if (w1->_info == w2->_info) {
199 return 0;
200 } else {
175 } else {
201 return -1;
176 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
202 }
177 }
203 } else {
178 } else {
204 return -1;
179 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
205 }
180 }
206 }
181 }
207
182
208 static long PythonQtClassWrapper_hash(PythonQtClassWrapper *obj)
183 */
209 {
210 return reinterpret_cast<long>(obj->_info);
211 }
212
184
213 PyTypeObject PythonQtClassWrapper_Type = {
185 PyTypeObject PythonQtClassWrapper_Type = {
214 PyObject_HEAD_INIT(NULL)
186 PyObject_HEAD_INIT(NULL)
@@ -216,23 +188,23 PyTypeObject PythonQtClassWrapper_Type = {
216 "PythonQt.PythonQtClassWrapper", /*tp_name*/
188 "PythonQt.PythonQtClassWrapper", /*tp_name*/
217 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
189 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
218 0, /*tp_itemsize*/
190 0, /*tp_itemsize*/
219 (destructor)PythonQtClassWrapper_dealloc, /*tp_dealloc*/
191 0, /*tp_dealloc*/
220 0, /*tp_print*/
192 0, /*tp_print*/
221 0, /*tp_getattr*/
193 0, /*tp_getattr*/
222 0, /*tp_setattr*/
194 0, /*tp_setattr*/
223 PythonQtClassWrapper_compare, /*tp_compare*/
195 0, /*tp_compare*/
224 PythonQtClassWrapper_repr, /*tp_repr*/
196 0, //PythonQtClassWrapper_repr, /*tp_repr*/
225 0, /*tp_as_number*/
197 0, /*tp_as_number*/
226 0, /*tp_as_sequence*/
198 0, /*tp_as_sequence*/
227 0, /*tp_as_mapping*/
199 0, /*tp_as_mapping*/
228 (hashfunc)PythonQtClassWrapper_hash, /*tp_hash */
200 0, /*tp_hash */
229 PythonQtClassWrapper_call, /*tp_call*/
201 0, /*tp_call*/
230 0, /*tp_str*/
202 0, /*tp_str*/
231 PythonQtClassWrapper_getattro, /*tp_getattro*/
203 PythonQtClassWrapper_getattro, /*tp_getattro*/
232 0, /*tp_setattro*/
204 PythonQtClassWrapper_setattro, /*tp_setattro*/
233 0, /*tp_as_buffer*/
205 0, /*tp_as_buffer*/
234 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
206 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
235 "PythonQtClassWrapper object", /* tp_doc */
207 0, /* tp_doc */
236 0, /* tp_traverse */
208 0, /* tp_traverse */
237 0, /* tp_clear */
209 0, /* tp_clear */
238 0, /* tp_richcompare */
210 0, /* tp_richcompare */
@@ -248,8 +220,9 PyTypeObject PythonQtClassWrapper_Type = {
248 0, /* tp_descr_set */
220 0, /* tp_descr_set */
249 0, /* tp_dictoffset */
221 0, /* tp_dictoffset */
250 (initproc)PythonQtClassWrapper_init, /* tp_init */
222 (initproc)PythonQtClassWrapper_init, /* tp_init */
251 0, /* tp_alloc */
223 PythonQtClassWrapper_alloc, /* tp_alloc */
252 PythonQtClassWrapper_new, /* tp_new */
224 0, /* tp_new */
225 0, /* tp_free */
253 };
226 };
254
227
255 //-------------------------------------------------------
228 //-------------------------------------------------------
@@ -51,29 +51,25
51 #include <QString>
51 #include <QString>
52
52
53 class PythonQtClassInfo;
53 class PythonQtClassInfo;
54 class QObject;
55 struct QMetaObject;
56
54
55 //! the type of the PythonQt class wrapper objects
57 extern PyTypeObject PythonQtClassWrapper_Type;
56 extern PyTypeObject PythonQtClassWrapper_Type;
58
57
59 //---------------------------------------------------------------
58 //---------------------------------------------------------------
60 //! a Python wrapper object for Qt meta objects
59 //! a Python wrapper object for PythonQt wrapped classes
60 //! which inherits from the Python type object to allow
61 //! deriving of wrapped CPP classes from Python.
61 typedef struct {
62 typedef struct {
62 PyObject_HEAD
63 PyHeapTypeObject _base;
63
64
64 //! the class information (which contains the meta object as well)
65 //! the additional class information that PythonQt stores for the CPP class
65 PythonQtClassInfo* _info;
66 PythonQtClassInfo* _classInfo;
67
68 //! get the class info
69 PythonQtClassInfo* classInfo() { return _classInfo; }
66
70
67 } PythonQtClassWrapper;
71 } PythonQtClassWrapper;
68
72
69 //---------------------------------------------------------------
73 //---------------------------------------------------------------
70 // an abstact class for handling construction of objects
71 class PythonQtConstructorHandler {
72 public:
73 //! get rid of warnings
74 virtual ~PythonQtConstructorHandler() {}
75
76 virtual QObject* create(const QMetaObject* meta, PyObject *args, PyObject *kw, QString& error) = 0;
77 };
78
74
79 #endif No newline at end of file
75 #endif
@@ -224,15 +224,15 return Py_None;
224 {
224 {
225 bool ok;
225 bool ok;
226 void* ptr = NULL;
226 void* ptr = NULL;
227 if (obj->ob_type == &PythonQtInstanceWrapper_Type && info.typeId != PythonQtMethodInfo::Variant) {
227 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
228 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
228 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
229 // (the Variant case is handled below in a switch)
229 // (the Variant case is handled below in a switch)
230
230
231 // a C++ wrapper (can be passed as pointer or reference)
231 // a C++ wrapper (can be passed as pointer or reference)
232 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
232 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
233 if (wrap->_info->inherits(info.name)) {
233 if (wrap->classInfo()->inherits(info.name)) {
234 void* object;
234 void* object;
235 if (wrap->_info->isCPPWrapper()) {
235 if (wrap->classInfo()->isCPPWrapper()) {
236 object = wrap->_wrappedPtr;
236 object = wrap->_wrappedPtr;
237 } else {
237 } else {
238 QObject* tmp = wrap->_obj;
238 QObject* tmp = wrap->_obj;
@@ -690,13 +690,13 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
690 type = QVariant::Double;
690 type = QVariant::Double;
691 } else if (val == Py_False || val == Py_True) {
691 } else if (val == Py_False || val == Py_True) {
692 type = QVariant::Bool;
692 type = QVariant::Bool;
693 } else if (val->ob_type == &PythonQtInstanceWrapper_Type) {
693 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
694 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
694 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
695 // c++ wrapper, check if the class names of the c++ objects match
695 // c++ wrapper, check if the class names of the c++ objects match
696 if (wrap->_info->isCPPWrapper()) {
696 if (wrap->classInfo()->isCPPWrapper()) {
697 if (wrap->_info->metaTypeId()>0) {
697 if (wrap->classInfo()->metaTypeId()>0) {
698 // construct a new variant from the C++ object if it has a meta type
698 // construct a new variant from the C++ object if it has a meta type
699 v = QVariant(wrap->_info->metaTypeId(), wrap->_wrappedPtr);
699 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
700 } else {
700 } else {
701 // is this worth anything? we loose the knowledge of the cpp object type
701 // is this worth anything? we loose the knowledge of the cpp object type
702 v = qVariantFromValue(wrap->_wrappedPtr);
702 v = qVariantFromValue(wrap->_wrappedPtr);
@@ -849,9 +849,9 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
849 break;
849 break;
850
850
851 default:
851 default:
852 if (val->ob_type == &PythonQtInstanceWrapper_Type) {
852 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
853 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
853 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
854 if (wrap->_info->isCPPWrapper() && wrap->_info->metaTypeId() == type) {
854 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
855 // construct a new variant from the C++ object if it has the same meta type
855 // construct a new variant from the C++ object if it has the same meta type
856 v = QVariant(type, wrap->_wrappedPtr);
856 v = QVariant(type, wrap->_wrappedPtr);
857 } else {
857 } else {
@@ -956,11 +956,11 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<vo
956 PyObject* value;
956 PyObject* value;
957 for (int i = 0;i<count;i++) {
957 for (int i = 0;i<count;i++) {
958 value = PySequence_GetItem(obj,i);
958 value = PySequence_GetItem(obj,i);
959 if (value->ob_type == &PythonQtInstanceWrapper_Type) {
959 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
960 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
960 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
961 // both QObjects and CPP wrappers support inherits, so we use that to check of we match
961 // both QObjects and CPP wrappers support inherits, so we use that to check of we match
962 if (wrap->_info->inherits(type)) {
962 if (wrap->classInfo()->inherits(type)) {
963 if (wrap->_info->isCPPWrapper()) {
963 if (wrap->classInfo()->isCPPWrapper()) {
964 list->append(wrap->_wrappedPtr);
964 list->append(wrap->_wrappedPtr);
965 } else {
965 } else {
966 QObject* myObject = wrap->_obj;
966 QObject* myObject = wrap->_obj;
@@ -45,24 +45,31
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
49
50 PythonQtClassInfo* PythonQtInstanceWrapper::classInfo()
51 {
52 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
48
55
49 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
50
57
51 // is this a C++ wrapper?
58 // is this a C++ wrapper?
52 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
54
61
55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
56 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
57 delete self->_obj;
64 delete self->_obj;
58 self->_obj = NULL;
65 self->_obj = NULL;
59 if (force || self->_info->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
60 int type = self->_info->metaTypeId();
67 int type = self->classInfo()->metaTypeId();
61 if (self->_useQMetaTypeDestroy && type>=0) {
68 if (self->_useQMetaTypeDestroy && type>=0) {
62 // use QMetaType to destroy the object
69 // use QMetaType to destroy the object
63 QMetaType::destroy(type, self->_wrappedPtr);
70 QMetaType::destroy(type, self->_wrappedPtr);
64 } else {
71 } else {
65 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->className());
72 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->classInfo()->className());
66 if (slot) {
73 if (slot) {
67 void* args[2];
74 void* args[2];
68 args[0] = NULL;
75 args[0] = NULL;
@@ -80,7 +87,7 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self,
80 }
87 }
81 }
88 }
82 } else {
89 } else {
83 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
84 if (self->_objPointerCopy) {
91 if (self->_objPointerCopy) {
85 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
86 }
93 }
@@ -107,13 +114,18 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
107 self->ob_type->tp_free((PyObject*)self);
114 self->ob_type->tp_free((PyObject*)self);
108 }
115 }
109
116
110 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * args, PyObject * /*kwds*/)
111 {
118 {
119 PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
112 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
124 }
125
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
113
127
114 self = (PythonQtInstanceWrapper *)type->tp_alloc(type, 0);
115 if (self != NULL) {
128 if (self != NULL) {
116 self->_info = NULL;
117 new (&self->_obj) QPointer<QObject>();
129 new (&self->_obj) QPointer<QObject>();
118 self->_wrappedPtr = NULL;
130 self->_wrappedPtr = NULL;
119 self->_ownedByPythonQt = false;
131 self->_ownedByPythonQt = false;
@@ -122,19 +134,51 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*ar
122 return (PyObject *)self;
134 return (PyObject *)self;
123 }
135 }
124
136
125 static int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
137 static int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
126 {
138 {
139 PyObject* result = NULL;
140
141 if (args == PythonQtPrivate::dummyTuple()) {
142 // we are called from the internal PythonQt API, so our data will be filled later on...
143 return 0;
144 }
145
146 // we are called from python, try to construct our object
147 if (self->classInfo()->constructors()) {
148 void* directCPPPointer = NULL;
149 PythonQtSlotFunction_CallImpl(NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
150 if (PyErr_Occurred()) {
151 return -1;
152 }
153 if (directCPPPointer) {
154 // change ownershipflag to be owned by PythonQt
155 self->_ownedByPythonQt = true;
156 self->_useQMetaTypeDestroy = false;
157 if (self->classInfo()->isCPPWrapper()) {
158 self->_wrappedPtr = directCPPPointer;
159 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
160 } else {
161 self->setQObject((QObject*)directCPPPointer);
162 }
163 // register with PythonQt
164 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
165 }
166 } else {
167 QString error = QString("No constructors available for ") + self->classInfo()->className();
168 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
169 return -1;
170 }
127 return 0;
171 return 0;
128 }
172 }
129
173
130 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* type)
174 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* type)
131 {
175 {
132 return PyString_FromString(type->_info->className());
176 return PyString_FromString(type->classInfo()->className());
133 }
177 }
134
178
135 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* type)
179 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* type)
136 {
180 {
137 return PythonQt::self()->helpCalled(type->_info);
181 return PythonQt::self()->helpCalled(type->classInfo());
138 }
182 }
139
183
140 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
184 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
@@ -169,7 +213,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
169 }
213 }
170
214
171 if (!wrapper->_obj && !wrapper->_wrappedPtr) {
215 if (!wrapper->_obj && !wrapper->_wrappedPtr) {
172 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wrapper->_info->className() + " object";
216 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
173 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
217 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
174 return NULL;
218 return NULL;
175 }
219 }
@@ -178,7 +222,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
178
222
179 // TODO: dynamic properties are missing
223 // TODO: dynamic properties are missing
180
224
181 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
225 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
182 switch (member._type) {
226 switch (member._type) {
183 case PythonQtMemberInfo::Property:
227 case PythonQtMemberInfo::Property:
184 if (wrapper->_obj) {
228 if (wrapper->_obj) {
@@ -215,7 +259,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
215 }
259 }
216
260
217 if (qstrcmp(attributeName, "__dict__")==0) {
261 if (qstrcmp(attributeName, "__dict__")==0) {
218 QStringList l = wrapper->_info->memberList(false);
262 QStringList l = wrapper->classInfo()->memberList(false);
219 PyObject* dict = PyDict_New();
263 PyObject* dict = PyDict_New();
220 foreach (QString name, l) {
264 foreach (QString name, l) {
221 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
265 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
@@ -227,7 +271,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
227 }
271 }
228
272
229
273
230 QString error = QString(wrapper->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
274 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
231 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
275 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
232 return NULL;
276 return NULL;
233 }
277 }
@@ -242,12 +286,12 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
242 return -1;
286 return -1;
243
287
244 if (!wrapper->_obj) {
288 if (!wrapper->_obj) {
245 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wrapper->_info->className() + " object";
289 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
246 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
290 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
247 return -1;
291 return -1;
248 }
292 }
249
293
250 PythonQtMemberInfo member = wrapper->_info->member(attributeName);
294 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
251 if (member._type == PythonQtMemberInfo::Property) {
295 if (member._type == PythonQtMemberInfo::Property) {
252 QMetaProperty prop = member._property;
296 QMetaProperty prop = member._property;
253 if (prop.isWritable()) {
297 if (prop.isWritable()) {
@@ -271,13 +315,13 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
271 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
315 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
272 }
316 }
273 } else {
317 } else {
274 error = QString("Property '") + attributeName + "' of " + wrapper->_info->className() + " object is not writable";
318 error = QString("Property '") + attributeName + "' of " + wrapper->classInfo()->className() + " object is not writable";
275 }
319 }
276 } else {
320 } else {
277 if (member._type == PythonQtMemberInfo::Slot) {
321 if (member._type == PythonQtMemberInfo::Slot) {
278 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wrapper->_info->className() + " object";
322 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wrapper->classInfo()->className() + " object";
279 } else if (member._type == PythonQtMemberInfo::EnumValue) {
323 } else if (member._type == PythonQtMemberInfo::EnumValue) {
280 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wrapper->_info->className() + " object";
324 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wrapper->classInfo()->className() + " object";
281 }
325 }
282 }
326 }
283
327
@@ -290,17 +334,17 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
290 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
334 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
291 QObject *qobj = wrapper->_obj;
335 QObject *qobj = wrapper->_obj;
292 if (wrapper->_wrappedPtr) {
336 if (wrapper->_wrappedPtr) {
293 QString str = PythonQtConv::CPPObjectToString(wrapper->_info->metaTypeId(), wrapper->_wrappedPtr);
337 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
294 if (!str.isEmpty()) {
338 if (!str.isEmpty()) {
295 return PyString_FromFormat("%s", str.toLatin1().constData());
339 return PyString_FromFormat("%s", str.toLatin1().constData());
296 } else
340 } else
297 if (wrapper->_obj) {
341 if (wrapper->_obj) {
298 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->_info->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
342 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
299 } else {
343 } else {
300 return PyString_FromFormat("%s (C++ Object %p)", wrapper->_info->className(), wrapper->_wrappedPtr);
344 return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr);
301 }
345 }
302 } else {
346 } else {
303 return PyString_FromFormat("%s (QObject %p)", wrapper->_info->className(), qobj);
347 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
304 }
348 }
305 }
349 }
306
350
@@ -309,24 +353,24 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
309 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
353 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
310 QObject *qobj = wrapper->_obj;
354 QObject *qobj = wrapper->_obj;
311 if (wrapper->_wrappedPtr) {
355 if (wrapper->_wrappedPtr) {
312 QString str = PythonQtConv::CPPObjectToString(wrapper->_info->metaTypeId(), wrapper->_wrappedPtr);
356 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
313 if (!str.isEmpty()) {
357 if (!str.isEmpty()) {
314 return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wrapper->_info->metaTypeId()), str.toLatin1().constData(), wrapper->_wrappedPtr);
358 return PyString_FromFormat("%s(%s, %p)", QMetaType::typeName(wrapper->classInfo()->metaTypeId()), str.toLatin1().constData(), wrapper->_wrappedPtr);
315 } else
359 } else
316 if (wrapper->_obj) {
360 if (wrapper->_obj) {
317 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->_info->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
361 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wrapper->classInfo()->className(), wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
318 } else {
362 } else {
319 return PyString_FromFormat("%s (C++ Object %p)", wrapper->_info->className(), wrapper->_wrappedPtr);
363 return PyString_FromFormat("%s (C++ Object %p)", wrapper->classInfo()->className(), wrapper->_wrappedPtr);
320 }
364 }
321 } else {
365 } else {
322 return PyString_FromFormat("%s (QObject %p)", wrapper->_info->className(), qobj);
366 return PyString_FromFormat("%s (QObject %p)", wrapper->classInfo()->className(), qobj);
323 }
367 }
324 }
368 }
325
369
326 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
370 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
327 {
371 {
328 if (obj1->ob_type == &PythonQtInstanceWrapper_Type &&
372 if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) &&
329 obj2->ob_type == &PythonQtInstanceWrapper_Type) {
373 PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) {
330
374
331 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
375 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
332 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
376 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
@@ -338,11 +382,11 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
338 } else if (w1->_obj == w2->_obj) {
382 } else if (w1->_obj == w2->_obj) {
339 return 0;
383 return 0;
340 }
384 }
341 const char* class1 = w1->_info->className();
385 const char* class1 = w1->classInfo()->className();
342 const char* class2 = w2->_info->className();
386 const char* class2 = w2->classInfo()->className();
343 if (strcmp(class1, class2) == 0) {
387 if (strcmp(class1, class2) == 0) {
344 // same class names, so we can try the operator_equal
388 // same class names, so we can try the operator_equal
345 PythonQtMemberInfo info = w1->_info->member("operator_equal");
389 PythonQtMemberInfo info = w1->classInfo()->member("operator_equal");
346 if (info._type == PythonQtMemberInfo::Slot) {
390 if (info._type == PythonQtMemberInfo::Slot) {
347 bool result = false;
391 bool result = false;
348 void* obj1 = w1->_wrappedPtr;
392 void* obj1 = w1->_wrappedPtr;
@@ -440,7 +484,7 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
440 };
484 };
441
485
442 PyTypeObject PythonQtInstanceWrapper_Type = {
486 PyTypeObject PythonQtInstanceWrapper_Type = {
443 PyObject_HEAD_INIT(NULL)
487 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
444 0, /*ob_size*/
488 0, /*ob_size*/
445 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
489 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
446 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
490 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
@@ -62,6 +62,9 extern PYTHONQT_EXPORT PyTypeObject PythonQtInstanceWrapper_Type;
62 typedef struct {
62 typedef struct {
63 PyObject_HEAD
63 PyObject_HEAD
64
64
65 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
66 PythonQtClassInfo* classInfo();
67
65 //! set the QObject pointer
68 //! set the QObject pointer
66 void setQObject(QObject* object) {
69 void setQObject(QObject* object) {
67 _obj = object;
70 _obj = object;
@@ -77,9 +80,6 typedef struct {
77 //! optional C++ object Ptr that is wrapped by the above _obj
80 //! optional C++ object Ptr that is wrapped by the above _obj
78 void* _wrappedPtr;
81 void* _wrappedPtr;
79
82
80 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
81 PythonQtClassInfo* _info;
82
83 //! flag that stores if the object is owned by pythonQt
83 //! flag that stores if the object is owned by pythonQt
84 bool _ownedByPythonQt;
84 bool _ownedByPythonQt;
85
85
@@ -50,10 +50,13
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument)
53 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
57 if (directReturnValuePointer) {
58 *directReturnValuePointer = NULL;
59 }
57 // store the current storage position, so that we can get back to this state after a slot is called
60 // store the current storage position, so that we can get back to this state after a slot is called
58 // (do this locally, so that we have all positions on the stack
61 // (do this locally, so that we have all positions on the stack
59 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalValueStoragePos;
@@ -87,7 +90,13 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, P
87 }
90 }
88 if (argList[0]==NULL) {
91 if (argList[0]==NULL) {
89 // create empty default value for the return value
92 // create empty default value for the return value
90 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
93 if (!directReturnValuePointer) {
94 // create empty default value for the return value
95 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
96 } else {
97 // we can use our pointer directly!
98 argList[0] = directReturnValuePointer;
99 }
91 }
100 }
92 }
101 }
93
102
@@ -129,10 +138,14 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, P
129 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
138 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
130
139
131 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
140 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
132 if (!returnValueIsEnum) {
141 if (directReturnValuePointer) {
133 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
142 result = NULL;
134 } else {
143 } else {
135 result = PyInt_FromLong(*((unsigned int*)argList[0]));
144 if (!returnValueIsEnum) {
145 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
146 } else {
147 result = PyInt_FromLong(*((unsigned int*)argList[0]));
148 }
136 }
149 }
137 } else {
150 } else {
138 QString e = QString("Called ") + info->fullSignature(skipFirst) + ", return type is ignored because it is unknown to PythonQt.";
151 QString e = QString("Called ") + info->fullSignature(skipFirst) + ", return type is ignored because it is unknown to PythonQt.";
@@ -147,8 +160,9 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, P
147 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
160 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
148 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
161 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
149
162
163 *pythonReturnValue = result;
150 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
164 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
151 return result;
165 return result || (directReturnValuePointer && *directReturnValuePointer);
152 }
166 }
153
167
154 //-----------------------------------------------------------------------------------
168 //-----------------------------------------------------------------------------------
@@ -159,7 +173,7 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw
159 {
173 {
160 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
174 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
161 PythonQtSlotInfo* info = f->m_ml;
175 PythonQtSlotInfo* info = f->m_ml;
162 if (f->m_self->ob_type == &PythonQtInstanceWrapper_Type) {
176 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
163 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
177 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
164 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, self->_wrappedPtr);
178 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, self->_wrappedPtr);
165 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
179 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
@@ -169,7 +183,7 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw
169 }
183 }
170 }
184 }
171
185
172 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg)
186 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
173 {
187 {
174 int argc = PyTuple_Size(args);
188 int argc = PyTuple_Size(args);
175
189
@@ -178,33 +192,32 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo*
178 #endif
192 #endif
179
193
180 PyObject* r = NULL;
194 PyObject* r = NULL;
181
195 bool ok = false;
196 if (directReturnValuePointer) {
197 *directReturnValuePointer = NULL;
198 }
199
182 if (info->nextInfo()) {
200 if (info->nextInfo()) {
183 // overloaded slot call, try on all slots with strict conversion first
201 // overloaded slot call, try on all slots with strict conversion first
202 bool strict = true;
184 PythonQtSlotInfo* i = info;
203 PythonQtSlotInfo* i = info;
185 while (i && r==NULL) {
204 while (i) {
186 bool skipFirst = i->isInstanceDecorator();
205 bool skipFirst = i->isInstanceDecorator();
187 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
206 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
188 PyErr_Clear();
207 PyErr_Clear();
189 r = PythonQtCallSlot(objectToCall, args, true, i, firstArg);
208 ok = PythonQtCallSlot(objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
190 if (PyErr_Occurred()) break;
209 if (PyErr_Occurred() || ok) break;
191 }
210 }
192 i = i->nextInfo();
211 i = i->nextInfo();
193 }
212 if (!i) {
194 if (!r) {
213 if (strict) {
195 // try on all slots with non-strict conversion
214 // one more run without being strict
196 i = info;
215 strict = false;
197 while (i && r==NULL) {
216 i = info;
198 bool skipFirst = i->isInstanceDecorator();
199 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
200 PyErr_Clear();
201 r = PythonQtCallSlot(objectToCall, args, false, i, firstArg);
202 if (PyErr_Occurred()) break;
203 }
217 }
204 i = i->nextInfo();
205 }
218 }
206 }
219 }
207 if (r==NULL && !PyErr_Occurred()) {
220 if (!ok && !PyErr_Occurred()) {
208 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
221 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
209 PythonQtSlotInfo* i = info;
222 PythonQtSlotInfo* i = info;
210 while (i) {
223 while (i) {
@@ -219,8 +232,8 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo*
219 bool skipFirst = info->isInstanceDecorator();
232 bool skipFirst = info->isInstanceDecorator();
220 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
233 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
221 PyErr_Clear();
234 PyErr_Clear();
222 r = PythonQtCallSlot(objectToCall, args, false, info, firstArg);
235 ok = PythonQtCallSlot(objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
223 if (r==NULL && !PyErr_Occurred()) {
236 if (!ok && !PyErr_Occurred()) {
224 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
237 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
225 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
238 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
226 }
239 }
@@ -61,7 +61,7 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
61
61
62 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
62 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
63
63
64 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL);
64 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
65
65
66
66
67 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
67 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
General Comments 0
You need to be logged in to leave comments. Login now