Add support for extension into PySide properties.

This is used by PySide implementation of QDeclarativeListProperty.
This commit is contained in:
Hugo Parente Lima 2010-12-08 15:06:52 -02:00
commit 1464dc1022
6 changed files with 109 additions and 55 deletions

View file

@ -367,12 +367,14 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
return; return;
// retrieve notifyId // retrieve notifyId
PySideProperty* property = reinterpret_cast<PySideProperty*>(data);
const char* signalNotify = PySide::Property::getNotifyName(property);
int notifyId = -1; int notifyId = -1;
if (signalNotify) { PySideProperty* property = reinterpret_cast<PySideProperty*>(data);
QByteArray signalSignature(signalNotify); if (property->d->notify) {
notifyId = m_d->m_signals.indexOf(signalNotify); const char* signalNotify = PySide::Property::getNotifyName(property);
if (signalNotify) {
QByteArray signalSignature(signalNotify);
notifyId = m_d->m_signals.indexOf(signalNotify);
}
} }
//search for a empty space //search for a empty space

View file

@ -186,7 +186,7 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
Shiboken::AutoDecRef slotAttrName(PyString_FromString(PYSIDE_SLOT_LIST_ATTR)); Shiboken::AutoDecRef slotAttrName(PyString_FromString(PYSIDE_SLOT_LIST_ATTR));
while (PyDict_Next(attrs, &pos, &key, &value)) { while (PyDict_Next(attrs, &pos, &key, &value)) {
if (value->ob_type == &PySidePropertyType) { if (PyType_IsSubtype(value->ob_type, &PySidePropertyType)) {
// Leave the properties to be register after signals because they may depend on notify signals // Leave the properties to be register after signals because they may depend on notify signals
properties << PropPair(PyString_AS_STRING(key), value); properties << PropPair(PyString_AS_STRING(key), value);
} else if (value->ob_type == &PySideSignalType) { // Register signals } else if (value->ob_type == &PySideSignalType) { // Register signals

View file

@ -36,6 +36,7 @@
extern "C" extern "C"
{ {
static PyObject* qpropertyTpNew(PyTypeObject* subtype, PyObject* args, PyObject* kwds);
static int qpropertyTpInit(PyObject*, PyObject*, PyObject*); static int qpropertyTpInit(PyObject*, PyObject*, PyObject*);
static void qpropertyFree(void*); static void qpropertyFree(void*);
@ -78,7 +79,7 @@ PyTypeObject PySidePropertyType = {
0, /*tp_dictoffset */ 0, /*tp_dictoffset */
qpropertyTpInit, /*tp_init */ qpropertyTpInit, /*tp_init */
0, /*tp_alloc */ 0, /*tp_alloc */
PyType_GenericNew, /*tp_new */ qpropertyTpNew, /*tp_new */
qpropertyFree, /*tp_free */ qpropertyFree, /*tp_free */
0, /*tp_is_gc */ 0, /*tp_is_gc */
0, /*tp_bases */ 0, /*tp_bases */
@ -89,25 +90,70 @@ PyTypeObject PySidePropertyType = {
0, /*tp_del */ 0, /*tp_del */
}; };
static void qpropertyMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::Call call, void** args)
{
Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get(pp->d->typeName);
Q_ASSERT(typeResolver);
switch(call) {
case QMetaObject::ReadProperty:
{
Shiboken::GilState gil;
PyObject* value = PySide::Property::getValue(pp, self);
if (value) {
typeResolver->toCpp(value, &args[0]);
Py_DECREF(value);
} else if (PyErr_Occurred()) {
PyErr_Print(); // Clear any errors but print them to stderr
}
break;
}
case QMetaObject::WriteProperty:
{
Shiboken::GilState gil;
Shiboken::AutoDecRef value(typeResolver->toPython(args[0]));
PySide::Property::setValue(pp, self, value);
break;
}
case QMetaObject::ResetProperty:
{
Shiboken::GilState gil;
PySide::Property::reset(pp, self);
break;
}
case QMetaObject::QueryPropertyDesignable:
case QMetaObject::QueryPropertyScriptable:
case QMetaObject::QueryPropertyStored:
case QMetaObject::QueryPropertyEditable:
case QMetaObject::QueryPropertyUser:
// just to avoid gcc warnings
case QMetaObject::InvokeMetaMethod:
case QMetaObject::CreateInstance:
break;
}
}
static PyObject* qpropertyTpNew(PyTypeObject* subtype, PyObject* args, PyObject* kwds)
{
PySideProperty* me = reinterpret_cast<PySideProperty*>(subtype->tp_alloc(subtype, 0));
me->d = new PySidePropertyPrivate;
memset(me->d, 0, sizeof(PySidePropertyPrivate));
PySidePropertyPrivate* pData = me->d;
pData->designable = true;
pData->scriptable = true;
pData->stored = true;
return (PyObject*) me;
}
int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds) int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
{ {
PyObject* type = 0; PyObject* type = 0;
PySideProperty* data = reinterpret_cast<PySideProperty*>(self); PySideProperty* data = reinterpret_cast<PySideProperty*>(self);
PySidePropertyPrivate* pData = (PySidePropertyPrivate*) malloc(sizeof(PySidePropertyPrivate)); PySidePropertyPrivate* pData = data->d;
data->d = pData; pData->metaCallHandler = &qpropertyMetaCall;
pData->fset = 0;
pData->fget = 0;
pData->freset = 0;
pData->fdel = 0;
pData->final = 0;
pData->designable = true;
pData->scriptable = true;
pData->stored = true;
pData->typeName = 0;
pData->doc = 0;
pData->notify = 0;
pData->notifySignature = 0;
pData->constant = 0;
static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", "notify", static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", "notify",
"designable", "scriptable", "stored", "user", "designable", "scriptable", "stored", "user",
@ -119,7 +165,6 @@ int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
/*s*/ &(pData->doc), /*s*/ &(pData->doc),
/*O*/ &(pData->notify), /*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))) {
free(pData);
return 0; return 0;
} }
@ -141,7 +186,7 @@ void qpropertyFree(void *self)
free(data->d->typeName); free(data->d->typeName);
free(data->d->doc); free(data->d->doc);
free(data->d->notifySignature); free(data->d->notifySignature);
free(data->d); delete data->d;
pySelf->ob_type->tp_base->tp_free(self); pySelf->ob_type->tp_base->tp_free(self);
} }
@ -163,7 +208,7 @@ void init(PyObject* module)
bool isPropertyType(PyObject* pyObj) bool isPropertyType(PyObject* pyObj)
{ {
if (pyObj) { if (pyObj) {
return pyObj->ob_type == &PySidePropertyType; return PyType_IsSubtype(pyObj->ob_type, &PySidePropertyType);
} }
return false; return false;
} }
@ -231,7 +276,7 @@ PySideProperty* getObject(PyObject* source, PyObject* name)
bool isReadable(const PySideProperty* self) bool isReadable(const PySideProperty* self)
{ {
return (self->d->fget != 0); return true;
} }
bool isWritable(const PySideProperty* self) bool isWritable(const PySideProperty* self)
@ -285,5 +330,25 @@ const char* getNotifyName(PySideProperty* self)
return self->d->notifySignature; return self->d->notifySignature;
} }
void setMetaCallHandler(PySideProperty* self, MetaCallHandler handler)
{
self->d->metaCallHandler = handler;
}
void setTypeName(PySideProperty* self, const char* typeName)
{
self->d->typeName = strdup(typeName);
}
void setUserData(PySideProperty* self, void* data)
{
self->d->userData = data;
}
void* userData(PySideProperty* self)
{
return self->d->userData;
}
} //namespace Property } //namespace Property
} //namespace PySide } //namespace PySide

View file

@ -41,6 +41,9 @@ extern "C"
namespace PySide { namespace Property { namespace PySide { namespace Property {
typedef void (*MetaCallHandler)(PySideProperty*,PyObject*,QMetaObject::Call, void**);
PYSIDE_API bool isPropertyType(PyObject* pyObj); PYSIDE_API bool isPropertyType(PyObject* pyObj);
/** /**
@ -82,6 +85,13 @@ PYSIDE_API const char* getNotifyName(PySideProperty* self);
**/ **/
PYSIDE_API PySideProperty* getObject(PyObject* source, PyObject* name); PYSIDE_API PySideProperty* getObject(PyObject* source, PyObject* name);
PYSIDE_API void setMetaCallHandler(PySideProperty* self, MetaCallHandler handler);
PYSIDE_API void setTypeName(PySideProperty* self, const char* typeName);
PYSIDE_API void setUserData(PySideProperty* self, void* data);
PYSIDE_API void* userData(PySideProperty* self);
} //namespace Property } //namespace Property
} //namespace PySide } //namespace PySide

View file

@ -24,6 +24,8 @@
#define PYSIDE_QPROPERTY_P_H #define PYSIDE_QPROPERTY_P_H
#include <Python.h> #include <Python.h>
#include <QMetaObject>
#include "pysideproperty.h"
struct PySideProperty; struct PySideProperty;
@ -33,6 +35,7 @@ extern "C"
struct PySidePropertyPrivate { struct PySidePropertyPrivate {
char* typeName; char* typeName;
PyObject* type; PyObject* type;
PySide::Property::MetaCallHandler metaCallHandler;
PyObject* fget; PyObject* fget;
PyObject* fset; PyObject* fset;
PyObject* freset; PyObject* freset;
@ -46,6 +49,7 @@ struct PySidePropertyPrivate {
bool user; bool user;
bool constant; bool constant;
bool final; bool final;
void* userData;
}; };
} // extern "C" } // extern "C"

View file

@ -248,7 +248,6 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
PySideProperty* pp = 0; PySideProperty* pp = 0;
PyObject* pp_name = 0; PyObject* pp_name = 0;
QMetaProperty mp; QMetaProperty mp;
Shiboken::TypeResolver* typeResolver = 0;
PyObject* pySelf = 0; PyObject* pySelf = 0;
if (call != QMetaObject::InvokeMetaMethod) { if (call != QMetaObject::InvokeMetaMethod) {
@ -262,49 +261,23 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
pp_name = PyString_FromString(mp.name()); pp_name = PyString_FromString(mp.name());
pp = Property::getObject(pySelf, pp_name); pp = Property::getObject(pySelf, pp_name);
if (!pp) { if (!pp) {
qWarning("Invalid property."); qWarning("Invalid property: %s.", mp.name());
Py_XDECREF(pp_name); Py_XDECREF(pp_name);
return id - metaObject->methodCount(); return id - metaObject->methodCount();
} }
typeResolver = Shiboken::TypeResolver::get(mp.typeName());
Q_ASSERT(typeResolver);
} }
switch(call) { switch(call) {
#ifndef QT_NO_PROPERTIES #ifndef QT_NO_PROPERTIES
case QMetaObject::ReadProperty: case QMetaObject::ReadProperty:
{
Shiboken::GilState gil;
PyObject* value = Property::getValue(pp, pySelf);
if (value) {
typeResolver->toCpp(value, &args[0]);
Py_DECREF(value);
} else if (PyErr_Occurred()) {
PyErr_Print(); // Clear any errors but print them to stderr
}
break;
}
case QMetaObject::WriteProperty: case QMetaObject::WriteProperty:
{
Shiboken::GilState gil;
Shiboken::AutoDecRef value(typeResolver->toPython(args[0]));
Property::setValue(pp, pySelf, value);
break;
}
case QMetaObject::ResetProperty: case QMetaObject::ResetProperty:
{
Shiboken::GilState gil;
Property::reset(pp, pp_name);
break;
}
case QMetaObject::QueryPropertyDesignable: case QMetaObject::QueryPropertyDesignable:
case QMetaObject::QueryPropertyScriptable: case QMetaObject::QueryPropertyScriptable:
case QMetaObject::QueryPropertyStored: case QMetaObject::QueryPropertyStored:
case QMetaObject::QueryPropertyEditable: case QMetaObject::QueryPropertyEditable:
case QMetaObject::QueryPropertyUser: case QMetaObject::QueryPropertyUser:
pp->d->metaCallHandler(pp, pySelf, call, args);
break; break;
#endif #endif
case QMetaObject::InvokeMetaMethod: case QMetaObject::InvokeMetaMethod: