aboutsummaryrefslogtreecommitdiffstats
path: root/PySide
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2010-12-08 16:52:23 -0200
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:47:57 -0300
commit3df02f96815b2183ff9b49db6e46db7700d5bc1e (patch)
treeee9fd395f09cb5a02a50f83cb4c5d71ff0f1e929 /PySide
parent8252145146de231387173d9b7beac284159f4b61 (diff)
Add support for QML list properties.
Reviewer: Marcelo Lira <marcelo.lira@openbossa.org> Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'PySide')
-rw-r--r--PySide/QtDeclarative/pysideqmlregistertype.cpp212
-rw-r--r--PySide/QtDeclarative/pysideqmlregistertype.h23
-rw-r--r--PySide/QtDeclarative/typesystem_declarative.xml4
3 files changed, 228 insertions, 11 deletions
diff --git a/PySide/QtDeclarative/pysideqmlregistertype.cpp b/PySide/QtDeclarative/pysideqmlregistertype.cpp
index 5a5170601..362e56d67 100644
--- a/PySide/QtDeclarative/pysideqmlregistertype.cpp
+++ b/PySide/QtDeclarative/pysideqmlregistertype.cpp
@@ -21,19 +21,32 @@
*/
#include "pysideqmlregistertype.h"
-#include <Python.h>
+// Qt
#include <QObject>
#include <QDeclarativeEngine>
#include <QMutex>
+// shiboken
#include <typeresolver.h>
-#include "qdeclarativeitem_wrapper.h"
#include <sbkdbg.h>
+// pyside
+#include <pyside.h>
+#include <dynamicqmetaobject.h>
+#include <pysideproperty.h>
+
+// auto generated headers
+#include "qdeclarativeitem_wrapper.h"
+#include "pyside_qtcore_python.h"
+#include "pyside_qtdeclarative_python.h"
#ifndef PYSIDE_MAX_QML_TYPES
// Maximum number of different types the user cna export to QML using qmlRegisterType.
#define PYSIDE_MAX_QML_TYPES 50
#endif
+// Forward declarations
+static void propListMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::Call call, void** args);
+
+
// All registered python types
static PyObject* pyTypes[PYSIDE_MAX_QML_TYPES];
static void (*createFuncs[PYSIDE_MAX_QML_TYPES])(void*);
@@ -76,11 +89,6 @@ struct ElementFactory<0> : ElementFactoryBase<0>
}
};
-void PySide::initQmlSupport()
-{
- ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init();
-}
-
int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, int versionMinor, const char* qmlName)
{
using namespace Shiboken;
@@ -138,3 +146,193 @@ int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor,
++nextType;
return qmlTypeId;
}
+
+extern "C"
+{
+
+// This is the user data we store in the property.
+struct DeclarativeListProperty
+{
+ PyTypeObject* type;
+ PyObject* append;
+ PyObject* at;
+ PyObject* clear;
+ PyObject* count;
+};
+
+static int propListTpInit(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ static const char *kwlist[] = {"type", "append", "at", "clear", "count", 0};
+ PySideProperty* pySelf = reinterpret_cast<PySideProperty*>(self);
+ DeclarativeListProperty* data = new DeclarativeListProperty;
+ memset(data, 0, sizeof(DeclarativeListProperty));
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "OO|OOO:QtDeclarative.ListProperty", (char**) kwlist,
+ &data->type,
+ &data->append,
+ &data->at,
+ &data->clear,
+ &data->count)) {
+ return 0;
+ }
+ PySide::Property::setMetaCallHandler(pySelf, &propListMetaCall);
+ PySide::Property::setTypeName(pySelf, "QDeclarativeListProperty<QDeclarativeItem>");
+ PySide::Property::setUserData(pySelf, data);
+
+ return 1;
+}
+
+void propListTpFree(void* self)
+{
+ PySideProperty* pySelf = reinterpret_cast<PySideProperty*>(self);
+ delete reinterpret_cast<DeclarativeListProperty*>(PySide::Property::userData(pySelf));
+ // calls base type constructor
+ pySelf->ob_type->tp_base->tp_free(self);
+}
+
+PyTypeObject PropertyListType = {
+ PyObject_HEAD_INIT(0)
+ 0, /*ob_size*/
+ "ListProperty", /*tp_name*/
+ sizeof(PySideProperty), /*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 */
+ 0, /*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 */
+ &PySidePropertyType, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ propListTpInit, /*tp_init */
+ 0, /*tp_alloc */
+ 0, /*tp_new */
+ propListTpFree, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+};
+
+} // extern "C"
+
+// Implementation of QDeclarativeListProperty<T>::AppendFunction callback
+void propListAppender(QDeclarativeListProperty<QDeclarativeItem>* propList, QDeclarativeItem* item)
+{
+ Shiboken::AutoDecRef args(Shiboken::makeTuple(propList->object, item));
+
+ DeclarativeListProperty* data = reinterpret_cast<DeclarativeListProperty*>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->append, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// Implementation of QDeclarativeListProperty<T>::CountFunction callback
+int propListCount(QDeclarativeListProperty<QDeclarativeItem>* propList)
+{
+ Shiboken::AutoDecRef args(Shiboken::makeTuple(propList->object));
+
+ DeclarativeListProperty* data = reinterpret_cast<DeclarativeListProperty*>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->count, args));
+
+ // Check return type
+ if (PyErr_Occurred())
+ PyErr_Print();
+ else if (Shiboken::Converter<int>::isConvertible(retVal))
+ return Shiboken::Converter<int>::toCpp(retVal);
+
+ return 0;
+}
+
+// Implementation of QDeclarativeListProperty<T>::AtFunction callback
+QDeclarativeItem* propListAt(QDeclarativeListProperty<QDeclarativeItem>* propList, int index)
+{
+ Shiboken::AutoDecRef args(Shiboken::makeTuple(propList->object, index));
+
+ DeclarativeListProperty* data = reinterpret_cast<DeclarativeListProperty*>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->at, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+ else if (PyType_IsSubtype(Py_TYPE(retVal), data->type))
+ return Shiboken::Converter<QDeclarativeItem*>::toCpp(retVal);
+
+ return 0;
+}
+
+// Implementation of QDeclarativeListProperty<T>::ClearFunction callback
+void propListClear(QDeclarativeListProperty<QDeclarativeItem>* propList)
+{
+ Shiboken::AutoDecRef args(Shiboken::makeTuple(propList->object));
+
+ DeclarativeListProperty* data = reinterpret_cast<DeclarativeListProperty*>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->clear, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// qt_metacall specialization for ListProperties
+static void propListMetaCall(PySideProperty* pp, PyObject* self, QMetaObject::Call call, void** args)
+{
+ if (call != QMetaObject::ReadProperty)
+ return;
+
+ DeclarativeListProperty* data = reinterpret_cast<DeclarativeListProperty*>(PySide::Property::userData(pp));
+ QDeclarativeListProperty<QDeclarativeItem> declProp(Shiboken::Converter<QObject*>::toCpp(self), data, &propListAppender);
+
+ if (data->count)
+ declProp.count = &propListCount;
+ if (data->at)
+ declProp.at = &propListAt;
+ if (data->clear)
+ declProp.clear = &propListClear;
+
+ // Copy the data to the memory location requested by the meta call
+ void* v = args[0];
+ *reinterpret_cast<QDeclarativeListProperty<QDeclarativeItem>*>(v) = declProp;
+}
+
+
+void PySide::initQmlSupport(PyObject* module)
+{
+ ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init();
+
+ // Export DeclarativeListProperty type
+ if (PyType_Ready(&PropertyListType) < 0)
+ return;
+
+ Py_INCREF((PyObject*)&PropertyListType);
+ PyModule_AddObject(module, PropertyListType.tp_name, (PyObject*)&PropertyListType);
+
+}
+
+
diff --git a/PySide/QtDeclarative/pysideqmlregistertype.h b/PySide/QtDeclarative/pysideqmlregistertype.h
index 11a5a9a2e..aa2520049 100644
--- a/PySide/QtDeclarative/pysideqmlregistertype.h
+++ b/PySide/QtDeclarative/pysideqmlregistertype.h
@@ -23,14 +23,33 @@
#ifndef PYSIDEQMLREGISTERTYPE_H
#define PYSIDEQMLREGISTERTYPE_H
-#include <basewrapper.h>
+#include <Python.h>
+
+struct SbkObjectType;
namespace PySide
{
extern void* nextQmlElementMemoryAddr;
-void initQmlSupport();
+/**
+ * Init the QML support doign things like registering QtDeclarative.ListProperty and create the necessary stuff for
+ * qmlRegisterType.
+ *
+ * \param module QtDeclarative python module
+ */
+void initQmlSupport(PyObject* module);
+
+/**
+ * PySide implementation of qmlRegisterType<T> function.
+ *
+ * \param pyObj Python type to be registered.
+ * \param uri QML element uri.
+ * \param versionMajor QML component major version.
+ * \param versionMinor QML component minor version.
+ * \param qmlName QML element name
+ * \return the metatype id of the registered type.
+ */
int qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, int versionMinor, const char* qmlName);
}
diff --git a/PySide/QtDeclarative/typesystem_declarative.xml b/PySide/QtDeclarative/typesystem_declarative.xml
index cc666024a..d1424abff 100644
--- a/PySide/QtDeclarative/typesystem_declarative.xml
+++ b/PySide/QtDeclarative/typesystem_declarative.xml
@@ -58,9 +58,9 @@
</extra-includes>
</enum-type>
- <inject-code>
+ <inject-code class="target" position="end">
Shiboken::TypeResolver::createValueTypeResolver&lt; QList&lt;QObject*&gt; &gt;("QList&lt;QObject*&gt;");
- PySide::initQmlSupport();
+ PySide::initQmlSupport(module);
</inject-code>
<object-type name="QDeclarativeExtensionInterface"/>