Implemented support to notify argument on Properties.

Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
          Marcelo Lira <marcelo.lira@openbossa.org>
This commit is contained in:
renatofilho 2010-10-21 13:15:04 -03:00
commit 26750d345c
10 changed files with 241 additions and 107 deletions

View file

@ -73,13 +73,13 @@ enum PropertyFlags {
class DynamicQMetaObject::DynamicQMetaObjectPrivate class DynamicQMetaObject::DynamicQMetaObjectPrivate
{ {
public: public:
QLinkedList<MethodData> m_signals; QList<MethodData> m_signals;
QLinkedList<MethodData> m_slots; QList<MethodData> m_slots;
QLinkedList<PropertyData> m_properties; QList<PropertyData> m_properties;
QByteArray m_className; QByteArray m_className;
void updateMetaObject(QMetaObject* metaObj); void updateMetaObject(QMetaObject* metaObj);
void writeMethodsData(QLinkedList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int maxCount, int nullIndex, int flags); void writeMethodsData(QList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int maxCount, int nullIndex, int flags);
}; };
static int registerString(const QByteArray& s, QList<QByteArray>* strings) static int registerString(const QByteArray& s, QList<QByteArray>* strings)
@ -196,6 +196,9 @@ uint PropertyData::flags() const
if (qpropertyIsFinal(m_data)) if (qpropertyIsFinal(m_data))
flags |= Final; flags |= Final;
if (m_notifyId)
flags |= Notify;
return flags; return flags;
} }
@ -246,12 +249,12 @@ bool MethodData::isValid() const
} }
PropertyData::PropertyData() PropertyData::PropertyData()
: m_data(0) : m_notifyId(0), m_data(0)
{ {
} }
PropertyData::PropertyData(const char* name, PyObject* data) PropertyData::PropertyData(const char* name, uint notifyId, PySideQProperty* data)
: m_name(name), m_data(data) : m_name(name), m_notifyId(notifyId), m_data(data)
{ {
} }
@ -271,6 +274,11 @@ QByteArray PropertyData::name() const
return m_name; return m_name;
} }
uint PropertyData::notifyId() const
{
return m_notifyId;
}
bool PropertyData::operator==(const PropertyData& other) const bool PropertyData::operator==(const PropertyData& other) const
{ {
return m_data == other.m_data; return m_data == other.m_data;
@ -301,15 +309,15 @@ DynamicQMetaObject::~DynamicQMetaObject()
void DynamicQMetaObject::addSignal(const char* signal, const char* type) void DynamicQMetaObject::addSignal(const char* signal, const char* type)
{ {
QLinkedList<MethodData>::iterator i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), signal); int index = m_d->m_signals.indexOf(signal);
if (i != m_d->m_signals.end()) if (index != -1)
return; return;
//search for a empty space //search for a empty space
MethodData blank; MethodData blank;
i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), blank); index = m_d->m_signals.indexOf(blank);
if (i != m_d->m_signals.end()) { if (index != -1) {
*i = MethodData(signal, type); m_d->m_signals[index] = MethodData(signal, type);
m_d->updateMetaObject(this); m_d->updateMetaObject(this);
return; return;
} }
@ -326,8 +334,8 @@ void DynamicQMetaObject::addSignal(const char* signal, const char* type)
void DynamicQMetaObject::addSlot(const char* slot, const char* type) void DynamicQMetaObject::addSlot(const char* slot, const char* type)
{ {
QLinkedList<MethodData>::iterator i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), slot); int index = m_d->m_slots.indexOf(slot);
if (i != m_d->m_slots.end()) if (index != -1)
return; return;
int maxSlots = maxSlotsCount(m_d->m_className); 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 //search for a empty space
MethodData blank; MethodData blank;
i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), blank); index = m_d->m_slots.indexOf(blank);
if (i != m_d->m_slots.end()) if (index != -1) {
*i = MethodData(slot, type); m_d->m_slots[index] = MethodData(slot, type);
else } else {
m_d->m_slots << MethodData(slot, type); m_d->m_slots << MethodData(slot, type);
}
m_d->updateMetaObject(this); 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<PropertyData>::iterator i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), property); int index = m_d->m_properties.indexOf(propertyName);
if (i != m_d->m_properties.end()) if (index != -1)
return; return;
// retrieve notifyId
PySideQProperty* property = reinterpret_cast<PySideQProperty*>(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 //search for a empty space
PropertyData blank; PropertyData blank;
i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), blank); index = m_d->m_properties.indexOf(blank);
if (i != m_d->m_properties.end()) { if (index != -1) {
*i = PropertyData(property, data); m_d->m_properties[index] = PropertyData(propertyName, notifyId, property);
} else { } else {
m_d->m_properties << PropertyData(property, data); m_d->m_properties << PropertyData(propertyName, notifyId, property);
} }
m_d->updateMetaObject(this); m_d->updateMetaObject(this);
} }
@ -438,7 +456,7 @@ void DynamicQMetaObject::removeSignal(uint index)
} }
} }
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QLinkedList<MethodData>& methods, void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QList<MethodData>& methods,
unsigned int** data, unsigned int** data,
QList<QByteArray>* strings, QList<QByteArray>* strings,
int* prtIndex, int* prtIndex,
@ -448,7 +466,7 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QLinkedList
{ {
int index = *prtIndex; int index = *prtIndex;
QLinkedList<MethodData>::iterator iMethod = methods.begin(); QList<MethodData>::iterator iMethod = methods.begin();
for(int i=0; i < maxCount; i++) { for(int i=0; i < maxCount; i++) {
QByteArray mType; QByteArray mType;
if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) { 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 // header size + 5 indexes per method + an ending zero
delete[] metaObj->d.data; delete[] metaObj->d.data;
unsigned int* 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)); std::memcpy(data, header, sizeof(header));
QList<QByteArray> strings; QList<QByteArray> strings;
@ -532,6 +550,11 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
data[index++] = pp.flags(); data[index++] = pp.flags();
} }
//write properties notify
foreach(PropertyData pp, m_properties) {
data[index++] = pp.notifyId(); //signal notify index
}
data[index++] = 0; // the end data[index++] = 0; // the end
// create the m_metadata string // create the m_metadata string

