@@ -170,18 +170,21 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); | |
184 |
|
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); | |||
|
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) { | |
187 | std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl; |
|
190 | std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl; | |
@@ -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 = |
|
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-> |
|
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-> |
|
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-> |
|
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. |
|
403 | info = _knownQtWrapperClasses.value(name); | |
394 | PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtClassWrapper(info)); |
|
404 | } | |
395 | } else { |
|
|||
396 |
|
|
405 | if (wrapper && (info->metaObject() != wrapper->metaObject())) { | |
397 |
|
|
406 | info->setMetaObject(wrapper->metaObject()); | |
398 |
|
|
407 | } | |
399 | } |
|
|||
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-> |
|
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-> |
|
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-> |
|
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 = |
|
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 |
|
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*/) |
|
62 | ||
|
63 | static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds) | |||
67 | { |
|
64 | { | |
68 | return 0; |
|
65 | // call the default type init | |
|
66 | if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) { | |||
|
67 | return -1; | |||
69 | } |
|
68 | } | |
70 |
|
69 | |||
71 | PyObject *PythonQtClassWrapper_call(PyObject *func, PyObject *args, PyObject *kw) { |
|
70 | // if we have no CPP class information, try our base class | |
72 | PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)func; |
|
71 | if (!self->classInfo()) { | |
73 | PyObject* result = NULL; |
|
72 | PyTypeObject* superType = ((PyTypeObject *)self)->tp_base; | |
74 | QString error; |
|
73 | ||
75 | PyObject* err = NULL; |
|
74 | if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) { | |
76 | if (wrapper->_info->constructors()) { |
|
75 | PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name); | |
77 | result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw); |
|
76 | return -1; | |
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 | } |
|
|||
90 | if (result) { |
|
|||
91 | // change ownershipflag to be owned by PythonQt |
|
|||
92 | if (result->ob_type == &PythonQtInstanceWrapper_Type) { |
|
|||
93 | ((PythonQtInstanceWrapper*)result)->_ownedByPythonQt = true; |
|
|||
94 | } |
|
|||
95 | } else { |
|
|||
96 | if (!wrapper->_info->constructors()) { |
|
|||
97 | if (!err) { |
|
|||
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(" |
|
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-> |
|
93 | return PythonQt::self()->helpCalled(type->classInfo()); | |
116 | } |
|
94 | } | |
117 |
|
95 | |||
118 |
|
96 | |||
@@ -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-> |
|
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-> |
|
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-> |
|
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-> |
|
165 | if (wrapper->classInfo()->isCPPWrapper()) { | |
174 |
const QMetaObject* meta = wrapper-> |
|
166 | const QMetaObject* meta = wrapper->classInfo()->metaObject(); | |
175 | if (!meta) { |
|
167 | if (!meta) { | |
176 |
QObject* decorator = wrapper-> |
|
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-> |
|
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 |
|
|
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 |
|
|
200 | 0, /*tp_hash */ | |
229 |
|
|
201 | 0, /*tp_call*/ | |
230 | 0, /*tp_str*/ |
|
202 | 0, /*tp_str*/ | |
231 | PythonQtClassWrapper_getattro, /*tp_getattro*/ |
|
203 | PythonQtClassWrapper_getattro, /*tp_getattro*/ | |
232 |
|
|
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 |
|
|
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 |
|
|
223 | PythonQtClassWrapper_alloc, /* tp_alloc */ | |
252 |
|
|
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 |
|
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* _ |
|
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 |
|
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 |
|
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-> |
|
233 | if (wrap->classInfo()->inherits(info.name)) { | |
234 | void* object; |
|
234 | void* object; | |
235 |
if (wrap-> |
|
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 |
|
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-> |
|
696 | if (wrap->classInfo()->isCPPWrapper()) { | |
697 |
if (wrap-> |
|
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-> |
|
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 |
|
852 | if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) { | |
853 | PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val; |
|
853 | PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val; | |
854 |
if (wrap-> |
|
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 |
|
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-> |
|
962 | if (wrap->classInfo()->inherits(type)) { | |
963 |
if (wrap-> |
|
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-> |
|
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-> |
|
66 | if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) { | |
60 |
int type = self-> |
|
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-> |
|
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-> |
|
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 * |
|
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 * |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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-> |
|
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 |
|
372 | if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) && | |
329 |
obj2 |
|
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-> |
|
385 | const char* class1 = w1->classInfo()->className(); | |
342 |
const char* class2 = w2-> |
|
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-> |
|
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 |
|
|
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 | |
|
93 | if (!directReturnValuePointer) { | |||
|
94 | // create empty default value for the return value | |||
90 | argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam); |
|
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,11 +138,15 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) { | |
|
141 | if (directReturnValuePointer) { | |||
|
142 | result = NULL; | |||
|
143 | } else { | |||
132 | if (!returnValueIsEnum) { |
|
144 | if (!returnValueIsEnum) { | |
133 | result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]); |
|
145 | result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]); | |
134 | } else { |
|
146 | } else { | |
135 | result = PyInt_FromLong(*((unsigned int*)argList[0])); |
|
147 | result = PyInt_FromLong(*((unsigned int*)argList[0])); | |
136 | } |
|
148 | } | |
|
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."; | |
139 | PyErr_SetString(PyExc_ValueError, e.toLatin1().data()); |
|
152 | PyErr_SetString(PyExc_ValueError, e.toLatin1().data()); | |
@@ -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 |
|
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; | |
|
195 | bool ok = false; | |||
|
196 | if (directReturnValuePointer) { | |||
|
197 | *directReturnValuePointer = NULL; | |||
|
198 | } | |||
181 |
|
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 |
|
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 |
|
|
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 ( |
|
213 | if (strict) { | |
195 | // try on all slots with non-strict conversion |
|
214 | // one more run without being strict | |
|
215 | strict = false; | |||
196 | i = info; |
|
216 | i = info; | |
197 | while (i && r==NULL) { |
|
|||
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 ( |
|
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 |
|
|
235 | ok = PythonQtCallSlot(objectToCall, args, false, info, firstArg, &r, directReturnValuePointer); | |
223 |
if ( |
|
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