@@ -78,11 +78,12 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName) | |||||
78 | PythonQtRegisterToolClassesTemplateConverter(quint64); |
|
78 | PythonQtRegisterToolClassesTemplateConverter(quint64); | |
79 | // TODO: which other POD types should be available for QList etc. |
|
79 | // TODO: which other POD types should be available for QList etc. | |
80 |
|
80 | |||
81 | PythonQt::self()->addDecorators(new PythonQtStdDecorators()); |
|
|||
82 |
|
||||
83 | PythonQt_init_QtCoreBuiltin(NULL); |
|
81 | PythonQt_init_QtCoreBuiltin(NULL); | |
84 | PythonQt_init_QtGuiBuiltin(NULL); |
|
82 | PythonQt_init_QtGuiBuiltin(NULL); | |
85 |
|
83 | |||
|
84 | PythonQt::self()->addDecorators(new PythonQtStdDecorators()); | |||
|
85 | PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>); | |||
|
86 | ||||
86 | PythonQtRegisterToolClassesTemplateConverter(QByteArray); |
|
87 | PythonQtRegisterToolClassesTemplateConverter(QByteArray); | |
87 | PythonQtRegisterToolClassesTemplateConverter(QDate); |
|
88 | PythonQtRegisterToolClassesTemplateConverter(QDate); | |
88 | PythonQtRegisterToolClassesTemplateConverter(QTime); |
|
89 | PythonQtRegisterToolClassesTemplateConverter(QTime); | |
@@ -919,6 +920,13 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) | |||||
919 | } |
|
920 | } | |
920 | Py_DECREF(keys); |
|
921 | Py_DECREF(keys); | |
921 | } |
|
922 | } | |
|
923 | if ((type == Anything) || (type == Variable)) { | |||
|
924 | if (object->ob_type == &PythonQtClassWrapper_Type) { | |||
|
925 | PythonQtClassWrapper* o = (PythonQtClassWrapper*)object; | |||
|
926 | PythonQtClassInfo* info = o->classInfo(); | |||
|
927 | results += info->propertyList(); | |||
|
928 | } | |||
|
929 | } | |||
922 | } |
|
930 | } | |
923 | return results; |
|
931 | return results; | |
924 | } |
|
932 | } | |
@@ -958,7 +966,13 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type) | |||||
958 | // the last item may be a member, split it away and try again |
|
966 | // the last item may be a member, split it away and try again | |
959 | QStringList tmp = typeName.split("."); |
|
967 | QStringList tmp = typeName.split("."); | |
960 | QString memberName = tmp.takeLast(); |
|
968 | QString memberName = tmp.takeLast(); | |
961 |
QString typeName |
|
969 | QString typeName; | |
|
970 | if (tmp.isEmpty()) { | |||
|
971 | typeName = memberName; | |||
|
972 | memberName.clear(); | |||
|
973 | } else { | |||
|
974 | typeName = tmp.takeLast(); | |||
|
975 | } | |||
962 | PyObject* typeObject = getObjectByType(typeName); |
|
976 | PyObject* typeObject = getObjectByType(typeName); | |
963 | if (typeObject) { |
|
977 | if (typeObject) { | |
964 | object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData()); |
|
978 | object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData()); | |
@@ -1690,3 +1704,18 QString PythonQtPrivate::getSignature(PyObject* object) | |||||
1690 |
|
1704 | |||
1691 | return signature; |
|
1705 | return signature; | |
1692 | } |
|
1706 | } | |
|
1707 | ||||
|
1708 | void PythonQtPrivate::shellClassDeleted( void* shellClass ) | |||
|
1709 | { | |||
|
1710 | PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass); | |||
|
1711 | if (wrap && wrap->_wrappedPtr) { | |||
|
1712 | // this is a pure C++ wrapper and the shell has gone, so we need | |||
|
1713 | // to set the _wrappedPtr to NULL on the wrapper | |||
|
1714 | wrap->_wrappedPtr = NULL; | |||
|
1715 | // and then we remove the wrapper, since the wrapped class is gone | |||
|
1716 | _wrappedObjects.remove(shellClass); | |||
|
1717 | } | |||
|
1718 | // if the wrapper is a QObject, we do not handle this here, | |||
|
1719 | // it will be handled by the QPointer<> to the QObject, which becomes NULL | |||
|
1720 | // via the QObject destructor. | |||
|
1721 | } No newline at end of file |
@@ -563,6 +563,9 public: | |||||
563 | //! remove the wrapper ptr again |
|
563 | //! remove the wrapper ptr again | |
564 | void removeWrapperPointer(void* obj); |
|
564 | void removeWrapperPointer(void* obj); | |
565 |
|
565 | |||
|
566 | //! called by destructor of shells to allow invalidation of the Python wrapper | |||
|
567 | void shellClassDeleted(void* shellClass); | |||
|
568 | ||||
566 | //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories |
|
569 | //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories | |
567 | void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); |
|
570 | void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); | |
568 |
|
571 |
@@ -205,46 +205,53 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con | |||||
205 | } |
|
205 | } | |
206 |
|
206 | |||
207 | tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset); |
|
207 | tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset); | |
208 |
|
||||
209 | return tail; |
|
|||
210 | } |
|
|||
211 |
|
208 | |||
212 | bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) |
|
209 | // now look for slots/signals/methods on this level of the meta object | |
213 | { |
|
|||
214 | bool found = false; |
|
|||
215 | int memberNameLen = static_cast<int>(strlen(memberName)); |
|
|||
216 | PythonQtSlotInfo* tail = NULL; |
|
|||
217 | if (_meta) { |
|
210 | if (_meta) { | |
218 | int numMethods = _meta->methodCount(); |
|
211 | int numMethods = _meta->methodCount(); | |
219 | for (int i = 0; i < numMethods; i++) { |
|
212 | // start from methodOffset, to only add slots which are located in this class, | |
|
213 | // and not in the parent class, which is traversed recursively later on. | |||
|
214 | // (if the class in not a QObject, we are working with a script wrapper QObject | |||
|
215 | // and need to read all slots/signals starting from 0). | |||
|
216 | int methodOffset = _isQObject?_meta->methodOffset():0; | |||
|
217 | for (int i = methodOffset; i < numMethods; i++) { | |||
220 | QMetaMethod m = _meta->method(i); |
|
218 | QMetaMethod m = _meta->method(i); | |
221 | if (((m.methodType() == QMetaMethod::Method || |
|
219 | if (((m.methodType() == QMetaMethod::Method || | |
222 |
|
|
220 | m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) | |
223 | || m.methodType()==QMetaMethod::Signal) { |
|
221 | || m.methodType()==QMetaMethod::Signal) { | |
224 |
|
222 | |||
225 | const char* sigStart = m.signature(); |
|
223 | const char* sigStart = m.signature(); | |
226 | // find the first '(' |
|
224 | // find the first '(' | |
227 | int offset = findCharOffset(sigStart, '('); |
|
225 | int offset = findCharOffset(sigStart, '('); | |
228 |
|
226 | |||
229 | // check if same length and same name |
|
227 | // check if same length and same name | |
230 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { |
|
228 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { | |
231 | found = true; |
|
229 | found = true; | |
232 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); |
|
230 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); | |
233 | if (tail) { |
|
231 | if (tail) { | |
234 | tail->setNextInfo(info); |
|
232 | tail->setNextInfo(info); | |
235 | } else { |
|
233 | } else { | |
236 | PythonQtMemberInfo newInfo(info); |
|
234 | PythonQtMemberInfo newInfo(info); | |
237 |
|
|
235 | memberCache.insert(memberName, newInfo); | |
|
236 | } | |||
|
237 | tail = info; | |||
238 | } |
|
238 | } | |
239 | tail = info; |
|
|||
240 | } |
|
|||
241 | } |
|
239 | } | |
242 | } |
|
240 | } | |
243 | } |
|
241 | } | |
|
242 | return tail; | |||
|
243 | } | |||
|
244 | ||||
|
245 | bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) | |||
|
246 | { | |||
|
247 | bool found = false; | |||
|
248 | PythonQtSlotInfo* tail = NULL; | |||
244 |
|
249 | |||
245 | // look for dynamic decorators in this class and in derived classes |
|
250 | // look for dynamic decorators in this class and in derived classes | |
|
251 | // (do this first to allow overloading of existing slots with generated wrappers, | |||
|
252 | // e.g. QDialog::accept is overloaded with PythonQtWrapper_QDialog::accept decorator) | |||
246 | tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0); |
|
253 | tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0); | |
247 |
|
254 | |||
248 |
|
|
255 | return found; | |
249 | } |
|
256 | } | |
250 |
|
257 | |||
@@ -710,22 +717,6 QObject* PythonQtClassInfo::decorator() | |||||
710 | return _decoratorProvider; |
|
717 | return _decoratorProvider; | |
711 | } |
|
718 | } | |
712 |
|
719 | |||
713 | bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object) |
|
|||
714 | { |
|
|||
715 | PythonQtMemberInfo info = member("py_hasOwner"); |
|
|||
716 | if (info._type == PythonQtMemberInfo::Slot) { |
|
|||
717 | void* obj = object; |
|
|||
718 | bool result = false; |
|
|||
719 | void* args[2]; |
|
|||
720 | args[0] = &result; |
|
|||
721 | args[1] = &obj; |
|
|||
722 | info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args); |
|
|||
723 | return !result; |
|
|||
724 | } else { |
|
|||
725 | return false; |
|
|||
726 | } |
|
|||
727 | } |
|
|||
728 |
|
||||
729 | void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName) |
|
720 | void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName) | |
730 | { |
|
721 | { | |
731 | if (!_polymorphicHandlers.isEmpty()) { |
|
722 | if (!_polymorphicHandlers.isEmpty()) { |
@@ -159,9 +159,6 public: | |||||
159 | //! add the parent class info of a CPP object |
|
159 | //! add the parent class info of a CPP object | |
160 | void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); } |
|
160 | void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); } | |
161 |
|
161 | |||
162 | //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed |
|
|||
163 | bool hasOwnerMethodButNoOwner(void* object); |
|
|||
164 |
|
||||
165 | //! set the associated PythonQtClassWrapper (which handles instance creation of this type) |
|
162 | //! set the associated PythonQtClassWrapper (which handles instance creation of this type) | |
166 | void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; } |
|
163 | void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; } | |
167 |
|
164 |
@@ -377,11 +377,32 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i | |||||
377 | // a pointer |
|
377 | // a pointer | |
378 | if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) |
|
378 | if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) | |
379 | { |
|
379 | { | |
|
380 | if (obj->ob_type == &PyString_Type) { | |||
|
381 | // take direct reference to string data | |||
|
382 | const char* data = PyString_AS_STRING(obj); | |||
|
383 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr); | |||
|
384 | } else { | |||
|
385 | // convert to string | |||
|
386 | QString str = PyObjGetString(obj, strict, ok); | |||
|
387 | if (ok) { | |||
|
388 | QByteArray bytes; | |||
|
389 | bytes = str.toUtf8(); | |||
|
390 | if (ok) { | |||
|
391 | void* ptr2 = NULL; | |||
|
392 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2); | |||
|
393 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr); | |||
|
394 | } | |||
|
395 | } | |||
|
396 | } | |||
|
397 | } else if (info.typeId == QMetaType::QString) { | |||
|
398 | // TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName | |||
|
399 | // In general we would need to decide to either support * args for all basic types (ignoring the fact that the | |||
|
400 | // result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do. | |||
380 | QString str = PyObjGetString(obj, strict, ok); |
|
401 | QString str = PyObjGetString(obj, strict, ok); | |
381 | if (ok) { |
|
402 | if (ok) { | |
382 | void* ptr2 = NULL; |
|
403 | void* ptr2 = NULL; | |
383 |
PythonQtValueStorage_ADD_VALUE_IF_NEEDED( |
|
404 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2); | |
384 |
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, ( |
|
405 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr); | |
385 | } |
|
406 | } | |
386 | } else if (info.name == "PyObject") { |
|
407 | } else if (info.name == "PyObject") { | |
387 | // handle low level PyObject directly |
|
408 | // handle low level PyObject directly | |
@@ -746,7 +767,13 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { | |||||
746 | } else if (val == Py_True) { |
|
767 | } else if (val == Py_True) { | |
747 | d = 1; |
|
768 | d = 1; | |
748 | } else { |
|
769 | } else { | |
749 | ok = false; |
|
770 | PyErr_Clear(); | |
|
771 | // PyInt_AsLong will try conversion to an int if the object is not an int: | |||
|
772 | d = PyInt_AsLong(val); | |||
|
773 | if (PyErr_Occurred()) { | |||
|
774 | ok = false; | |||
|
775 | PyErr_Clear(); | |||
|
776 | } | |||
750 | } |
|
777 | } | |
751 | } else { |
|
778 | } else { | |
752 | ok = false; |
|
779 | ok = false; | |
@@ -772,7 +799,13 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) { | |||||
772 | } else if (val == Py_True) { |
|
799 | } else if (val == Py_True) { | |
773 | d = 1; |
|
800 | d = 1; | |
774 | } else { |
|
801 | } else { | |
775 | ok = false; |
|
802 | PyErr_Clear(); | |
|
803 | // PyLong_AsLongLong will try conversion to an int if the object is not an int: | |||
|
804 | d = PyLong_AsLongLong(val); | |||
|
805 | if (PyErr_Occurred()) { | |||
|
806 | ok = false; | |||
|
807 | PyErr_Clear(); | |||
|
808 | } | |||
776 | } |
|
809 | } | |
777 | } else { |
|
810 | } else { | |
778 | ok = false; |
|
811 | ok = false; | |
@@ -798,7 +831,13 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) { | |||||
798 | } else if (val == Py_True) { |
|
831 | } else if (val == Py_True) { | |
799 | d = 1; |
|
832 | d = 1; | |
800 | } else { |
|
833 | } else { | |
801 | ok = false; |
|
834 | PyErr_Clear(); | |
|
835 | // PyLong_AsLongLong will try conversion to an int if the object is not an int: | |||
|
836 | d = PyLong_AsLongLong(val); | |||
|
837 | if (PyErr_Occurred()) { | |||
|
838 | PyErr_Clear(); | |||
|
839 | ok = false; | |||
|
840 | } | |||
802 | } |
|
841 | } | |
803 | } else { |
|
842 | } else { | |
804 | ok = false; |
|
843 | ok = false; | |
@@ -821,7 +860,13 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) { | |||||
821 | } else if (val == Py_True) { |
|
860 | } else if (val == Py_True) { | |
822 | d = 1; |
|
861 | d = 1; | |
823 | } else { |
|
862 | } else { | |
824 | ok = false; |
|
863 | PyErr_Clear(); | |
|
864 | // PyFloat_AsDouble will try conversion to a double if the object is not a float: | |||
|
865 | d = PyFloat_AsDouble(val); | |||
|
866 | if (PyErr_Occurred()) { | |||
|
867 | PyErr_Clear(); | |||
|
868 | ok = false; | |||
|
869 | } | |||
825 | } |
|
870 | } | |
826 | } else { |
|
871 | } else { | |
827 | ok = false; |
|
872 | ok = false; |
@@ -64,7 +64,7 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, | |||||
64 | // we own our qobject, so we delete it now: |
|
64 | // we own our qobject, so we delete it now: | |
65 | delete self->_obj; |
|
65 | delete self->_obj; | |
66 | self->_obj = NULL; |
|
66 | self->_obj = NULL; | |
67 | if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) { |
|
67 | if (force || self->_ownedByPythonQt) { | |
68 | int type = self->classInfo()->metaTypeId(); |
|
68 | int type = self->classInfo()->metaTypeId(); | |
69 | if (self->_useQMetaTypeDestroy && type>=0) { |
|
69 | if (self->_useQMetaTypeDestroy && type>=0) { | |
70 | // use QMetaType to destroy the object |
|
70 | // use QMetaType to destroy the object |
@@ -197,6 +197,31 int PythonQtMethodInfo::nameToType(const char* name) | |||||
197 | _parameterTypeDict.insert("QString", QMetaType::QString); |
|
197 | _parameterTypeDict.insert("QString", QMetaType::QString); | |
198 | _parameterTypeDict.insert("", QMetaType::Void); |
|
198 | _parameterTypeDict.insert("", QMetaType::Void); | |
199 | _parameterTypeDict.insert("void", QMetaType::Void); |
|
199 | _parameterTypeDict.insert("void", QMetaType::Void); | |
|
200 | ||||
|
201 | // GL types | |||
|
202 | _parameterTypeDict.insert("GLenum", QMetaType::UInt); | |||
|
203 | _parameterTypeDict.insert("GLboolean", QMetaType::UChar); | |||
|
204 | _parameterTypeDict.insert("GLbitfield", QMetaType::UInt); | |||
|
205 | _parameterTypeDict.insert("GLbyte", QMetaType::Char); | |||
|
206 | _parameterTypeDict.insert("GLubyte", QMetaType::UChar); | |||
|
207 | _parameterTypeDict.insert("GLshort", QMetaType::Short); | |||
|
208 | _parameterTypeDict.insert("GLushort", QMetaType::UShort); | |||
|
209 | _parameterTypeDict.insert("GLint", QMetaType::Int); | |||
|
210 | _parameterTypeDict.insert("GLuint", QMetaType::UInt); | |||
|
211 | _parameterTypeDict.insert("GLsizei", QMetaType::UInt); | |||
|
212 | _parameterTypeDict.insert("GLclampf", QMetaType::Float); | |||
|
213 | _parameterTypeDict.insert("GLfloat", QMetaType::Float); | |||
|
214 | _parameterTypeDict.insert("GLclampd", QMetaType::Double); | |||
|
215 | _parameterTypeDict.insert("GLdouble", QMetaType::Double); | |||
|
216 | _parameterTypeDict.insert("GLvoid", QMetaType::Void); | |||
|
217 | if (QT_POINTER_SIZE == 8) { | |||
|
218 | _parameterTypeDict.insert("qgl_GLintptr", QMetaType::LongLong); | |||
|
219 | _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::LongLong); | |||
|
220 | } else { | |||
|
221 | _parameterTypeDict.insert("qgl_GLintptr", QMetaType::Int); | |||
|
222 | _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::Int); | |||
|
223 | } | |||
|
224 | ||||
200 | // QVariant names |
|
225 | // QVariant names | |
201 | _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong); |
|
226 | _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong); | |
202 | _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong); |
|
227 | _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong); |
@@ -47,6 +47,10 | |||||
47 | #include <QMetaMethod> |
|
47 | #include <QMetaMethod> | |
48 | #include "funcobject.h" |
|
48 | #include "funcobject.h" | |
49 |
|
49 | |||
|
50 | // use -2 to signal that the variable is uninitialized | |||
|
51 | int PythonQtSignalReceiver::_destroyedSignal1Id = -2; | |||
|
52 | int PythonQtSignalReceiver::_destroyedSignal2Id = -2; | |||
|
53 | ||||
50 | void PythonQtSignalTarget::call(void **arguments) const { |
|
54 | void PythonQtSignalTarget::call(void **arguments) const { | |
51 | PyObject* result = call(_callable, methodInfo(), arguments); |
|
55 | PyObject* result = call(_callable, methodInfo(), arguments); | |
52 | if (result) { |
|
56 | if (result) { | |
@@ -141,6 +145,16 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const | |||||
141 |
|
145 | |||
142 | PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj) |
|
146 | PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj) | |
143 | { |
|
147 | { | |
|
148 | if (_destroyedSignal1Id == -2) { | |||
|
149 | // initialize these once | |||
|
150 | _destroyedSignal1Id = QObject::staticMetaObject.indexOfSignal("destroyed()"); | |||
|
151 | _destroyedSignal2Id = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); | |||
|
152 | if (_destroyedSignal1Id == -1 || _destroyedSignal2Id == -1) { | |||
|
153 | std::cerr << "PythonQt: could not find destroyed signal index, should never happen!" << std::endl; | |||
|
154 | } | |||
|
155 | } | |||
|
156 | ||||
|
157 | _destroyedSignalCount = 0; | |||
144 | _obj = obj; |
|
158 | _obj = obj; | |
145 |
|
159 | |||
146 | // fetch the class info for object, since we will need to for correct enum resolution in |
|
160 | // fetch the class info for object, since we will need to for correct enum resolution in | |
@@ -177,13 +191,22 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* call | |||||
177 |
|
191 | |||
178 | _slotCount++; |
|
192 | _slotCount++; | |
179 | flag = true; |
|
193 | flag = true; | |
|
194 | ||||
|
195 | if (sigId == _destroyedSignal1Id || sigId == _destroyedSignal2Id) { | |||
|
196 | _destroyedSignalCount++; | |||
|
197 | if (_destroyedSignalCount==1) { | |||
|
198 | // make ourself parent of PythonQt, to not get deleted as a child of the QObject we are | |||
|
199 | // listening to, since we do that manually when we receive the destroyed signal | |||
|
200 | this->setParent(PythonQt::priv()); | |||
|
201 | } | |||
|
202 | } | |||
180 | } |
|
203 | } | |
181 | return flag; |
|
204 | return flag; | |
182 | } |
|
205 | } | |
183 |
|
206 | |||
184 | bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable) |
|
207 | bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable) | |
185 | { |
|
208 | { | |
186 | bool found = false; |
|
209 | int foundCount = 0; | |
187 | int sigId = getSignalIndex(signal); |
|
210 | int sigId = getSignalIndex(signal); | |
188 | if (sigId>=0) { |
|
211 | if (sigId>=0) { | |
189 | QMutableListIterator<PythonQtSignalTarget> i(_targets); |
|
212 | QMutableListIterator<PythonQtSignalTarget> i(_targets); | |
@@ -191,7 +214,7 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c | |||||
191 | while (i.hasNext()) { |
|
214 | while (i.hasNext()) { | |
192 | if (i.next().isSame(sigId, callable)) { |
|
215 | if (i.next().isSame(sigId, callable)) { | |
193 | i.remove(); |
|
216 | i.remove(); | |
194 |
found |
|
217 | foundCount++; | |
195 | break; |
|
218 | break; | |
196 | } |
|
219 | } | |
197 | } |
|
220 | } | |
@@ -199,17 +222,19 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c | |||||
199 | while (i.hasNext()) { |
|
222 | while (i.hasNext()) { | |
200 | if (i.next().signalId() == sigId) { |
|
223 | if (i.next().signalId() == sigId) { | |
201 | i.remove(); |
|
224 | i.remove(); | |
202 |
found |
|
225 | foundCount++; | |
203 | } |
|
226 | } | |
204 | } |
|
227 | } | |
205 | } |
|
228 | } | |
206 | } |
|
229 | } | |
207 | return found; |
|
230 | if ((foundCount>0) && (sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) { | |
208 | } |
|
231 | _destroyedSignalCount -= foundCount; | |
209 |
|
232 | if (_destroyedSignalCount==0) { | ||
210 | void PythonQtSignalReceiver::removeSignalHandlers() |
|
233 | // make ourself child of QObject again, to get deleted when the object gets deleted | |
211 | { |
|
234 | this->setParent(_obj); | |
212 | _targets.clear(); |
|
235 | } | |
|
236 | } | |||
|
237 | return foundCount>0; | |||
213 | } |
|
238 | } | |
214 |
|
239 | |||
215 | int PythonQtSignalReceiver::getSignalIndex(const char* signal) |
|
240 | int PythonQtSignalReceiver::getSignalIndex(const char* signal) | |
@@ -229,11 +254,17 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **argu | |||||
229 | QObject::qt_metacall(c, id, arguments); |
|
254 | QObject::qt_metacall(c, id, arguments); | |
230 | } |
|
255 | } | |
231 |
|
256 | |||
232 | bool found = false; |
|
|||
233 | foreach(const PythonQtSignalTarget& t, _targets) { |
|
257 | foreach(const PythonQtSignalTarget& t, _targets) { | |
234 | if (t.slotId() == id) { |
|
258 | if (t.slotId() == id) { | |
235 | found = true; |
|
|||
236 | t.call(arguments); |
|
259 | t.call(arguments); | |
|
260 | // if the signal is the last destroyed signal, we delete ourselves | |||
|
261 | int sigId = t.signalId(); | |||
|
262 | if ((sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) { | |||
|
263 | _destroyedSignalCount--; | |||
|
264 | if (_destroyedSignalCount == 0) { | |||
|
265 | delete this; | |||
|
266 | } | |||
|
267 | } | |||
237 | break; |
|
268 | break; | |
238 | } |
|
269 | } | |
239 | } |
|
270 | } |
@@ -121,9 +121,6 public: | |||||
121 | //! remove a signal handler for given callable (or all callables on that signal if callable is NULL) |
|
121 | //! remove a signal handler for given callable (or all callables on that signal if callable is NULL) | |
122 | bool removeSignalHandler(const char* signal, PyObject* callable = NULL); |
|
122 | bool removeSignalHandler(const char* signal, PyObject* callable = NULL); | |
123 |
|
123 | |||
124 | //! remove all signal handlers |
|
|||
125 | void removeSignalHandlers(); |
|
|||
126 |
|
||||
127 | //! we implement this method to simulate a number of slots that match the ids in _targets |
|
124 | //! we implement this method to simulate a number of slots that match the ids in _targets | |
128 | virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments); |
|
125 | virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments); | |
129 |
|
126 | |||
@@ -134,8 +131,12 private: | |||||
134 | QObject* _obj; |
|
131 | QObject* _obj; | |
135 | PythonQtClassInfo* _objClassInfo; |
|
132 | PythonQtClassInfo* _objClassInfo; | |
136 | int _slotCount; |
|
133 | int _slotCount; | |
|
134 | int _destroyedSignalCount; | |||
137 | // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals |
|
135 | // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals | |
138 | QList<PythonQtSignalTarget> _targets; |
|
136 | QList<PythonQtSignalTarget> _targets; | |
|
137 | ||||
|
138 | static int _destroyedSignal1Id; | |||
|
139 | static int _destroyedSignal2Id; | |||
139 | }; |
|
140 | }; | |
140 |
|
141 | |||
141 |
|
142 |
@@ -66,7 +66,7 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, P | |||||
66 | return result; |
|
66 | return result; | |
67 | } |
|
67 | } | |
68 |
|
68 | |||
69 | bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) |
|
69 | bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type) | |
70 | { |
|
70 | { | |
71 | bool r = false; |
|
71 | bool r = false; | |
72 | if (sender && receiver) { |
|
72 | if (sender && receiver) { | |
@@ -85,7 +85,7 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, Q | |||||
85 | } else { |
|
85 | } else { | |
86 | slotTmp = "1" + slot; |
|
86 | slotTmp = "1" + slot; | |
87 | } |
|
87 | } | |
88 | r = QObject::connect(sender, signalTmp, receiver, slotTmp); |
|
88 | r = QObject::connect(sender, signalTmp, receiver, slotTmp, type); | |
89 | } |
|
89 | } | |
90 | return r; |
|
90 | return r; | |
91 | } |
|
91 | } | |
@@ -316,3 +316,8 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, c | |||||
316 |
|
316 | |||
317 | return 0; |
|
317 | return 0; | |
318 | } |
|
318 | } | |
|
319 | ||||
|
320 | const QMetaObject* PythonQtStdDecorators::metaObject( QObject* obj ) | |||
|
321 | { | |||
|
322 | return obj->metaObject(); | |||
|
323 | } No newline at end of file |
@@ -53,6 +53,10 | |||||
53 | #include <QDateTime> |
|
53 | #include <QDateTime> | |
54 | #include <QDate> |
|
54 | #include <QDate> | |
55 | #include <QTime> |
|
55 | #include <QTime> | |
|
56 | #include <QImage> | |||
|
57 | #include <QMetaMethod> | |||
|
58 | #include <QMetaEnum> | |||
|
59 | #include <QMetaProperty> | |||
56 |
|
60 | |||
57 | class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject |
|
61 | class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject | |
58 | { |
|
62 | { | |
@@ -60,9 +64,16 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject | |||||
60 |
|
64 | |||
61 | public slots: |
|
65 | public slots: | |
62 | bool connect(QObject* sender, const QByteArray& signal, PyObject* callable); |
|
66 | bool connect(QObject* sender, const QByteArray& signal, PyObject* callable); | |
63 | bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot); |
|
67 | bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection); | |
|
68 | bool connect(QObject* receiver, QObject* sender, const QByteArray& signal, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); } | |||
|
69 | bool static_QObject_connect(QObject* sender, const QByteArray& signal, PyObject* callable) { return connect(sender, signal, callable); } | |||
|
70 | bool static_QObject_connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); } | |||
64 | bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL); |
|
71 | bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL); | |
65 | bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot); |
|
72 | bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot); | |
|
73 | bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL) { return disconnect(sender, signal, callable); } | |||
|
74 | bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return connect(sender, signal, receiver, slot); } | |||
|
75 | ||||
|
76 | const QMetaObject* metaObject( QObject* obj ); | |||
66 |
|
77 | |||
67 | QObject* parent(QObject* o); |
|
78 | QObject* parent(QObject* o); | |
68 | void setParent(QObject* o, QObject* parent); |
|
79 | void setParent(QObject* o, QObject* parent); | |
@@ -105,5 +116,44 private: | |||||
105 | int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list); |
|
116 | int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list); | |
106 | }; |
|
117 | }; | |
107 |
|
118 | |||
|
119 | class PythonQtWrapper_QMetaObject : public QObject | |||
|
120 | { | |||
|
121 | Q_OBJECT | |||
|
122 | ||||
|
123 | public slots: | |||
|
124 | const char *className(QMetaObject* obj) const { return obj->className(); } | |||
|
125 | const QMetaObject *superClass(QMetaObject* obj) const { return obj->superClass(); } | |||
|
126 | ||||
|
127 | int methodOffset(QMetaObject* obj) const { return obj->methodOffset(); } | |||
|
128 | int enumeratorOffset(QMetaObject* obj) const { return obj->enumeratorOffset(); } | |||
|
129 | int propertyOffset(QMetaObject* obj) const { return obj->propertyOffset(); } | |||
|
130 | int classInfoOffset(QMetaObject* obj) const { return obj->classInfoOffset(); } | |||
|
131 | ||||
|
132 | int constructorCount(QMetaObject* obj) const { return obj->constructorCount(); } | |||
|
133 | int methodCount(QMetaObject* obj) const { return obj->methodCount(); } | |||
|
134 | int enumeratorCount(QMetaObject* obj) const { return obj->enumeratorCount(); } | |||
|
135 | int propertyCount(QMetaObject* obj) const { return obj->propertyCount(); } | |||
|
136 | int classInfoCount(QMetaObject* obj) const { return obj->classInfoCount(); } | |||
|
137 | ||||
|
138 | int indexOfConstructor(QMetaObject* obj, const char *constructor) const { return obj->indexOfConstructor(constructor); } | |||
|
139 | int indexOfMethod(QMetaObject* obj, const char *method) const { return obj->indexOfMethod(method); } | |||
|
140 | int indexOfSignal(QMetaObject* obj, const char *signal) const { return obj->indexOfSignal(signal); } | |||
|
141 | int indexOfSlot(QMetaObject* obj, const char *slot) const { return obj->indexOfSlot(slot); } | |||
|
142 | int indexOfEnumerator(QMetaObject* obj, const char *name) const { return obj->indexOfEnumerator(name); } | |||
|
143 | int indexOfProperty(QMetaObject* obj, const char *name) const { return obj->indexOfProperty(name); } | |||
|
144 | int indexOfClassInfo(QMetaObject* obj, const char *name) const { return obj->indexOfClassInfo(name); } | |||
|
145 | ||||
|
146 | QMetaMethod constructor(QMetaObject* obj, int index) const { return obj->constructor(index); } | |||
|
147 | QMetaMethod method(QMetaObject* obj, int index) const { return obj->method(index); } | |||
|
148 | QMetaEnum enumerator(QMetaObject* obj, int index) const { return obj->enumerator(index); } | |||
|
149 | QMetaProperty property(QMetaObject* obj, int index) const { return obj->property(index); } | |||
|
150 | QMetaClassInfo classInfo(QMetaObject* obj, int index) const { return obj->classInfo(index); } | |||
|
151 | QMetaProperty userProperty(QMetaObject* obj) const { return obj->userProperty(); } | |||
|
152 | ||||
|
153 | bool static_QMetaObject_checkConnectArgs(const char *signal, const char *method) { return QMetaObject::checkConnectArgs(signal, method); } | |||
|
154 | QByteArray static_QMetaObject_normalizedSignature(const char *method) { return QMetaObject::normalizedSignature(method); } | |||
|
155 | QByteArray static_QMetaObject_normalizedType(const char *type) { return QMetaObject::normalizedType(type); } | |||
|
156 | ||||
|
157 | }; | |||
108 |
|
158 | |||
109 | #endif |
|
159 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now