Implemented PySide::ClassInfo Object.
This class reproduce the Qt macro Q_CLASSINFO behavior.
Eg.:
@QtCore.ClassInfo(author='PySide', url='http://www.pyside.org')
fixes bug #705.
Reviewer: Marcelo Lira <marcelo.lira@openbossa.org>
Hugo Parente Lima <hugo.pl@gmail.com>
This commit is contained in:
parent
fe06dba43c
commit
04be2b1ca2
7 changed files with 317 additions and 11 deletions
|
|
@ -4,6 +4,7 @@ set(libpyside_SRC
|
||||||
dynamicqmetaobject.cpp
|
dynamicqmetaobject.cpp
|
||||||
signalmanager.cpp
|
signalmanager.cpp
|
||||||
globalreceiver.cpp
|
globalreceiver.cpp
|
||||||
|
pysideclassinfo.cpp
|
||||||
pysidemetafunction.cpp
|
pysidemetafunction.cpp
|
||||||
pysidesignal.cpp
|
pysidesignal.cpp
|
||||||
pysideslot.cpp
|
pysideslot.cpp
|
||||||
|
|
@ -35,6 +36,7 @@ set_target_properties(pyside PROPERTIES
|
||||||
set(libpyside_HEADERS
|
set(libpyside_HEADERS
|
||||||
dynamicqmetaobject.h
|
dynamicqmetaobject.h
|
||||||
globalreceiver.h
|
globalreceiver.h
|
||||||
|
pysideclassinfo.h
|
||||||
pysideconversions.h
|
pysideconversions.h
|
||||||
pysidemacros.h
|
pysidemacros.h
|
||||||
signalmanager.h
|
signalmanager.h
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ class DynamicQMetaObject::DynamicQMetaObjectPrivate
|
||||||
public:
|
public:
|
||||||
QList<MethodData> m_methods;
|
QList<MethodData> m_methods;
|
||||||
QList<PropertyData> m_properties;
|
QList<PropertyData> m_properties;
|
||||||
|
QMap<QByteArray, QByteArray> m_info;
|
||||||
QByteArray m_className;
|
QByteArray m_className;
|
||||||
|
|
||||||
void updateMetaObject(QMetaObject* metaObj);
|
void updateMetaObject(QMetaObject* metaObj);
|
||||||
|
|
@ -380,6 +381,20 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
|
||||||
m_d->updateMetaObject(this);
|
m_d->updateMetaObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicQMetaObject::addInfo(const char* key, const char* value)
|
||||||
|
{
|
||||||
|
m_d->m_info[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicQMetaObject::addInfo(QMap<QByteArray, QByteArray> info)
|
||||||
|
{
|
||||||
|
QMap<QByteArray, QByteArray>::const_iterator i = info.constBegin();
|
||||||
|
while (i != info.constEnd()) {
|
||||||
|
m_d->m_info[i.key()] = i.value();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
m_d->updateMetaObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
|
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
|
||||||
unsigned int** data,
|
unsigned int** data,
|
||||||
|
|
@ -409,21 +424,22 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
|
||||||
{
|
{
|
||||||
uint n_methods = m_methods.size();
|
uint n_methods = m_methods.size();
|
||||||
uint n_properties = m_properties.size();
|
uint n_properties = m_properties.size();
|
||||||
int header[] = {3, // revision
|
uint n_info = m_info.size();
|
||||||
0, // class name index in m_metadata
|
int header[] = {3, // revision
|
||||||
0, 0, // classinfo and classinfo index, not used by us
|
0, // class name index in m_metadata
|
||||||
n_methods, 0, // method count and method list index
|
n_info, 0, // classinfo and classinfo index
|
||||||
n_properties, 0, // prop count and prop indexes
|
n_methods, 0, // method count and method list index
|
||||||
0, 0, // enum count and enum index
|
n_properties, 0, // prop count and prop indexes
|
||||||
0, 0, // constructors
|
0, 0, // enum count and enum index
|
||||||
0}; // flags
|
0, 0, // constructors
|
||||||
|
0}; // flags
|
||||||
|
|
||||||
const int HEADER_LENGHT = sizeof(header)/sizeof(int);
|
const int HEADER_LENGHT = sizeof(header)/sizeof(int);
|
||||||
header[5] = HEADER_LENGHT;
|
header[5] = HEADER_LENGHT;
|
||||||
// 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*4 + 1];
|
data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*4 + n_info*2 + 1];
|
||||||
std::memcpy(data, header, sizeof(header));
|
std::memcpy(data, header, sizeof(header));
|
||||||
|
|
||||||
QList<QByteArray> strings;
|
QList<QByteArray> strings;
|
||||||
|
|
@ -431,6 +447,19 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
|
||||||
const int NULL_INDEX = registerString("", &strings); // register a null string
|
const int NULL_INDEX = registerString("", &strings); // register a null string
|
||||||
int index = HEADER_LENGHT;
|
int index = HEADER_LENGHT;
|
||||||
|
|
||||||
|
//write class info
|
||||||
|
if (n_info) {
|
||||||
|
data[3] = index;
|
||||||
|
QMap<QByteArray, QByteArray>::const_iterator i = m_info.constBegin();
|
||||||
|
while (i != m_info.constEnd()) {
|
||||||
|
int valueIndex = registerString(i.value(), &strings);
|
||||||
|
int keyIndex = registerString(i.key(), &strings);
|
||||||
|
data[index++] = keyIndex;
|
||||||
|
data[index++] = valueIndex;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//write signals/slots
|
//write signals/slots
|
||||||
writeMethodsData(m_methods, &data, &strings, &index, NULL_INDEX, AccessPublic);
|
writeMethodsData(m_methods, &data, &strings, &index, NULL_INDEX, AccessPublic);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ public:
|
||||||
void addSignal(const char* signal, const char* type = 0);
|
void addSignal(const char* signal, const char* type = 0);
|
||||||
void addSlot(const char* slot, const char* type = 0);
|
void addSlot(const char* slot, const char* type = 0);
|
||||||
void addProperty(const char* property, PyObject* data);
|
void addProperty(const char* property, PyObject* data);
|
||||||
|
void addInfo(const char* key, const char* value);
|
||||||
|
void addInfo(QMap<QByteArray, QByteArray> info);
|
||||||
|
|
||||||
void removeSignal(uint idex);
|
void removeSignal(uint idex);
|
||||||
void removeSlot(uint index);
|
void removeSlot(uint index);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "pyside.h"
|
#include "pyside.h"
|
||||||
#include "signalmanager.h"
|
#include "signalmanager.h"
|
||||||
|
#include "pysideclassinfo_p.h"
|
||||||
#include "pysideproperty_p.h"
|
#include "pysideproperty_p.h"
|
||||||
#include "pysideproperty.h"
|
#include "pysideproperty.h"
|
||||||
#include "pysidesignal.h"
|
#include "pysidesignal.h"
|
||||||
|
|
@ -47,6 +48,7 @@ namespace PySide
|
||||||
|
|
||||||
void init(PyObject *module)
|
void init(PyObject *module)
|
||||||
{
|
{
|
||||||
|
ClassInfo::init(module);
|
||||||
Signal::init(module);
|
Signal::init(module);
|
||||||
Slot::init(module);
|
Slot::init(module);
|
||||||
Property::init(module);
|
Property::init(module);
|
||||||
|
|
@ -188,10 +190,10 @@ 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 (PyType_IsSubtype(value->ob_type, &PySidePropertyType)) {
|
if (Property::checkType(value)) {
|
||||||
// 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 (Signal::checkType(value)) { // Register signals
|
||||||
PySideSignal* data = reinterpret_cast<PySideSignal*>(value);
|
PySideSignal* data = reinterpret_cast<PySideSignal*>(value);
|
||||||
const char* signalName = PyString_AS_STRING(key);
|
const char* signalName = PyString_AS_STRING(key);
|
||||||
data->signalName = strdup(signalName);
|
data->signalName = strdup(signalName);
|
||||||
|
|
|
||||||
166
libpyside/pysideclassinfo.cpp
Normal file
166
libpyside/pysideclassinfo.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the PySide project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
*
|
||||||
|
* Contact: PySide team <contact@pyside.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include "pysideclassinfo.h"
|
||||||
|
#include "pysideclassinfo_p.h"
|
||||||
|
#include "dynamicqmetaobject.h"
|
||||||
|
|
||||||
|
#include <shiboken.h>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#define CLASSINFO_CLASS_NAME "ClassInfo"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
static PyObject* classInfoTpNew(PyTypeObject* subtype, PyObject* args, PyObject* kwds);
|
||||||
|
static int classInfoTpInit(PyObject*, PyObject*, PyObject*);
|
||||||
|
static void classInfoFree(void*);
|
||||||
|
static PyObject* classCall(PyObject*, PyObject*, PyObject*);
|
||||||
|
|
||||||
|
PyTypeObject PySideClassInfoType = {
|
||||||
|
PyObject_HEAD_INIT(0)
|
||||||
|
0, /*ob_size*/
|
||||||
|
CLASSINFO_CLASS_NAME, /*tp_name*/
|
||||||
|
sizeof(PySideClassInfo), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
0, /*tp_dealloc*/
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /*tp_getattr*/
|
||||||
|
0, /*tp_setattr*/
|
||||||
|
0, /*tp_compare*/
|
||||||
|
0, /*tp_repr*/
|
||||||
|
0, /*tp_as_number*/
|
||||||
|
0, /*tp_as_sequence*/
|
||||||
|
0, /*tp_as_mapping*/
|
||||||
|
0, /*tp_hash */
|
||||||
|
classCall, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
0, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
|
0, /*tp_as_buffer*/
|
||||||
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||||
|
0, /*tp_doc */
|
||||||
|
0, /*tp_traverse */
|
||||||
|
0, /*tp_clear */
|
||||||
|
0, /*tp_richcompare */
|
||||||
|
0, /*tp_weaklistoffset */
|
||||||
|
0, /*tp_iter */
|
||||||
|
0, /*tp_iternext */
|
||||||
|
0, /*tp_methods */
|
||||||
|
0, /*tp_members */
|
||||||
|
0, /*tp_getset */
|
||||||
|
0, /*tp_base */
|
||||||
|
0, /*tp_dict */
|
||||||
|
0, /*tp_descr_get */
|
||||||
|
0, /*tp_descr_set */
|
||||||
|
0, /*tp_dictoffset */
|
||||||
|
classInfoTpInit, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
classInfoTpNew, /*tp_new */
|
||||||
|
classInfoFree, /*tp_free */
|
||||||
|
0, /*tp_is_gc */
|
||||||
|
0, /*tp_bases */
|
||||||
|
0, /*tp_mro */
|
||||||
|
0, /*tp_cache */
|
||||||
|
0, /*tp_subclasses */
|
||||||
|
0, /*tp_weaklist */
|
||||||
|
0, /*tp_del */
|
||||||
|
};
|
||||||
|
|
||||||
|
PyObject* classCall(PyObject* self, PyObject* args, PyObject* kw)
|
||||||
|
{
|
||||||
|
PyObject* klass;
|
||||||
|
klass = PyTuple_GetItem(args, 0);
|
||||||
|
|
||||||
|
if (Shiboken::ObjectType::checkType(reinterpret_cast<PyTypeObject*>(klass))) {
|
||||||
|
PySide::DynamicQMetaObject* mo = reinterpret_cast<PySide::DynamicQMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(klass)));
|
||||||
|
if (mo)
|
||||||
|
mo->addInfo(PySide::ClassInfo::getMap(reinterpret_cast<PySideClassInfo*>(self)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF(klass);
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject* classInfoTpNew(PyTypeObject* subtype, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
PySideClassInfo* me = reinterpret_cast<PySideClassInfo*>(subtype->tp_alloc(subtype, 0));
|
||||||
|
me->d = new PySideClassInfoPrivate;
|
||||||
|
return (PyObject*) me;
|
||||||
|
}
|
||||||
|
|
||||||
|
int classInfoTpInit(PyObject* self, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
PySideClassInfo* data = reinterpret_cast<PySideClassInfo*>(self);
|
||||||
|
PySideClassInfoPrivate* pData = data->d;
|
||||||
|
|
||||||
|
PyObject* key;
|
||||||
|
PyObject* value;
|
||||||
|
Py_ssize_t pos = 0;
|
||||||
|
while (PyDict_Next(kwds, &pos, &key, &value)) {
|
||||||
|
if (PyString_Check(key) && PyString_Check(value))
|
||||||
|
pData->m_data[PyString_AS_STRING(key)] = PyString_AS_STRING(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyErr_Occurred() ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void classInfoFree(void *self)
|
||||||
|
{
|
||||||
|
PyObject* pySelf = reinterpret_cast<PyObject*>(self);
|
||||||
|
PySideClassInfo* data = reinterpret_cast<PySideClassInfo*>(self);
|
||||||
|
|
||||||
|
delete data->d;
|
||||||
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
namespace PySide { namespace ClassInfo {
|
||||||
|
|
||||||
|
void init(PyObject* module)
|
||||||
|
{
|
||||||
|
if (PyType_Ready(&PySideClassInfoType) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Py_INCREF(&PySideClassInfoType);
|
||||||
|
PyModule_AddObject(module, CLASSINFO_CLASS_NAME, ((PyObject*)&PySideClassInfoType));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkType(PyObject* pyObj)
|
||||||
|
{
|
||||||
|
if (pyObj)
|
||||||
|
return PyType_IsSubtype(pyObj->ob_type, &PySideClassInfoType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QByteArray, QByteArray> getMap(PySideClassInfo* obj)
|
||||||
|
{
|
||||||
|
return obj->d->m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace Property
|
||||||
|
} //namespace PySide
|
||||||
51
libpyside/pysideclassinfo.h
Normal file
51
libpyside/pysideclassinfo.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the PySide project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
*
|
||||||
|
* Contact: PySide team <contact@pyside.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYSIDE_CLASSINFO_H
|
||||||
|
#define PYSIDE_CLASSINFO_H
|
||||||
|
|
||||||
|
#include <pysidemacros.h>
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
extern PYSIDE_API PyTypeObject PySideClassInfoType;
|
||||||
|
|
||||||
|
struct PySideClassInfoPrivate;
|
||||||
|
struct PYSIDE_API PySideClassInfo
|
||||||
|
{
|
||||||
|
PyObject_HEAD
|
||||||
|
PySideClassInfoPrivate* d;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace PySide { namespace ClassInfo {
|
||||||
|
|
||||||
|
PYSIDE_API bool checkType(PyObject* pyObj);
|
||||||
|
PYSIDE_API QMap<QByteArray, QByteArray> getMap(PySideClassInfo* obj);
|
||||||
|
|
||||||
|
} //namespace ClassInfo
|
||||||
|
} //namespace PySide
|
||||||
|
|
||||||
|
#endif
|
||||||
54
libpyside/pysideclassinfo_p.h
Normal file
54
libpyside/pysideclassinfo_p.h
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the PySide project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
*
|
||||||
|
* Contact: PySide team <contact@pyside.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYSIDE_CLASSINFO_P_H
|
||||||
|
#define PYSIDE_CLASSINFO_P_H
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include "pysideclassinfo.h"
|
||||||
|
|
||||||
|
#define __INFO_ATTR_NAME__ "__classInfo__"
|
||||||
|
|
||||||
|
struct PySideClassInfo;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PySideClassInfoPrivate {
|
||||||
|
QMap<QByteArray, QByteArray> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace PySide { namespace ClassInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init PySide QProperty support system
|
||||||
|
*/
|
||||||
|
void init(PyObject* module);
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ClassInfo
|
||||||
|
} // namespace PySide
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue