// The type descriptor get slot. static PyObject *pyqtSignal_descr_get(PyObject *self, PyObject *obj, PyObject *) { qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)self; // Return the unbound signal if there is nothing to bind it to. if (obj == NULL || obj == Py_None) { Py_INCREF(self); return self; } // Get the QObject. int is_err = 0; void *qobject = sipForceConvertToType(obj, sipType_QObject, 0, SIP_NO_CONVERTORS, 0, &is_err); if (is_err) { PyErr_Format(PyExc_TypeError, "pyqtSignal must be bound to a QObject, not '%s'", Py_TYPE(obj)->tp_name); return 0; } // Return the bound signal. return qpycore_pyqtBoundSignal_New(self, obj, reinterpret_cast<QObject *>(qobject), ps->overloads->first()); }
// The mapping subscript slot. static PyObject *pyqtBoundSignal_mp_subscript(PyObject *self, PyObject *subscript) { qpycore_pyqtBoundSignal *bs = (qpycore_pyqtBoundSignal *)self; qpycore_pyqtSignal *ps = qpycore_find_signal(bs->unbound_signal, subscript, "a bound signal type argument"); if (!ps) return 0; // Create a new bound signal. return qpycore_pyqtBoundSignal_New(ps, bs->bound_pyobject, bs->bound_qobject); }
// The mapping subscript slot. static PyObject *pyqtBoundSignal_mp_subscript(PyObject *self, PyObject *subscript) { qpycore_pyqtBoundSignal *bs = (qpycore_pyqtBoundSignal *)self; int idx = qpycore_signal_index((qpycore_pyqtSignal *)bs->unbound_signal, subscript, "a bound signal type argument"); if (idx < 0) return 0; // Create a new bound signal. return qpycore_pyqtBoundSignal_New(bs->unbound_signal, bs->bound_pyobject, bs->bound_qobject, idx); }
// The type descriptor get slot. static PyObject *pyqtSignal_descr_get(PyObject *self, PyObject *obj, PyObject *) { qpycore_pyqtSignal *ps = (qpycore_pyqtSignal *)self; // Return the unbound signal if there is nothing to bind it to. if (obj == NULL || obj == Py_None) { Py_INCREF(self); return self; } // Get the QObject. int is_err = 0; void *qobject = sipForceConvertToType(obj, sipType_QObject, 0, SIP_NO_CONVERTORS, 0, &is_err); if (is_err) return 0; // Return the bound signal. return qpycore_pyqtBoundSignal_New(ps, obj, reinterpret_cast<QObject *>(qobject)); }
// See if we can find an attribute in the Qt meta-type system. This is // primarily to support access to JavaScript (e.g. QDeclarativeItem) so we // don't support overloads. PyObject *qpycore_qobject_getattr(QObject *qobj, PyObject *py_qobj, const char *name) { const QMetaObject *mo = qobj->metaObject(); // Try and find a method with the name. QMetaMethod method; int method_index = -1; // Count down to allow overrides (assuming they are possible). for (int m = mo->methodCount() - 1; m >= 0; --m) { method = mo->method(m); #if QT_VERSION >= 0x040500 if (method.methodType() == QMetaMethod::Constructor) continue; #endif // Get the method name. #if QT_VERSION >= 0x050000 QByteArray mname(method.methodSignature()); #else QByteArray mname(method.signature()); #endif int idx = mname.indexOf('('); if (idx >= 0) mname.truncate(idx); if (mname == name) { method_index = m; break; } } if (method_index < 0) { // Replicate the standard Python exception. PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", Py_TYPE(py_qobj)->tp_name, name); return 0; } // Get the value to return. Note that this is recreated each time. We // could put a descriptor in the type dictionary to satisfy the request in // future but the typical use case is getting a value from a C++ proxy // (e.g. QDeclarativeItem) and we can't assume that what is being proxied // is the same each time. PyObject *value; if (method.methodType() == QMetaMethod::Signal) { // We need to keep explicit references to the unbound signals (because // we don't use the type dictionary to do so) because they own the // parsed signature which may be needed by a PyQtProxy at some point. typedef QHash<QByteArray, PyObject *> SignalHash; static SignalHash *sig_hash = 0; // For crappy compilers. if (!sig_hash) sig_hash = new SignalHash; PyObject *sig_obj; #if QT_VERSION >= 0x050000 QByteArray sig_str(method.methodSignature()); #else QByteArray sig_str(method.signature()); #endif SignalHash::const_iterator it = sig_hash->find(sig_str); if (it == sig_hash->end()) { sig_obj = (PyObject *)qpycore_pyqtSignal_New(sig_str.constData()); if (!sig_obj) return 0; sig_hash->insert(sig_str, sig_obj); } else { sig_obj = it.value(); } value = qpycore_pyqtBoundSignal_New((qpycore_pyqtSignal *)sig_obj, py_qobj, qobj); } else { QByteArray py_name(Py_TYPE(py_qobj)->tp_name); py_name.append('.'); py_name.append(name); value = qpycore_pyqtMethodProxy_New(qobj, method_index, py_name); } return value; }