From 26750d345c61148d45b500e891b970b8e4e79661 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Thu, 21 Oct 2010 13:15:04 -0300 Subject: Implemented support to notify argument on Properties. Reviewer: Luciano Wolf Marcelo Lira --- libpyside/dynamicqmetaobject.cpp | 79 +++++++++++++++-------- libpyside/dynamicqmetaobject_p.h | 10 ++- libpyside/pyside.cpp | 2 +- libpyside/qproperty.cpp | 118 +++++++++++++++++++--------------- libpyside/qproperty.h | 23 +++++-- libpyside/qproperty_p.h | 24 +++---- libpyside/qsignal.cpp | 54 ++++++++++++++-- libpyside/qsignal_p.h | 2 + libpyside/signalmanager.cpp | 2 +- tests/QtCore/qobject_property_test.py | 34 ++++++++++ 10 files changed, 241 insertions(+), 107 deletions(-) diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp index ea6566563..88497843a 100644 --- a/libpyside/dynamicqmetaobject.cpp +++ b/libpyside/dynamicqmetaobject.cpp @@ -73,13 +73,13 @@ enum PropertyFlags { class DynamicQMetaObject::DynamicQMetaObjectPrivate { public: - QLinkedList m_signals; - QLinkedList m_slots; - QLinkedList m_properties; + QList m_signals; + QList m_slots; + QList m_properties; QByteArray m_className; void updateMetaObject(QMetaObject* metaObj); - void writeMethodsData(QLinkedList& methods, unsigned int** data, QList* strings, int* prtIndex, int maxCount, int nullIndex, int flags); + void writeMethodsData(QList& methods, unsigned int** data, QList* strings, int* prtIndex, int maxCount, int nullIndex, int flags); }; static int registerString(const QByteArray& s, QList* strings) @@ -196,6 +196,9 @@ uint PropertyData::flags() const if (qpropertyIsFinal(m_data)) flags |= Final; + if (m_notifyId) + flags |= Notify; + return flags; } @@ -246,12 +249,12 @@ bool MethodData::isValid() const } PropertyData::PropertyData() - : m_data(0) + : m_notifyId(0), m_data(0) { } -PropertyData::PropertyData(const char* name, PyObject* data) - : m_name(name), m_data(data) +PropertyData::PropertyData(const char* name, uint notifyId, PySideQProperty* data) + : m_name(name), m_notifyId(notifyId), m_data(data) { } @@ -271,6 +274,11 @@ QByteArray PropertyData::name() const return m_name; } +uint PropertyData::notifyId() const +{ + return m_notifyId; +} + bool PropertyData::operator==(const PropertyData& other) const { return m_data == other.m_data; @@ -301,15 +309,15 @@ DynamicQMetaObject::~DynamicQMetaObject() void DynamicQMetaObject::addSignal(const char* signal, const char* type) { - QLinkedList::iterator i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), signal); - if (i != m_d->m_signals.end()) + int index = m_d->m_signals.indexOf(signal); + if (index != -1) return; //search for a empty space MethodData blank; - i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), blank); - if (i != m_d->m_signals.end()) { - *i = MethodData(signal, type); + index = m_d->m_signals.indexOf(blank); + if (index != -1) { + m_d->m_signals[index] = MethodData(signal, type); m_d->updateMetaObject(this); return; } @@ -326,8 +334,8 @@ void DynamicQMetaObject::addSignal(const char* signal, const char* type) void DynamicQMetaObject::addSlot(const char* slot, const char* type) { - QLinkedList::iterator i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), slot); - if (i != m_d->m_slots.end()) + int index = m_d->m_slots.indexOf(slot); + if (index != -1) return; int maxSlots = maxSlotsCount(m_d->m_className); @@ -338,11 +346,12 @@ void DynamicQMetaObject::addSlot(const char* slot, const char* type) //search for a empty space MethodData blank; - i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), blank); - if (i != m_d->m_slots.end()) - *i = MethodData(slot, type); - else + index = m_d->m_slots.indexOf(blank); + if (index != -1) { + m_d->m_slots[index] = MethodData(slot, type); + } else { m_d->m_slots << MethodData(slot, type); + } m_d->updateMetaObject(this); } @@ -358,19 +367,28 @@ void DynamicQMetaObject::removeSlot(uint index) } } -void DynamicQMetaObject::addProperty(const char* property, PyObject* data) +void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data) { - QLinkedList::iterator i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), property); - if (i != m_d->m_properties.end()) + int index = m_d->m_properties.indexOf(propertyName); + if (index != -1) return; + // retrieve notifyId + PySideQProperty* property = reinterpret_cast(data); + const char* signalNotify = qpropertyGetNotify(property); + uint notifyId = 0; + if (signalNotify) { + QByteArray signalSignature(signalNotify); + notifyId = m_d->m_signals.indexOf(signalNotify) + 1; + } + //search for a empty space PropertyData blank; - i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), blank); - if (i != m_d->m_properties.end()) { - *i = PropertyData(property, data); + index = m_d->m_properties.indexOf(blank); + if (index != -1) { + m_d->m_properties[index] = PropertyData(propertyName, notifyId, property); } else { - m_d->m_properties << PropertyData(property, data); + m_d->m_properties << PropertyData(propertyName, notifyId, property); } m_d->updateMetaObject(this); } @@ -438,7 +456,7 @@ void DynamicQMetaObject::removeSignal(uint index) } } -void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QLinkedList& methods, +void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QList& methods, unsigned int** data, QList* strings, int* prtIndex, @@ -448,7 +466,7 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QLinkedList { int index = *prtIndex; - QLinkedList::iterator iMethod = methods.begin(); + QList::iterator iMethod = methods.begin(); for(int i=0; i < maxCount; i++) { QByteArray mType; if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) { @@ -504,7 +522,7 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject // header size + 5 indexes per method + an ending zero delete[] metaObj->d.data; unsigned int* data; - data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*3 + 1]; + data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*4 + 1]; std::memcpy(data, header, sizeof(header)); QList strings; @@ -532,6 +550,11 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject data[index++] = pp.flags(); } + //write properties notify + foreach(PropertyData pp, m_properties) { + data[index++] = pp.notifyId(); //signal notify index + } + data[index++] = 0; // the end // create the m_metadata string diff --git a/libpyside/dynamicqmetaobject_p.h b/libpyside/dynamicqmetaobject_p.h index 4488f07da..195209d24 100644 --- a/libpyside/dynamicqmetaobject_p.h +++ b/libpyside/dynamicqmetaobject_p.h @@ -29,19 +29,21 @@ #define PYSIDE_SLOT_LIST_ATTR "_slots" +struct PySideQProperty; namespace PySide { class MethodData { public: MethodData(){} - MethodData(const char* signature, const char* type); + MethodData(const char* signature, const char* type = 0); void clear(); bool isValid() const; QByteArray signature() const; QByteArray type() const; bool operator==(const MethodData& other) const; bool operator==(const char* other) const; + operator const char*() { return m_signature->data(); } private: QSharedPointer m_signature; @@ -52,17 +54,19 @@ namespace PySide { public: PropertyData(); - PropertyData(const char* name, PyObject* data); + PropertyData(const char* name, uint notifyId=0, PySideQProperty* data = 0); QByteArray name() const; QByteArray type() const; uint flags() const; bool isValid() const; + uint notifyId() const; bool operator==(const PropertyData& other) const; bool operator==(const char* name) const; private: QByteArray m_name; - PyObject* m_data; + uint m_notifyId; + PySideQProperty* m_data; }; } diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index 30a5e2663..7d9230016 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -68,7 +68,7 @@ bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds } else { PyObject* attr = PyObject_GenericGetAttr(qObj, key); if (isQPropertyType(attr)) - PySide::qpropertySet(attr, qObj, value); + PySide::qpropertySet(reinterpret_cast(attr), qObj, value); } } else { propName.append("()"); diff --git a/libpyside/qproperty.cpp b/libpyside/qproperty.cpp index fbdc31798..0a5b1c5ea 100644 --- a/libpyside/qproperty.cpp +++ b/libpyside/qproperty.cpp @@ -27,6 +27,7 @@ #include "qproperty.h" #include "qproperty_p.h" #include "dynamicqmetaobject_p.h" +#include "qsignal.h" #define QPROPERTY_CLASS_NAME "Property" @@ -57,13 +58,15 @@ char* translateTypeName(PyObject* type) extern "C" { -struct PySideQPropertyDataPrivate { +struct PySideQPropertyPrivate { char* typeName; PyObject* type; PyObject* fget; PyObject* fset; PyObject* freset; PyObject* fdel; + PyObject* notify; + char* notifySignature; char* doc; bool designable; bool scriptable; @@ -80,7 +83,7 @@ PyTypeObject PySideQPropertyType = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ QPROPERTY_CLASS_NAME, /*tp_name*/ - sizeof(PySideQPropertyData), /*tp_basicsize*/ + sizeof(PySideQProperty), /*tp_basicsize*/ 0, /*tp_itemsize*/ 0, /*tp_dealloc*/ 0, /*tp_print*/ @@ -129,21 +132,30 @@ PyTypeObject PySideQPropertyType = { int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) { PyObject* type = 0; - PySideQPropertyData* data = reinterpret_cast(self); - PySideQPropertyDataPrivate* pData = (PySideQPropertyDataPrivate*) malloc(sizeof(PySideQPropertyDataPrivate*)); + PySideQProperty* data = reinterpret_cast(self); + PySideQPropertyPrivate* pData = (PySideQPropertyPrivate*) malloc(sizeof(PySideQPropertyPrivate)); data->d = pData; + pData->fset = 0; + pData->fget = 0; + pData->freset = 0; + pData->fdel = 0; pData->designable = true; pData->scriptable = true; pData->stored = true; + pData->typeName = 0; + pData->doc = 0; + pData->notify = 0; + pData->notifySignature = 0; - static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", + static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", "notify", "designable", "scriptable", "stored", "user", "constant", "final", 0}; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OO|OOOsbbbbbb:QtCore.QProperty", (char**) kwlist, + "OO|OOOsObbbbbb:QtCore.QProperty", (char**) kwlist, /*OO*/ &type, &(pData->fget), - /*OOOO*/ &(pData->fset), &(pData->freset), &(pData->fdel), + /*OOO*/ &(pData->fset), &(pData->freset), &(pData->fdel), /*s*/ &(pData->doc), + /*O*/ &(pData->notify), /*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final))) return 0; @@ -157,10 +169,11 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) void qpropertyFree(void *self) { PyObject *pySelf = reinterpret_cast(self); - PySideQPropertyData *data = reinterpret_cast(self); + PySideQProperty *data = reinterpret_cast(self); free(data->d->typeName); free(data->d->doc); + free(data->d->notifySignature); free(data->d); pySelf->ob_type->tp_base->tp_free(self); } @@ -189,16 +202,16 @@ bool isQPropertyType(PyObject* pyObj) return false; } -int qpropertySet(PyObject* self, PyObject* source, PyObject* value) +int qpropertySet(PySideQProperty* self, PyObject* source, PyObject* value) { - PySideQPropertyData *data = reinterpret_cast(self); - if (data->d->fset) { + PyObject* fset = self->d->fset; + if (fset) { Shiboken::AutoDecRef args(PyTuple_New(2)); PyTuple_SET_ITEM(args, 0, source); PyTuple_SET_ITEM(args, 1, value); Py_INCREF(source); Py_INCREF(value); - Shiboken::AutoDecRef result(PyObject_CallObject(data->d->fset, args)); + Shiboken::AutoDecRef result(PyObject_CallObject(fset, args)); return (result.isNull() ? -1 : 0); } else { PyErr_SetString(PyExc_AttributeError, "Attibute read only"); @@ -206,43 +219,42 @@ int qpropertySet(PyObject* self, PyObject* source, PyObject* value) return -1; } -PyObject* qpropertyGet(PyObject* self, PyObject* source) +PyObject* qpropertyGet(PySideQProperty* self, PyObject* source) { - PySideQPropertyData *data = reinterpret_cast(self); - if (data->d->fget) { + PyObject* fget = self->d->fget; + if (fget) { Shiboken::AutoDecRef args(PyTuple_New(1)); Py_INCREF(source); PyTuple_SET_ITEM(args, 0, source); - return PyObject_CallObject(data->d->fget, args); + return PyObject_CallObject(fget, args); } return 0; } -int qpropertyReset(PyObject* self, PyObject* source) +int qpropertyReset(PySideQProperty* self, PyObject* source) { - PySideQPropertyData *data = reinterpret_cast(self); - if (data->d->freset) { + PyObject* freset = self->d->freset; + if (freset) { Shiboken::AutoDecRef args(PyTuple_New(1)); Py_INCREF(source); PyTuple_SET_ITEM(args, 0, source); - Shiboken::AutoDecRef result(PyObject_CallObject(data->d->freset, args)); + Shiboken::AutoDecRef result(PyObject_CallObject(freset, args)); return (result.isNull() ? -1 : 0); } return -1; } -const char* qpropertyGetType(PyObject* self) +const char* qpropertyGetType(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->typeName; + return self->d->typeName; } -PyObject* qpropertyGetObject(PyObject* source, PyObject* name) +PySideQProperty* qpropertyGetObject(PyObject* source, PyObject* name) { PyObject* attr = PyObject_GenericGetAttr(source, name); if (attr && isQPropertyType(attr)) - return attr; + return reinterpret_cast(attr); if (!attr) PyErr_Clear(); //Clear possible error caused by PyObject_GenericGetAttr @@ -251,58 +263,60 @@ PyObject* qpropertyGetObject(PyObject* source, PyObject* name) return 0; } -bool qpropertyIsReadable(PyObject* self) +bool qpropertyIsReadable(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return (data->d->fget != 0); + return (self->d->fget != 0); } -bool qpropertyIsWritable(PyObject* self) +bool qpropertyIsWritable(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return (data->d->fset != 0); + return (self->d->fset != 0); } -bool qpropertyHasReset(PyObject* self) +bool qpropertyHasReset(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return (data->d->freset != 0); + return (self->d->freset != 0); } -bool qpropertyIsDesignable(PyObject* self) +bool qpropertyIsDesignable(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->designable; + return self->d->designable; } -bool qpropertyIsScriptable(PyObject* self) +bool qpropertyIsScriptable(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->scriptable; + return self->d->scriptable; } -bool qpropertyIsStored(PyObject* self) +bool qpropertyIsStored(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->stored; + return self->d->stored; } -bool qpropertyIsUser(PyObject* self) +bool qpropertyIsUser(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->user; + return self->d->user; } -bool qpropertyIsConstant(PyObject* self) +bool qpropertyIsConstant(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->constant; + return self->d->constant; } -bool qpropertyIsFinal(PyObject* self) +bool qpropertyIsFinal(PySideQProperty* self) { - PySideQPropertyData *data = reinterpret_cast(self); - return data->d->final; + return self->d->final; +} + +const char* qpropertyGetNotify(PySideQProperty* self) +{ + if (!self->d->notifySignature) { + PyObject* str = PyObject_Str(self->d->notify); + self->d->notifySignature = strdup(PyString_AsString(str)); + Py_DECREF(str); + } + + return self->d->notifySignature; } } //namespace PySide diff --git a/libpyside/qproperty.h b/libpyside/qproperty.h index e0f89346b..ebe4ee762 100644 --- a/libpyside/qproperty.h +++ b/libpyside/qproperty.h @@ -31,12 +31,14 @@ extern "C" { extern PYSIDE_API PyTypeObject PySideQPropertyType; - struct PySideQPropertyDataPrivate; - struct PYSIDE_API PySideQPropertyData + struct PySideQPropertyPrivate; + struct PYSIDE_API PySideQProperty { PyObject_HEAD - PySideQPropertyDataPrivate* d; + PySideQPropertyPrivate* d; }; + + struct PySideSignalInstanceData; }; namespace PySide @@ -53,7 +55,7 @@ PYSIDE_API bool isQPropertyType(PyObject* pyObj); * @param value The value to set in property * @return Return 0 if ok or -1 if this function fail **/ -PYSIDE_API int qpropertySet(PyObject* self, PyObject* source, PyObject* value); +PYSIDE_API int qpropertySet(PySideQProperty* self, PyObject* source, PyObject* value); /** * This function call get property function @@ -63,7 +65,16 @@ PYSIDE_API int qpropertySet(PyObject* self, PyObject* source, PyObject* value); * @param source The QObject witch has the property * @return Return the result of property get function or 0 if this fail **/ -PYSIDE_API PyObject* qpropertyGet(PyObject* self, PyObject* source); +PYSIDE_API PyObject* qpropertyGet(PySideQProperty* self, PyObject* source); + +/** + * This function return the notify name used on this property + * + * @param self The property object + * @return Return a const char with the notify name used + **/ +PYSIDE_API const char* qpropertyGetNotify(PySideQProperty* self); + /** * This function search in the source object for desired property @@ -72,7 +83,7 @@ PYSIDE_API PyObject* qpropertyGet(PyObject* self, PyObject* source); * @param name The property name * @return Return a new reference to property object **/ -PYSIDE_API PyObject* qpropertyGetObject(PyObject* source, PyObject* name); +PYSIDE_API PySideQProperty* qpropertyGetObject(PyObject* source, PyObject* name); } //namespace PySide diff --git a/libpyside/qproperty_p.h b/libpyside/qproperty_p.h index dbd6dd107..d23a02c37 100644 --- a/libpyside/qproperty_p.h +++ b/libpyside/qproperty_p.h @@ -25,6 +25,8 @@ #include +struct PySideQProperty; + namespace PySide { @@ -41,7 +43,7 @@ void initQProperty(PyObject* module); * @param source The QObject witch has the property * @return Return 0 if ok or -1 if this function fail **/ -int qpropertyReset(PyObject* self, PyObject* source); +int qpropertyReset(PySideQProperty* self, PyObject* source); /** @@ -51,7 +53,7 @@ int qpropertyReset(PyObject* self, PyObject* source); * @param self The property object * @return Return the property type name **/ -const char* qpropertyGetType(PyObject* self); +const char* qpropertyGetType(PySideQProperty* self); /** * This function check if property has read function @@ -60,7 +62,7 @@ const char* qpropertyGetType(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsReadable(PyObject* self); +bool qpropertyIsReadable(PySideQProperty* self); /** * This function check if property has write function @@ -69,7 +71,7 @@ bool qpropertyIsReadable(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsWritable(PyObject* self); +bool qpropertyIsWritable(PySideQProperty* self); /** * This function check if property has reset function @@ -78,7 +80,7 @@ bool qpropertyIsWritable(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyHasReset(PyObject* self); +bool qpropertyHasReset(PySideQProperty* self); /** * This function check if property has the flag DESIGNABLE setted @@ -87,7 +89,7 @@ bool qpropertyHasReset(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsDesignable(PyObject* self); +bool qpropertyIsDesignable(PySideQProperty* self); /** * This function check if property has the flag SCRIPTABLE setted @@ -96,7 +98,7 @@ bool qpropertyIsDesignable(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsScriptable(PyObject* self); +bool qpropertyIsScriptable(PySideQProperty* self); /** * This function check if property has the flag STORED setted @@ -105,7 +107,7 @@ bool qpropertyIsScriptable(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsStored(PyObject* self); +bool qpropertyIsStored(PySideQProperty* self); /** * This function check if property has the flag USER setted @@ -114,7 +116,7 @@ bool qpropertyIsStored(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsUser(PyObject* self); +bool qpropertyIsUser(PySideQProperty* self); /** * This function check if property has the flag CONSTANT setted @@ -123,7 +125,7 @@ bool qpropertyIsUser(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsConstant(PyObject* self); +bool qpropertyIsConstant(PySideQProperty* self); /** * This function check if property has the flag FINAL setted @@ -132,7 +134,7 @@ bool qpropertyIsConstant(PyObject* self); * @param self The property object * @return Return a boolean value **/ -bool qpropertyIsFinal(PyObject* self); +bool qpropertyIsFinal(PySideQProperty* self); } // namespace PySide diff --git a/libpyside/qsignal.cpp b/libpyside/qsignal.cpp index 4d1559e6d..f6902619f 100644 --- a/libpyside/qsignal.cpp +++ b/libpyside/qsignal.cpp @@ -54,12 +54,14 @@ struct SignalData { int signaturesSize; PyObject* homonymousMethod; }; - +//Signal methods static int signalTpInit(PyObject*, PyObject*, PyObject*); static void signalFree(void*); static void signalInstanceFree(void*); +static PyObject* signalGetItem(PyObject* self, PyObject* key); +static PyObject* signalToString(PyObject* self); -//methods +//Signal Instance methods static PyObject* signalInstanceConnect(PyObject*, PyObject*, PyObject*); static PyObject* signalInstanceDisconnect(PyObject*, PyObject*); static PyObject* signalInstanceEmit(PyObject*, PyObject*); @@ -68,6 +70,13 @@ static PyObject* signalInstanceGetItem(PyObject*, PyObject*); static PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw); static PyObject* signalCall(PyObject*, PyObject*, PyObject*); +static PyMappingMethods Signal_as_mapping = { + 0, + signalGetItem, + 0 +}; + + PyTypeObject PySideSignalType = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, @@ -82,10 +91,10 @@ PyTypeObject PySideSignalType = { /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, - /*tp_as_mapping*/ 0, + /*tp_as_mapping*/ &Signal_as_mapping, /*tp_hash*/ 0, /*tp_call*/ signalCall, - /*tp_str*/ 0, + /*tp_str*/ signalToString, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ 0, @@ -234,6 +243,31 @@ void signalFree(void *self) pySelf->ob_type->tp_base->tp_free(self); } +PyObject* signalGetItem(PyObject* self, PyObject* key) +{ + SignalData* data = reinterpret_cast(self); + char* sigKey; + if (key) { + sigKey = PySide::signalParseSignature(key); + } else { + if (data->signatures[0]) + sigKey = strdup(data->signatures[0]); + else + sigKey = strdup("void"); + } + char* sig = PySide::signalBuildSignature(data->signalName, sigKey); + free(sigKey); + PyObject* pySignature = PyString_FromString(sig); + free(sig); + return pySignature; +} + + +PyObject* signalToString(PyObject* self) +{ + return signalGetItem(self, 0); +} + void signalInstanceFree(void* self) { PyObject* pySelf = reinterpret_cast(self); @@ -543,8 +577,10 @@ void signalInstanceInitialize(PyObject* instance, PyObject* name, SignalData* da selfPvt->next = 0; if (data->signalName) selfPvt->signalName = strdup(data->signalName); - else + else { selfPvt->signalName = strdup(PyString_AsString(name)); + data->signalName = strdup(selfPvt->signalName); + } selfPvt->source = source; selfPvt->signature = signalBuildSignature(self->d->signalName, data->signatures[index]); @@ -628,4 +664,12 @@ const char* getSignalSignature(PySideSignalInstanceData* signal) return signal->d->signature; } + +const char** getSignalSignatures(PyObject* signal, int *size) +{ + SignalData *self = reinterpret_cast(signal); + *size = self->signaturesSize; + return (const char**) self->signatures; +} + } //namespace PySide diff --git a/libpyside/qsignal_p.h b/libpyside/qsignal_p.h index 2fbe523d2..b4e4ab8d8 100644 --- a/libpyside/qsignal_p.h +++ b/libpyside/qsignal_p.h @@ -43,6 +43,8 @@ namespace PySide bool signalConnect(PyObject* source, const char* signal, PyObject* callback); char* getTypeName(PyObject*); void initSignalSupport(PyObject* module); + const char** getSignalSignatures(PyObject* self, int *size); + } //namespace PySide #endif diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index c0ce568a9..28e3792f2 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -354,7 +354,7 @@ bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* ar int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args) { const QMetaObject* metaObject = object->metaObject(); - PyObject* pp = 0; + PySideQProperty* pp = 0; PyObject* pp_name = 0; QMetaProperty mp; Shiboken::TypeResolver* typeResolver = 0; diff --git a/tests/QtCore/qobject_property_test.py b/tests/QtCore/qobject_property_test.py index 74068940a..776a14dfe 100644 --- a/tests/QtCore/qobject_property_test.py +++ b/tests/QtCore/qobject_property_test.py @@ -36,6 +36,21 @@ class MyObject(QObject): pp = Property(int, readPP) +class MyObjectWithNotifyProperty(QObject): + def __init__(self, parent=None): + QObject.__init__(self, parent) + self.p = 0 + + def readP(self): + return self.p + + def writeP(self, v): + self.p = v + self.notifyP.emit() + + notifyP = Signal() + myProperty = Property(int, readP, fset=writeP, notify=notifyP) + class PropertyCase(unittest.TestCase): '''Test case for QObject properties''' @@ -146,6 +161,25 @@ class PropertyWithConstructorCase(unittest.TestCase): self.assertEqual(o.pp, 42) self.assertRaises(AttributeError, o.trySetPP) +class PropertyWithNotify(unittest.TestCase): + def called(self): + self.called_ = True + + def testMetaData(self): + obj = MyObjectWithNotifyProperty() + mo = obj.metaObject() + self.assertEqual(mo.propertyCount(), 2) + p = mo.property(1) + self.assertEqual(p.name(), "myProperty") + self.assert_(p.hasNotifySignal()) + + def testNotify(self): + self.called_ = False + obj = MyObjectWithNotifyProperty() + obj.notifyP.connect(self.called) + obj.myProperty = 10 + self.assert_(self.called_) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3