/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef PYSIDECONVERSIONS_H #define PYSIDECONVERSIONS_H #include #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::Object::checkType(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::Object::cppPointer(reinterpret_cast(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::Object::checkType(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::Object::cppPointer(reinterpret_cast(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::Object::checkType(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::Object::cppPointer(reinterpret_cast(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) { return reinterpret_cast(PySide::QFlags::newObject(cppObj, Shiboken::SbkType())); } static inline T toCpp(PyObject* pyObj) { /* this was long. Needed int in Qt5 */ int val = 0; if (Shiboken::Enum::check(pyObj)) { val = Shiboken::Enum::getValue(pyObj); } else if (PyObject_TypeCheck(pyObj, Shiboken::SbkType())) { val = PySide::QFlags::getValue(reinterpret_cast(pyObj)); } else if (PyNumber_Check(pyObj)) { Shiboken::AutoDecRef pyLong(PyNumber_Long(pyObj)); val = PyLong_AsLong(pyLong.object()); } else { PyErr_BadArgument(); } return T(QFlag(val)); } }; #endif