@@ -78,11 +78,12 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName) | |||
|
78 | 78 | PythonQtRegisterToolClassesTemplateConverter(quint64); |
|
79 | 79 | // TODO: which other POD types should be available for QList etc. |
|
80 | 80 | |
|
81 | PythonQt::self()->addDecorators(new PythonQtStdDecorators()); | |
|
82 | ||
|
83 | 81 | PythonQt_init_QtCoreBuiltin(NULL); |
|
84 | 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 | 87 | PythonQtRegisterToolClassesTemplateConverter(QByteArray); |
|
87 | 88 | PythonQtRegisterToolClassesTemplateConverter(QDate); |
|
88 | 89 | PythonQtRegisterToolClassesTemplateConverter(QTime); |
@@ -919,6 +920,13 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) | |||
|
919 | 920 | } |
|
920 | 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 | 931 | return results; |
|
924 | 932 | } |
@@ -958,7 +966,13 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type) | |||
|
958 | 966 | // the last item may be a member, split it away and try again |
|
959 | 967 | QStringList tmp = typeName.split("."); |
|
960 | 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 | 976 | PyObject* typeObject = getObjectByType(typeName); |
|
963 | 977 | if (typeObject) { |
|
964 | 978 | object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData()); |
@@ -1690,3 +1704,18 QString PythonQtPrivate::getSignature(PyObject* object) | |||
|
1690 | 1704 | |
|
1691 | 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 | 563 | //! remove the wrapper ptr again |
|
564 | 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 | 569 | //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories |
|
567 | 570 | void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); |
|
568 | 571 |
@@ -205,46 +205,53 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con | |||
|
205 | 205 | } |
|
206 | 206 | |
|
207 | 207 | tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset); |
|
208 | ||
|
209 | return tail; | |
|
210 | } | |
|
211 | 208 | |
|
212 | bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) | |
|
213 | { | |
|
214 | bool found = false; | |
|
215 | int memberNameLen = static_cast<int>(strlen(memberName)); | |
|
216 | PythonQtSlotInfo* tail = NULL; | |
|
209 | // now look for slots/signals/methods on this level of the meta object | |
|
217 | 210 | if (_meta) { |
|
218 | 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 | 218 | QMetaMethod m = _meta->method(i); |
|
221 | 219 | if (((m.methodType() == QMetaMethod::Method || |
|
222 |
|
|
|
220 | m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) | |
|
223 | 221 | || m.methodType()==QMetaMethod::Signal) { |
|
224 | ||
|
225 | const char* sigStart = m.signature(); | |
|
226 | // find the first '(' | |
|
227 | int offset = findCharOffset(sigStart, '('); | |
|
228 | ||
|
229 | // check if same length and same name | |
|
230 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { | |
|
231 | found = true; | |
|
232 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); | |
|
233 | if (tail) { | |
|
234 | tail->setNextInfo(info); | |
|
235 | } else { | |
|
236 | PythonQtMemberInfo newInfo(info); | |
|
237 |
|
|
|
222 | ||
|
223 | const char* sigStart = m.signature(); | |
|
224 | // find the first '(' | |
|
225 | int offset = findCharOffset(sigStart, '('); | |
|
226 | ||
|
227 | // check if same length and same name | |
|
228 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { | |
|
229 | found = true; | |
|
230 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); | |
|
231 | if (tail) { | |
|
232 | tail->setNextInfo(info); | |
|
233 | } else { | |
|
234 | PythonQtMemberInfo newInfo(info); | |
|
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 | 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 | 253 | tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0); |
|
247 | ||
|
254 | ||
|
248 | 255 |
|
|
249 | 256 | } |
|
250 | 257 | |
@@ -710,22 +717,6 QObject* PythonQtClassInfo::decorator() | |||
|
710 | 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 | 720 | void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName) |
|
730 | 721 | { |
|
731 | 722 | if (!_polymorphicHandlers.isEmpty()) { |
@@ -159,9 +159,6 public: | |||
|
159 | 159 | //! add the parent class info of a CPP object |
|
160 | 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 | 162 | //! set the associated PythonQtClassWrapper (which handles instance creation of this type) |
|
166 | 163 | void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; } |
|
167 | 164 |
@@ -377,11 +377,32 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i | |||
|
377 | 377 | // a pointer |
|
378 | 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 | 401 | QString str = PyObjGetString(obj, strict, ok); |
|
381 | 402 | if (ok) { |
|
382 | 403 | void* ptr2 = NULL; |
|
383 |
PythonQtValueStorage_ADD_VALUE_IF_NEEDED( |
|
|
384 |
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, ( |
|
|
404 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2); | |
|
405 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr); | |
|
385 | 406 | } |
|
386 | 407 | } else if (info.name == "PyObject") { |
|
387 | 408 | // handle low level PyObject directly |
@@ -746,7 +767,13 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { | |||
|
746 | 767 | } else if (val == Py_True) { |
|
747 | 768 | d = 1; |
|
748 | 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 | 778 | } else { |
|
752 | 779 | ok = false; |
@@ -772,7 +799,13 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) { | |||
|
772 | 799 | } else if (val == Py_True) { |
|
773 | 800 | d = 1; |
|
774 | 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 | 810 | } else { |
|
778 | 811 | ok = false; |
@@ -798,7 +831,13 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) { | |||
|
798 | 831 | } else if (val == Py_True) { |
|
799 | 832 | d = 1; |
|
800 | 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 | 842 | } else { |
|
804 | 843 | ok = false; |
@@ -821,7 +860,13 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) { | |||
|
821 | 860 | } else if (val == Py_True) { |
|
822 | 861 | d = 1; |
|
823 | 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 | 871 | } else { |
|
827 | 872 | ok = false; |
@@ -64,7 +64,7 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, | |||
|
64 | 64 | // we own our qobject, so we delete it now: |
|
65 | 65 | delete self->_obj; |
|
66 | 66 | self->_obj = NULL; |
|
67 | if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) { | |
|
67 | if (force || self->_ownedByPythonQt) { | |
|
68 | 68 | int type = self->classInfo()->metaTypeId(); |
|
69 | 69 | if (self->_useQMetaTypeDestroy && type>=0) { |
|
70 | 70 | // use QMetaType to destroy the object |
@@ -197,6 +197,31 int PythonQtMethodInfo::nameToType(const char* name) | |||
|
197 | 197 | _parameterTypeDict.insert("QString", QMetaType::QString); |
|
198 | 198 | _parameterTypeDict.insert("", QMetaType::Void); |
|
199 | 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 | 225 | // QVariant names |
|
201 | 226 | _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong); |
|
202 | 227 | _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong); |
@@ -47,6 +47,10 | |||
|
47 | 47 | #include <QMetaMethod> |
|
48 | 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 | 54 | void PythonQtSignalTarget::call(void **arguments) const { |
|
51 | 55 | PyObject* result = call(_callable, methodInfo(), arguments); |
|
52 | 56 | if (result) { |
@@ -141,6 +145,16 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const | |||
|
141 | 145 | |
|
142 | 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 | 158 | _obj = obj; |
|
145 | 159 | |
|
146 | 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 | 192 | _slotCount++; |
|
179 | 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 | 204 | return flag; |
|
182 | 205 | } |
|
183 | 206 | |
|
184 | 207 | bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable) |
|
185 | 208 | { |
|
186 | bool found = false; | |
|
209 | int foundCount = 0; | |
|
187 | 210 | int sigId = getSignalIndex(signal); |
|
188 | 211 | if (sigId>=0) { |
|
189 | 212 | QMutableListIterator<PythonQtSignalTarget> i(_targets); |
@@ -191,7 +214,7 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c | |||
|
191 | 214 | while (i.hasNext()) { |
|
192 | 215 | if (i.next().isSame(sigId, callable)) { |
|
193 | 216 | i.remove(); |
|
194 |
found |
|
|
217 | foundCount++; | |
|
195 | 218 | break; |
|
196 | 219 | } |
|
197 | 220 | } |
@@ -199,17 +222,19 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c | |||
|
199 | 222 | while (i.hasNext()) { |
|
200 | 223 | if (i.next().signalId() == sigId) { |
|
201 | 224 | i.remove(); |
|
202 |
found |
|
|
225 | foundCount++; | |
|
203 | 226 | } |
|
204 | 227 | } |
|
205 | 228 | } |
|
206 | 229 | } |
|
207 | return found; | |
|
208 | } | |
|
209 | ||
|
210 | void PythonQtSignalReceiver::removeSignalHandlers() | |
|
211 | { | |
|
212 | _targets.clear(); | |
|
230 | if ((foundCount>0) && (sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) { | |
|
231 | _destroyedSignalCount -= foundCount; | |
|
232 | if (_destroyedSignalCount==0) { | |
|
233 | // make ourself child of QObject again, to get deleted when the object gets deleted | |
|
234 | this->setParent(_obj); | |
|
235 | } | |
|
236 | } | |
|
237 | return foundCount>0; | |
|
213 | 238 | } |
|
214 | 239 | |
|
215 | 240 | int PythonQtSignalReceiver::getSignalIndex(const char* signal) |
@@ -229,11 +254,17 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **argu | |||
|
229 | 254 | QObject::qt_metacall(c, id, arguments); |
|
230 | 255 | } |
|
231 | 256 | |
|
232 | bool found = false; | |
|
233 | 257 | foreach(const PythonQtSignalTarget& t, _targets) { |
|
234 | 258 | if (t.slotId() == id) { |
|
235 | found = true; | |
|
236 | 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 | 268 | break; |
|
238 | 269 | } |
|
239 | 270 | } |
@@ -121,9 +121,6 public: | |||
|
121 | 121 | //! remove a signal handler for given callable (or all callables on that signal if callable is NULL) |
|
122 | 122 | bool removeSignalHandler(const char* signal, PyObject* callable = NULL); |
|
123 | 123 | |
|
124 | //! remove all signal handlers | |
|
125 | void removeSignalHandlers(); | |
|
126 | ||
|
127 | 124 | //! we implement this method to simulate a number of slots that match the ids in _targets |
|
128 | 125 | virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments); |
|
129 | 126 | |
@@ -134,8 +131,12 private: | |||
|
134 | 131 | QObject* _obj; |
|
135 | 132 | PythonQtClassInfo* _objClassInfo; |
|
136 | 133 | int _slotCount; |
|
134 | int _destroyedSignalCount; | |
|
137 | 135 | // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals |
|
138 | 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 | 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 | 71 | bool r = false; |
|
72 | 72 | if (sender && receiver) { |
@@ -85,7 +85,7 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, Q | |||
|
85 | 85 | } else { |
|
86 | 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 | 90 | return r; |
|
91 | 91 | } |
@@ -316,3 +316,8 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, c | |||
|
316 | 316 | |
|
317 | 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 | 53 | #include <QDateTime> |
|
54 | 54 | #include <QDate> |
|
55 | 55 | #include <QTime> |
|
56 | #include <QImage> | |
|
57 | #include <QMetaMethod> | |
|
58 | #include <QMetaEnum> | |
|
59 | #include <QMetaProperty> | |
|
56 | 60 | |
|
57 | 61 | class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject |
|
58 | 62 | { |
@@ -60,9 +64,16 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject | |||
|
60 | 64 | |
|
61 | 65 | public slots: |
|
62 | 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 | 71 | bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL); |
|
65 | 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 | 78 | QObject* parent(QObject* o); |
|
68 | 79 | void setParent(QObject* o, QObject* parent); |
@@ -105,5 +116,44 private: | |||
|
105 | 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 | 159 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now