diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-12-07 19:10:52 -0200 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-12-08 14:52:58 -0300 |
commit | 354b09e00b57a8f87d53bdcd3cab0e254cd461bd (patch) | |
tree | baa6eb4ef9b9bdcf49485f93d6b7efec40953540 /PySide/QtCore | |
parent | b9ca1774f78c3dbd287b28138aaea6907f839918 (diff) |
Almost all QVariant tests pass.
There is just one test which fail, it'll need some support from libpyside to work.
Reviewed by Marcelo Lira <marcelo.lira@openbossa.org>
Diffstat (limited to 'PySide/QtCore')
-rw-r--r-- | PySide/QtCore/glue/qvariant_converter_impl.cpp | 61 | ||||
-rw-r--r-- | PySide/QtCore/qvariant_conversions.h | 3 | ||||
-rw-r--r-- | PySide/QtCore/typesystem_core.xml | 53 |
3 files changed, 107 insertions, 10 deletions
diff --git a/PySide/QtCore/glue/qvariant_converter_impl.cpp b/PySide/QtCore/glue/qvariant_converter_impl.cpp new file mode 100644 index 000000000..bfead230c --- /dev/null +++ b/PySide/QtCore/glue/qvariant_converter_impl.cpp @@ -0,0 +1,61 @@ +// We use this thin wrapper instead of the plain PyObject pointer to avoid conflicts with specializations of T* +// in QVariant. +struct PyObjectHolder +{ + PyObject* m_me; + PyObjectHolder(PyObject* me) : m_me(me) {} + PyObjectHolder() : m_me(Py_None) {} + operator PyObject*() { return m_me; } +}; + +/** + * Q_DECLARE_METATYPE(PyObjectHolder); + * Use the expanded version of Q_DECLARE_METATYPE macro to define a typename + * compatible with PyQt4 + **/ +QT_BEGIN_NAMESPACE +template <> +struct QMetaTypeId< PyObjectHolder > +{ + enum { Defined = 1 }; + static int qt_metatype_id() + { + static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); + if (!metatype_id) + metatype_id = + qRegisterMetaType<PyObjectHolder>("PyQt_PyObject"); + return metatype_id; + } +}; +QT_END_NAMESPACE + +// all types are convertible to QVariant +bool Shiboken::Converter<QVariant>::isConvertible(PyObject* pyobj) +{ + return true; +} + +PyObject* Shiboken::Converter<QVariant>::toPython(const QVariant& cppobj) +{ + return Converter<QVariant>::createWrapper(new QVariant(cppobj)); +} + +QVariant* Shiboken::Converter<QVariant>::copyCppObject(const QVariant& cppobj) +{ + return new QVariant(cppobj); +} + +QVariant Shiboken::Converter<QVariant>::toCpp(PyObject* pyobj) +{ + if (SbkQVariant_Check(pyobj)) + return *SbkQVariant_cptr(pyobj); + // voodoo stuff to avoid linking qtcore bindings with qtgui bindings + uint typeCode = QMetaType::type(pyobj->ob_type->tp_name); + if (!typeCode || typeCode > QVariant::UserType) { + Py_INCREF(pyobj); + return QVariant::fromValue<PyObjectHolder>(pyobj); + } else { + // Is a known Qt type + return QVariant(typeCode, reinterpret_cast<SbkBaseWrapper*>(pyobj)->cptr); + } +} diff --git a/PySide/QtCore/qvariant_conversions.h b/PySide/QtCore/qvariant_conversions.h new file mode 100644 index 000000000..2f96f1dab --- /dev/null +++ b/PySide/QtCore/qvariant_conversions.h @@ -0,0 +1,3 @@ + +// This is just a place holder to avoid automatic generation of the QVariant converter, +// The QVariant converter implementation is inside a glue code called qvariant_converter_impl.cpp diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index 1c31d8873..cb12f1f37 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -1297,21 +1297,14 @@ </modify-function> </object-type> <value-type name="QVariant"> + <conversion-rule file="qvariant_conversions.h" /> <modify-function signature="create(int,const void*)" remove="all" /> - <modify-function signature="QVariant(const char*)" remove="all"/> <modify-function signature="QVariant(int, const void*)" remove="all"/> - <modify-function signature="QVariant(uint)" remove="all"/> - <!-- handled by inject code --> - <modify-function signature="QVariant(int)" remove="all"/> <!-- handled by inject code --> - <modify-function signature="QVariant(double)" remove="all"/> + <modify-function signature="QVariant(uint)" remove="all"/> <modify-function signature="QVariant(qulonglong)" remove="all"/> - <modify-function signature="QVariant(qlonglong)" remove="all"/> - <modify-function signature="QVariant(bool)" remove="all" /> - <!-- QByteArray ctor MUST be declared before QString ctor --> <modify-function signature="QVariant(const QByteArray&)" remove="all"/> - <!-- Support QVariant as PyQt4.5 does --> <modify-function signature="QVariant(QDataStream&)" remove="all"/> <modify-function signature="QVariant(const QBitArray&)" remove="all"/> <modify-function signature="QVariant(const QString&)" remove="all"/> @@ -1330,6 +1323,46 @@ <modify-function signature="QVariant(const QUrl&)" remove="all"/> <modify-function signature="QVariant(const QLocale&)" remove="all"/> <modify-function signature="QVariant(const QRegExp&)" remove="all"/> + <modify-function signature="QVariant(QHash<QString,QVariant>)" remove="all" /> + <modify-function signature="QVariant(QMap<QString,QVariant>)" remove="all" /> + <modify-function signature="QVariant(QList<QVariant>)" remove="all" /> + <modify-function signature="QVariant(QVariant)" remove="all" /> + <modify-function signature="QVariant(QLine)" remove="all" /> + <modify-function signature="QVariant(QLineF)" remove="all" /> + + <inject-code class="native" position="beginning" file="glue/qvariant_converter_impl.cpp" /> + <add-function signature="QVariant(PyObject*)"> + <inject-code class="target" position="beginning"> + cptr = new QVariant(Shiboken::Converter<QVariant>::toCpp(%PYARG_1)); + </inject-code> + </add-function> + <add-function signature="toPyObject()" return-type="PyObject*"> + <inject-code class="target" position="beginning"> + const char* type_name = %CPPSELF.typeName(); + uint type_id = QMetaType::type(type_name); + if (!type_id || type_id > QVariant::UserType) { + %PYARG_0 = %CPPSELF.value<PyObjectHolder>(); + } else { + %PYARG_0 = Py_None; + Py_INCREF(Py_None); + } + </inject-code> + </add-function> + <modify-function signature="typeName()const"> + <inject-code class="target" position="beginning"> + if (%CPPSELF.isNull()) { + %PYARG_0 = Py_None; + Py_INCREF(Py_None); + } else if (%CPPSELF.userType() == QMetaTypeId<PyObjectHolder>::qt_metatype_id()) { + // emulate PyQt4 behaviour + PyObject* obj = %CPPSELF.value<PyObjectHolder>(); + if (PySequence_Check(obj)) + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE]("QVariantList"); + } + if (!%PYARG_0) + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%CPPSELF.typeName()); + </inject-code> + </modify-function> <modify-function signature="toDouble(bool*)const"> <modify-argument index="1"> <remove-argument/> @@ -1386,7 +1419,7 @@ PyErr_SetString(PyExc_IndexError, "index out of bounds"); return 0; } - return %CONVERTTOPYTHON[%TYPE](%CPPSELF.at(_i)); + return %CONVERTTOPYTHON[QString](%CPPSELF.at(_i)); </inject-code> </add-function> <add-function signature="__setitem__"> |