Add support for extension into PySide properties.
This is used by PySide implementation of QDeclarativeListProperty.
This commit is contained in:
parent
e76fffc617
commit
b4d1a3a4b6
6 changed files with 109 additions and 55 deletions
|
|
@ -367,13 +367,15 @@ 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;
|
||||||
|
PySideProperty* property = reinterpret_cast<PySideProperty*>(data);
|
||||||
|
if (property->d->notify) {
|
||||||
|
const char* signalNotify = PySide::Property::getNotifyName(property);
|
||||||
if (signalNotify) {
|
if (signalNotify) {
|
||||||
QByteArray signalSignature(signalNotify);
|
QByteArray signalSignature(signalNotify);
|
||||||
notifyId = m_d->m_signals.indexOf(signalNotify);
|
notifyId = m_d->m_signals.indexOf(signalNotify);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//search for a empty space
|
//search for a empty space
|
||||||
PropertyData blank;
|
PropertyData blank;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue