/* * This file is part of the PySide project. * * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * 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 PYSIDECONVERSIONS_H #define PYSIDECONVERSIONS_H #include #include #include template struct QtDictConverter { static inline bool checkType(PyObject* pyObj) { return isConvertible(pyObj); } static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) return true; if ((Shiboken::SbkType() && Shiboken::isShibokenType(pyObj)) || !PyDict_Check(pyObj)) return false; PyObject* key; PyObject* value; Py_ssize_t pos = 0; while (PyDict_Next(pyObj, &pos, &key, &value)) { if (!Shiboken::Converter::isConvertible(key) && !Shiboken::Converter::isConvertible(value)) { return false; } } return true; } static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } static inline PyObject* toPython(const QtDict& cppobj) { PyObject* result = PyDict_New(); typename QtDict::const_iterator it = cppobj.begin(); for (; it != cppobj.end(); ++it) { Shiboken::AutoDecRef keyObj(Shiboken::Converter::toPython(it.key())); Shiboken::AutoDecRef valueObj(Shiboken::Converter::toPython(it.value())); PyDict_SetItem(result, keyObj, valueObj); } return result; } static inline QtDict toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, Shiboken::SbkType())) return *reinterpret_cast(Shiboken::getCppPointer(pyobj, Shiboken::SbkType())); QtDict result; PyObject* key; PyObject* value; Py_ssize_t pos = 0; while (PyDict_Next(pyobj, &pos, &key, &value)) result[Shiboken::Converter::toCpp(key)] = Shiboken::Converter::toCpp(value); return result; } }; template struct QtMultiMapConverter { static inline bool checkType(PyObject* pyObj) { return isConvertible(pyObj); } static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) return true; if ((Shiboken::SbkType() && Shiboken::isShibokenType(pyObj)) || !PyDict_Check(pyObj)) return false; PyObject* key; PyObject* value; Py_ssize_t pos = 0; while (PyDict_Next(pyObj, &pos, &key, &value)) { if (!Shiboken::Converter::isConvertible(key)) { if (PySequence_Check(value)) { for (int i = 0, max = PySequence_Length(value); i < max; ++i) { Shiboken::AutoDecRef item(PySequence_GetItem(value, i)); if (!Shiboken::Converter::isConvertible(value)) return false; } } else if (!Shiboken::Converter::isConvertible(value)) { return false; } } } return true; } static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } static inline PyObject* toPython(const MultiMap& cppObj) { PyObject* result = PyDict_New(); typename MultiMap::const_iterator it = cppObj.begin(); for (; it != cppObj.end(); ++it) { Shiboken::AutoDecRef key(Shiboken::Converter::toPython(it.key())); Shiboken::AutoDecRef value(Shiboken::Converter::toPython(it.value())); PyObject* values = PyDict_GetItem(result, key); bool decRefValues = !values; if (!values) values = PyList_New(0); PyList_Append(values, value); PyDict_SetItem(result, key, values); if (decRefValues) { Py_DECREF(values); } } return result; } static inline MultiMap toCpp(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) return *reinterpret_cast(Shiboken::getCppPointer(pyObj, Shiboken::SbkType())); MultiMap result; PyObject* key; PyObject* value; Py_ssize_t pos = 0; while (PyDict_Next(pyObj, &pos, &key, &value)) result[Shiboken::Converter::toCpp(key)] = Shiboken::Converter::toCpp(value); return result; } }; template struct QSequenceConverter { static inline bool checkType(PyObject* pyObj) { return isConvertible(pyObj); } static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) return true; if ((Shiboken::SbkType() && Shiboken::isShibokenType(pyObj)) || !PySequence_Check(pyObj)) return false; for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { Shiboken::AutoDecRef item(PySequence_GetItem(pyObj, i)); if (!Shiboken::Converter::isConvertible(item)) return false; } return true; } static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } static PyObject* toPython(const T& cppobj) { PyObject* result = PyList_New((int) cppobj.size()); typename T::const_iterator it = cppobj.begin(); for (int idx = 0; it != cppobj.end(); ++it, ++idx) { typename T::value_type vh(*it); PyList_SET_ITEM(result, idx, Shiboken::Converter::toPython(vh)); } return result; } static T toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, Shiboken::SbkType())) return *reinterpret_cast(Shiboken::getCppPointer(pyobj, Shiboken::SbkType())); Shiboken::AutoDecRef fastSequence(PySequence_Fast(pyobj, "Invalid sequence object")); T result; for (int i = 0; i < PySequence_Size(pyobj); i++) { PyObject* pyItem = PySequence_Fast_GET_ITEM(fastSequence.object(), i); result << Shiboken::Converter::toCpp(pyItem); } return result; } }; template struct QFlagsConverter { static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, Shiboken::SbkType()); } static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, Shiboken::SbkType()) || PyObject_TypeCheck(pyObj, Shiboken::SbkType()); } static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } static inline PyObject* toPython(const T& cppObj) { PyObject* qflags = Shiboken::SbkType()->tp_alloc(Shiboken::SbkType(), 0); reinterpret_cast(qflags)->ob_ival = cppObj; return qflags; } static inline T toCpp(PyObject* pyObj) { if (Shiboken::isShibokenEnum(pyObj)) return T(QFlag(reinterpret_cast(pyObj)->ob_ival)); else return T(QFlag(reinterpret_cast(pyObj)->ob_ival)); } }; #endif