aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2011-05-19 18:12:52 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:54:25 -0300
commite13ce9212afb46f86e11f78fee98a1d1e1b1557e (patch)
tree75b6a9c5e616596b2fa5ccda2573d34f22a7dcd3
parent5805ea4e01c463e5eae029a51978bdb1b910aad4 (diff)
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>
-rw-r--r--libpyside/CMakeLists.txt2
-rw-r--r--libpyside/dynamicqmetaobject.cpp47
-rw-r--r--libpyside/dynamicqmetaobject.h2
-rw-r--r--libpyside/pyside.cpp6
-rw-r--r--libpyside/pysideclassinfo.cpp166
-rw-r--r--libpyside/pysideclassinfo.h51
-rw-r--r--libpyside/pysideclassinfo_p.h54
7 files changed, 317 insertions, 11 deletions
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt
index c3d3f8611..2d2a61375 100644
--- a/libpyside/CMakeLists.txt
+++ b/libpyside/CMakeLists.txt
@@ -4,6 +4,7 @@ set(libpyside_SRC
dynamicqmetaobject.cpp
signalmanager.cpp
globalreceiver.cpp
+ pysideclassinfo.cpp
pysidemetafunction.cpp
pysidesignal.cpp
pysideslot.cpp
@@ -35,6 +36,7 @@ set_target_properties(pyside PROPERTIES
set(libpyside_HEADERS
dynamicqmetaobject.h
globalreceiver.h
+ pysideclassinfo.h
pysideconversions.h
pysidemacros.h
signalmanager.h
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
index 73572e3b4..86190fa5d 100644
--- a/libpyside/dynamicqmetaobject.cpp
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -84,6 +84,7 @@ class DynamicQMetaObject::DynamicQMetaObjectPrivate
public:
QList<MethodData> m_methods;
QList<PropertyData> m_properties;
+ QMap<QByteArray, QByteArray> m_info;
QByteArray m_className;
void updateMetaObject(QMetaObject* metaObj);
@@ -380,6 +381,20 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
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,
unsigned int** data,
@@ -409,21 +424,22 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
{
uint n_methods = m_methods.size();
uint n_properties = m_properties.size();
- int header[] = {3, // revision
- 0, // class name index in m_metadata
- 0, 0, // classinfo and classinfo index, not used by us
- n_methods, 0, // method count and method list index
- n_properties, 0, // prop count and prop indexes
- 0, 0, // enum count and enum index
- 0, 0, // constructors
- 0}; // flags
+ uint n_info = m_info.size();
+ int header[] = {3, // revision
+ 0, // class name index in m_metadata
+ n_info, 0, // classinfo and classinfo index
+ n_methods, 0, // method count and method list index
+ n_properties, 0, // prop count and prop indexes
+ 0, 0, // enum count and enum index
+ 0, 0, // constructors
+ 0}; // flags
const int HEADER_LENGHT = sizeof(header)/sizeof(int);
header[5] = HEADER_LENGHT;
// 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*4 + 1];
+ data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*4 + n_info*2 + 1];
std::memcpy(data, header, sizeof(header));
QList<QByteArray> strings;
@@ -431,6 +447,19 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
const int NULL_INDEX = registerString("", &strings); // register a null string
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
writeMethodsData(m_methods, &data, &strings, &index, NULL_INDEX, AccessPublic);
diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h
index 2efeef165..d137e3057 100644
--- a/libpyside/dynamicqmetaobject.h
+++ b/libpyside/dynamicqmetaobject.h
@@ -43,6 +43,8 @@ public:
void addSignal(const char* signal, const char* type = 0);
void addSlot(const char* slot, const char* type = 0);
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 removeSlot(uint index);
diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp
index 4b1c17b6a..a4fcbccf0 100644
--- a/libpyside/pyside.cpp
+++ b/libpyside/pyside.cpp
@@ -22,6 +22,7 @@
#include "pyside.h"
#include "signalmanager.h"
+#include "pysideclassinfo_p.h"
#include "pysideproperty_p.h"
#include "pysideproperty.h"
#include "pysidesignal.h"
@@ -47,6 +48,7 @@ namespace PySide
void init(PyObject *module)
{
+ ClassInfo::init(module);
Signal::init(module);
Slot::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));
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
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);
const char* signalName = PyString_AS_STRING(key);
data->signalName = strdup(signalName);
diff --git a/libpyside/pysideclassinfo.cpp b/libpyside/pysideclassinfo.cpp
new file mode 100644
index 000000000..023f4d723
--- /dev/null
+++ b/libpyside/pysideclassinfo.cpp
@@ -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
diff --git a/libpyside/pysideclassinfo.h b/libpyside/pysideclassinfo.h
new file mode 100644
index 000000000..e13049ed3
--- /dev/null
+++ b/libpyside/pysideclassinfo.h
@@ -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
diff --git a/libpyside/pysideclassinfo_p.h b/libpyside/pysideclassinfo_p.h
new file mode 100644
index 000000000..3b96342f4
--- /dev/null
+++ b/libpyside/pysideclassinfo_p.h
@@ -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