View file

@ -29,19 +29,21 @@
#define PYSIDE_SLOT_LIST_ATTR "_slots" #define PYSIDE_SLOT_LIST_ATTR "_slots"
struct PySideQProperty;
namespace PySide namespace PySide
{ {
class MethodData class MethodData
{ {
public: public:
MethodData(){} MethodData(){}
MethodData(const char* signature, const char* type); MethodData(const char* signature, const char* type = 0);
void clear(); void clear();
bool isValid() const; bool isValid() const;
QByteArray signature() const; QByteArray signature() const;
QByteArray type() const; QByteArray type() const;
bool operator==(const MethodData& other) const; bool operator==(const MethodData& other) const;
bool operator==(const char* other) const; bool operator==(const char* other) const;
operator const char*() { return m_signature->data(); }
private: private:
QSharedPointer<QByteArray> m_signature; QSharedPointer<QByteArray> m_signature;
@ -52,17 +54,19 @@ namespace PySide
{ {
public: public:
PropertyData(); PropertyData();
PropertyData(const char* name, PyObject* data); PropertyData(const char* name, uint notifyId=0, PySideQProperty* data = 0);
QByteArray name() const; QByteArray name() const;
QByteArray type() const; QByteArray type() const;
uint flags() const; uint flags() const;
bool isValid() const; bool isValid() const;
uint notifyId() const;
bool operator==(const PropertyData& other) const; bool operator==(const PropertyData& other) const;
bool operator==(const char* name) const; bool operator==(const char* name) const;
private: private:
QByteArray m_name; QByteArray m_name;
PyObject* m_data; uint m_notifyId;
PySideQProperty* m_data;
}; };
} }

View file

@ -68,7 +68,7 @@ bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds
} else { } else {
PyObject* attr = PyObject_GenericGetAttr(qObj, key); PyObject* attr = PyObject_GenericGetAttr(qObj, key);
if (isQPropertyType(attr)) if (isQPropertyType(attr))
PySide::qpropertySet(attr, qObj, value); PySide::qpropertySet(reinterpret_cast<PySideQProperty*>(attr), qObj, value);
} }
} else { } else {
propName.append("()"); propName.append("()");

View file

@ -27,6 +27,7 @@
#include "qproperty.h" #include "qproperty.h"
#include "qproperty_p.h" #include "qproperty_p.h"
#include "dynamicqmetaobject_p.h" #include "dynamicqmetaobject_p.h"
#include "qsignal.h"
#define QPROPERTY_CLASS_NAME "Property" #define QPROPERTY_CLASS_NAME "Property"
@ -57,13 +58,15 @@ char* translateTypeName(PyObject* type)
extern "C" extern "C"
{ {
struct PySideQPropertyDataPrivate { struct PySideQPropertyPrivate {
char* typeName; char* typeName;
PyObject* type; PyObject* type;
PyObject* fget; PyObject* fget;
PyObject* fset; PyObject* fset;
PyObject* freset; PyObject* freset;
PyObject* fdel; PyObject* fdel;
PyObject* notify;
char* notifySignature;
char* doc; char* doc;
bool designable; bool designable;
bool scriptable; bool scriptable;
@ -80,7 +83,7 @@ PyTypeObject PySideQPropertyType = {
PyObject_HEAD_INIT(0) PyObject_HEAD_INIT(0)
0, /*ob_size*/ 0, /*ob_size*/
QPROPERTY_CLASS_NAME, /*tp_name*/ QPROPERTY_CLASS_NAME, /*tp_name*/
sizeof(PySideQPropertyData), /*tp_basicsize*/ sizeof(PySideQProperty), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
0, /*tp_dealloc*/ 0, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
@ -129,21 +132,30 @@ PyTypeObject PySideQPropertyType = {
int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
{ {
PyObject* type = 0; PyObject* type = 0;
PySideQPropertyData* data = reinterpret_cast<PySideQPropertyData*>(self); PySideQProperty* data = reinterpret_cast<PySideQProperty*>(self);
PySideQPropertyDataPrivate* pData = (PySideQPropertyDataPrivate*) malloc(sizeof(PySideQPropertyDataPrivate*)); PySideQPropertyPrivate* pData = (PySideQPropertyPrivate*) malloc(sizeof(PySideQPropertyPrivate));
data->d = pData; data->d = pData;
pData->fset = 0;
pData->fget = 0;
pData->freset = 0;
pData->fdel = 0;
pData->designable = true; pData->designable = true;
pData->scriptable = true; pData->scriptable = true;
pData->stored = 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", "designable", "scriptable", "stored", "user",
"constant", "final", 0}; "constant", "final", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, if (!PyArg_ParseTupleAndKeywords(args, kwds,
"OO|OOOsbbbbbb:QtCore.QProperty", (char**) kwlist, "OO|OOOsObbbbbb:QtCore.QProperty", (char**) kwlist,
/*OO*/ &type, &(pData->fget), /*OO*/ &type, &(pData->fget),
/*OOOO*/ &(pData->fset), &(pData->freset), &(pData->fdel), /*OOO*/ &(pData->fset), &(pData->freset), &(pData->fdel),
/*s*/ &(pData->doc), /*s*/ &(pData->doc),
/*O*/ &(pData->notify),
/*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final))) /*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final)))
return 0; return 0;
@ -157,10 +169,11 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
void qpropertyFree(void *self) void qpropertyFree(void *self)
{ {
PyObject *pySelf = reinterpret_cast<PyObject*>(self); PyObject *pySelf = reinterpret_cast<PyObject*>(self);
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); PySideQProperty *data = reinterpret_cast<PySideQProperty*>(self);
free(data->d->typeName); free(data->d->typeName);
free(data->d->doc); free(data->d->doc);
free(data->d->notifySignature);
free(data->d); free(data->d);
pySelf->ob_type->tp_base->tp_free(self); pySelf->ob_type->tp_base->tp_free(self);
} }
@ -189,16 +202,16 @@ bool isQPropertyType(PyObject* pyObj)
return false; return false;
} }
int qpropertySet(PyObject* self, PyObject* source, PyObject* value) int qpropertySet(PySideQProperty* self, PyObject* source, PyObject* value)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); PyObject* fset = self->d->fset;
if (data->d->fset) { if (fset) {
Shiboken::AutoDecRef args(PyTuple_New(2)); Shiboken::AutoDecRef args(PyTuple_New(2));
PyTuple_SET_ITEM(args, 0, source); PyTuple_SET_ITEM(args, 0, source);
PyTuple_SET_ITEM(args, 1, value); PyTuple_SET_ITEM(args, 1, value);
Py_INCREF(source); Py_INCREF(source);
Py_INCREF(value); Py_INCREF(value);
Shiboken::AutoDecRef result(PyObject_CallObject(data->d->fset, args)); Shiboken::AutoDecRef result(PyObject_CallObject(fset, args));
return (result.isNull() ? -1 : 0); return (result.isNull() ? -1 : 0);
} else { } else {
PyErr_SetString(PyExc_AttributeError, "Attibute read only"); PyErr_SetString(PyExc_AttributeError, "Attibute read only");
@ -206,43 +219,42 @@ int qpropertySet(PyObject* self, PyObject* source, PyObject* value)
return -1; return -1;
} }
PyObject* qpropertyGet(PyObject* self, PyObject* source) PyObject* qpropertyGet(PySideQProperty* self, PyObject* source)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); PyObject* fget = self->d->fget;
if (data->d->fget) { if (fget) {
Shiboken::AutoDecRef args(PyTuple_New(1)); Shiboken::AutoDecRef args(PyTuple_New(1));
Py_INCREF(source); Py_INCREF(source);
PyTuple_SET_ITEM(args, 0, source); PyTuple_SET_ITEM(args, 0, source);
return PyObject_CallObject(data->d->fget, args); return PyObject_CallObject(fget, args);
} }
return 0; return 0;
} }
int qpropertyReset(PyObject* self, PyObject* source) int qpropertyReset(PySideQProperty* self, PyObject* source)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); PyObject* freset = self->d->freset;
if (data->d->freset) { if (freset) {
Shiboken::AutoDecRef args(PyTuple_New(1)); Shiboken::AutoDecRef args(PyTuple_New(1));
Py_INCREF(source); Py_INCREF(source);
PyTuple_SET_ITEM(args, 0, 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 (result.isNull() ? -1 : 0);
} }
return -1; return -1;
} }
const char* qpropertyGetType(PyObject* self) const char* qpropertyGetType(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->typeName;
return data->d->typeName;
} }
PyObject* qpropertyGetObject(PyObject* source, PyObject* name) PySideQProperty* qpropertyGetObject(PyObject* source, PyObject* name)
{ {
PyObject* attr = PyObject_GenericGetAttr(source, name); PyObject* attr = PyObject_GenericGetAttr(source, name);
if (attr && isQPropertyType(attr)) if (attr && isQPropertyType(attr))
return attr; return reinterpret_cast<PySideQProperty*>(attr);
if (!attr) if (!attr)
PyErr_Clear(); //Clear possible error caused by PyObject_GenericGetAttr PyErr_Clear(); //Clear possible error caused by PyObject_GenericGetAttr
@ -251,58 +263,60 @@ PyObject* qpropertyGetObject(PyObject* source, PyObject* name)
return 0; return 0;
} }
bool qpropertyIsReadable(PyObject* self) bool qpropertyIsReadable(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return (self->d->fget != 0);
return (data->d->fget != 0);
} }
bool qpropertyIsWritable(PyObject* self) bool qpropertyIsWritable(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return (self->d->fset != 0);
return (data->d->fset != 0);
} }
bool qpropertyHasReset(PyObject* self) bool qpropertyHasReset(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return (self->d->freset != 0);
return (data->d->freset != 0);
} }
bool qpropertyIsDesignable(PyObject* self) bool qpropertyIsDesignable(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->designable;
return data->d->designable;
} }
bool qpropertyIsScriptable(PyObject* self) bool qpropertyIsScriptable(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->scriptable;
return data->d->scriptable;
} }
bool qpropertyIsStored(PyObject* self) bool qpropertyIsStored(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->stored;
return data->d->stored;
} }
bool qpropertyIsUser(PyObject* self) bool qpropertyIsUser(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->user;
return data->d->user;
} }
bool qpropertyIsConstant(PyObject* self) bool qpropertyIsConstant(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->constant;
return data->d->constant;
} }
bool qpropertyIsFinal(PyObject* self) bool qpropertyIsFinal(PySideQProperty* self)
{ {
PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self); return self->d->final;
return data->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 } //namespace PySide

View file

@ -31,12 +31,14 @@ extern "C"
{ {
extern PYSIDE_API PyTypeObject PySideQPropertyType; extern PYSIDE_API PyTypeObject PySideQPropertyType;
struct PySideQPropertyDataPrivate; struct PySideQPropertyPrivate;
struct PYSIDE_API PySideQPropertyData struct PYSIDE_API PySideQProperty
{ {
PyObject_HEAD PyObject_HEAD
PySideQPropertyDataPrivate* d; PySideQPropertyPrivate* d;
}; };
struct PySideSignalInstanceData;
}; };
namespace PySide namespace PySide
@ -53,7 +55,7 @@ PYSIDE_API bool isQPropertyType(PyObject* pyObj);
* @param value The value to set in property * @param value The value to set in property
* @return Return 0 if ok or -1 if this function fail * @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 * 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 * @param source The QObject witch has the property
* @return Return the result of property get function or 0 if this fail * @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 * 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 * @param name The property name
* @return Return a new reference to property object * @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 } //namespace PySide

View file

@ -25,6 +25,8 @@
#include <Python.h> #include <Python.h>
struct PySideQProperty;
namespace PySide namespace PySide
{ {
@ -41,7 +43,7 @@ void initQProperty(PyObject* module);
* @param source The QObject witch has the property * @param source The QObject witch has the property
* @return Return 0 if ok or -1 if this function fail * @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 * @param self The property object
* @return Return the property type name * @return Return the property type name
**/ **/
const char* qpropertyGetType(PyObject* self); const char* qpropertyGetType(PySideQProperty* self);
/** /**
* This function check if property has read function * This function check if property has read function
@ -60,7 +62,7 @@ const char* qpropertyGetType(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsReadable(PyObject* self); bool qpropertyIsReadable(PySideQProperty* self);
/** /**
* This function check if property has write function * This function check if property has write function
@ -69,7 +71,7 @@ bool qpropertyIsReadable(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsWritable(PyObject* self); bool qpropertyIsWritable(PySideQProperty* self);
/** /**
* This function check if property has reset function * This function check if property has reset function
@ -78,7 +80,7 @@ bool qpropertyIsWritable(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyHasReset(PyObject* self); bool qpropertyHasReset(PySideQProperty* self);
/** /**
* This function check if property has the flag DESIGNABLE setted * This function check if property has the flag DESIGNABLE setted
@ -87,7 +89,7 @@ bool qpropertyHasReset(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsDesignable(PyObject* self); bool qpropertyIsDesignable(PySideQProperty* self);
/** /**
* This function check if property has the flag SCRIPTABLE setted * This function check if property has the flag SCRIPTABLE setted
@ -96,7 +98,7 @@ bool qpropertyIsDesignable(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsScriptable(PyObject* self); bool qpropertyIsScriptable(PySideQProperty* self);
/** /**
* This function check if property has the flag STORED setted * This function check if property has the flag STORED setted
@ -105,7 +107,7 @@ bool qpropertyIsScriptable(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsStored(PyObject* self); bool qpropertyIsStored(PySideQProperty* self);
/** /**
* This function check if property has the flag USER setted * This function check if property has the flag USER setted
@ -114,7 +116,7 @@ bool qpropertyIsStored(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsUser(PyObject* self); bool qpropertyIsUser(PySideQProperty* self);
/** /**
* This function check if property has the flag CONSTANT setted * This function check if property has the flag CONSTANT setted
@ -123,7 +125,7 @@ bool qpropertyIsUser(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsConstant(PyObject* self); bool qpropertyIsConstant(PySideQProperty* self);
/** /**
* This function check if property has the flag FINAL setted * This function check if property has the flag FINAL setted
@ -132,7 +134,7 @@ bool qpropertyIsConstant(PyObject* self);
* @param self The property object * @param self The property object
* @return Return a boolean value * @return Return a boolean value
**/ **/
bool qpropertyIsFinal(PyObject* self); bool qpropertyIsFinal(PySideQProperty* self);
} // namespace PySide } // namespace PySide

View file

@ -54,12 +54,14 @@ struct SignalData {
int signaturesSize; int signaturesSize;
PyObject* homonymousMethod; PyObject* homonymousMethod;
}; };
//Signal methods
static int signalTpInit(PyObject*, PyObject*, PyObject*); static int signalTpInit(PyObject*, PyObject*, PyObject*);
static void signalFree(void*); static void signalFree(void*);
static void signalInstanceFree(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* signalInstanceConnect(PyObject*, PyObject*, PyObject*);
static PyObject* signalInstanceDisconnect(PyObject*, PyObject*); static PyObject* signalInstanceDisconnect(PyObject*, PyObject*);
static PyObject* signalInstanceEmit(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* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw);
static PyObject* signalCall(PyObject*, PyObject*, PyObject*); static PyObject* signalCall(PyObject*, PyObject*, PyObject*);
static PyMappingMethods Signal_as_mapping = {
0,
signalGetItem,
0
};
PyTypeObject PySideSignalType = { PyTypeObject PySideSignalType = {
PyObject_HEAD_INIT(0) PyObject_HEAD_INIT(0)
/*ob_size*/ 0, /*ob_size*/ 0,
@ -82,10 +91,10 @@ PyTypeObject PySideSignalType = {
/*tp_repr*/ 0, /*tp_repr*/ 0,
/*tp_as_number*/ 0, /*tp_as_number*/ 0,
/*tp_as_sequence*/ 0, /*tp_as_sequence*/ 0,
/*tp_as_mapping*/ 0, /*tp_as_mapping*/ &Signal_as_mapping,
/*tp_hash*/ 0, /*tp_hash*/ 0,
/*tp_call*/ signalCall, /*tp_call*/ signalCall,
/*tp_str*/ 0, /*tp_str*/ signalToString,
/*tp_getattro*/ 0, /*tp_getattro*/ 0,
/*tp_setattro*/ 0, /*tp_setattro*/ 0,
/*tp_as_buffer*/ 0, /*tp_as_buffer*/ 0,
@ -234,6 +243,31 @@ void signalFree(void *self)
pySelf->ob_type->tp_base->tp_free(self); pySelf->ob_type->tp_base->tp_free(self);
} }
PyObject* signalGetItem(PyObject* self, PyObject* key)
{
SignalData* data = reinterpret_cast<SignalData*>(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) void signalInstanceFree(void* self)
{ {
PyObject* pySelf = reinterpret_cast<PyObject*>(self); PyObject* pySelf = reinterpret_cast<PyObject*>(self);
@ -543,8 +577,10 @@ void signalInstanceInitialize(PyObject* instance, PyObject* name, SignalData* da
selfPvt->next = 0; selfPvt->next = 0;
if (data->signalName) if (data->signalName)
selfPvt->signalName = strdup(data->signalName); selfPvt->signalName = strdup(data->signalName);
else else {
selfPvt->signalName = strdup(PyString_AsString(name)); selfPvt->signalName = strdup(PyString_AsString(name));
data->signalName = strdup(selfPvt->signalName);
}
selfPvt->source = source; selfPvt->source = source;
selfPvt->signature = signalBuildSignature(self->d->signalName, data->signatures[index]); selfPvt->signature = signalBuildSignature(self->d->signalName, data->signatures[index]);
@ -628,4 +664,12 @@ const char* getSignalSignature(PySideSignalInstanceData* signal)
return signal->d->signature; return signal->d->signature;
} }
const char** getSignalSignatures(PyObject* signal, int *size)
{
SignalData *self = reinterpret_cast<SignalData*>(signal);
*size = self->signaturesSize;
return (const char**) self->signatures;
}
} //namespace PySide } //namespace PySide

View file

@ -43,6 +43,8 @@ namespace PySide
bool signalConnect(PyObject* source, const char* signal, PyObject* callback); bool signalConnect(PyObject* source, const char* signal, PyObject* callback);
char* getTypeName(PyObject*); char* getTypeName(PyObject*);
void initSignalSupport(PyObject* module); void initSignalSupport(PyObject* module);
const char** getSignalSignatures(PyObject* self, int *size);
} //namespace PySide } //namespace PySide
#endif #endif

View file

@ -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) int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args)
{ {
const QMetaObject* metaObject = object->metaObject(); const QMetaObject* metaObject = object->metaObject();
PyObject* pp = 0; PySideQProperty* pp = 0;
PyObject* pp_name = 0; PyObject* pp_name = 0;
QMetaProperty mp; QMetaProperty mp;
Shiboken::TypeResolver* typeResolver = 0; Shiboken::TypeResolver* typeResolver = 0;

View file

@ -36,6 +36,21 @@ class MyObject(QObject):
pp = Property(int, readPP) 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): class PropertyCase(unittest.TestCase):
'''Test case for QObject properties''' '''Test case for QObject properties'''
@ -146,6 +161,25 @@ class PropertyWithConstructorCase(unittest.TestCase):
self.assertEqual(o.pp, 42) self.assertEqual(o.pp, 42)
self.assertRaises(AttributeError, o.trySetPP) 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__': if __name__ == '__main__':
unittest.main() unittest.main()