@@ -1,204 +1,210 | |||||
1 | #ifndef _PYTHONQTCONVERSION_H |
|
1 | #ifndef _PYTHONQTCONVERSION_H | |
2 | #define _PYTHONQTCONVERSION_H |
|
2 | #define _PYTHONQTCONVERSION_H | |
3 |
|
3 | |||
4 | /* |
|
4 | /* | |
5 | * |
|
5 | * | |
6 | * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved. |
|
6 | * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved. | |
7 | * |
|
7 | * | |
8 | * This library is free software; you can redistribute it and/or |
|
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public |
|
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either |
|
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. |
|
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * |
|
12 | * | |
13 | * This library is distributed in the hope that it will be useful, |
|
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. |
|
16 | * Lesser General Public License for more details. | |
17 | * |
|
17 | * | |
18 | * Further, this software is distributed without any warranty that it is |
|
18 | * Further, this software is distributed without any warranty that it is | |
19 | * free of the rightful claim of any third person regarding infringement |
|
19 | * free of the rightful claim of any third person regarding infringement | |
20 | * or the like. Any license provided herein, whether implied or |
|
20 | * or the like. Any license provided herein, whether implied or | |
21 | * otherwise, applies only to this software file. Patent licenses, if |
|
21 | * otherwise, applies only to this software file. Patent licenses, if | |
22 | * any, provided herein do not apply to combinations of this program with |
|
22 | * any, provided herein do not apply to combinations of this program with | |
23 | * other software, or any other product whatsoever. |
|
23 | * other software, or any other product whatsoever. | |
24 | * |
|
24 | * | |
25 | * You should have received a copy of the GNU Lesser General Public |
|
25 | * You should have received a copy of the GNU Lesser General Public | |
26 | * License along with this library; if not, write to the Free Software |
|
26 | * License along with this library; if not, write to the Free Software | |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
28 | * |
|
28 | * | |
29 | * Contact information: MeVis Research GmbH, Universitaetsallee 29, |
|
29 | * Contact information: MeVis Research GmbH, Universitaetsallee 29, | |
30 | * 28359 Bremen, Germany or: |
|
30 | * 28359 Bremen, Germany or: | |
31 | * |
|
31 | * | |
32 | * http://www.mevis.de |
|
32 | * http://www.mevis.de | |
33 | * |
|
33 | * | |
34 | */ |
|
34 | */ | |
35 |
|
35 | |||
36 | //---------------------------------------------------------------------------------- |
|
36 | //---------------------------------------------------------------------------------- | |
37 | /*! |
|
37 | /*! | |
38 | // \file PythonQtConversion.h |
|
38 | // \file PythonQtConversion.h | |
39 | // \author Florian Link |
|
39 | // \author Florian Link | |
40 | // \author Last changed by $Author: florian $ |
|
40 | // \author Last changed by $Author: florian $ | |
41 | // \date 2006-05 |
|
41 | // \date 2006-05 | |
42 | */ |
|
42 | */ | |
43 | //---------------------------------------------------------------------------------- |
|
43 | //---------------------------------------------------------------------------------- | |
44 |
|
44 | |||
45 | #include "PythonQt.h" |
|
45 | #include "PythonQt.h" | |
46 | #include "PythonQtMisc.h" |
|
46 | #include "PythonQtMisc.h" | |
47 | #include "PythonQtClassInfo.h" |
|
47 | #include "PythonQtClassInfo.h" | |
48 | #include "PythonQtMethodInfo.h" |
|
48 | #include "PythonQtMethodInfo.h" | |
49 |
|
49 | |||
50 | #include <QWidget> |
|
50 | #include <QWidget> | |
51 | #include <QList> |
|
51 | #include <QList> | |
52 | #include <vector> |
|
52 | #include <vector> | |
53 |
|
53 | |||
54 | typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId); |
|
54 | typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId); | |
55 | typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict); |
|
55 | typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict); | |
56 |
|
56 | |||
57 | #define PythonQtRegisterListTemplateConverter(type, innertype) \ |
|
57 | #define PythonQtRegisterListTemplateConverter(type, innertype) \ | |
58 | { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \ |
|
58 | { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \ | |
59 | PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \ |
|
59 | PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \ | |
60 | PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \ |
|
60 | PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \ | |
61 | } |
|
61 | } | |
62 |
|
62 | |||
63 | #define PythonQtRegisterToolClassesTemplateConverter(innertype) \ |
|
63 | #define PythonQtRegisterToolClassesTemplateConverter(innertype) \ | |
64 | PythonQtRegisterListTemplateConverter(QList, innertype); \ |
|
64 | PythonQtRegisterListTemplateConverter(QList, innertype); \ | |
65 | PythonQtRegisterListTemplateConverter(QVector, innertype); \ |
|
65 | PythonQtRegisterListTemplateConverter(QVector, innertype); \ | |
66 | PythonQtRegisterListTemplateConverter(std::vector, innertype); |
|
66 | PythonQtRegisterListTemplateConverter(std::vector, innertype); | |
67 | // TODO: add QHash etc. here! |
|
67 | // TODO: add QHash etc. here! | |
68 |
|
68 | |||
69 | //! a static class that offers methods for type conversion |
|
69 | //! a static class that offers methods for type conversion | |
70 | class PYTHONQT_EXPORT PythonQtConv { |
|
70 | class PYTHONQT_EXPORT PythonQtConv { | |
71 |
|
71 | |||
72 | public: |
|
72 | public: | |
73 |
|
73 | |||
74 | //! get a ref counted True or False Python object |
|
74 | //! get a ref counted True or False Python object | |
75 | static PyObject* GetPyBool(bool val); |
|
75 | static PyObject* GetPyBool(bool val); | |
76 |
|
76 | |||
77 | //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object, |
|
77 | //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object, | |
78 | static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data); |
|
78 | static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data); | |
79 |
|
79 | |||
80 | //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore) |
|
80 | //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore) | |
81 | static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL); |
|
81 | static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL); | |
82 |
|
82 | |||
83 | //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall |
|
83 | //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall | |
84 | static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info); |
|
84 | static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info); | |
85 |
|
85 | |||
86 | //! converts QString to Python string (unicode!) |
|
86 | //! converts QString to Python string (unicode!) | |
87 | static PyObject* QStringToPyObject(const QString& str); |
|
87 | static PyObject* QStringToPyObject(const QString& str); | |
88 |
|
88 | |||
89 | //! converts QStringList to Python tuple |
|
89 | //! converts QStringList to Python tuple | |
90 | static PyObject* QStringListToPyObject(const QStringList& list); |
|
90 | static PyObject* QStringListToPyObject(const QStringList& list); | |
91 |
|
91 | |||
92 | //! converts QStringList to Python list |
|
92 | //! converts QStringList to Python list | |
93 | static PyObject* QStringListToPyList(const QStringList& list); |
|
93 | static PyObject* QStringListToPyList(const QStringList& list); | |
94 |
|
94 | |||
95 | //! get string representation of py object |
|
95 | //! get string representation of py object | |
96 | static QString PyObjGetRepresentation(PyObject* val); |
|
96 | static QString PyObjGetRepresentation(PyObject* val); | |
97 |
|
97 | |||
98 | //! get string value from py object |
|
98 | //! get string value from py object | |
99 | static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; } |
|
99 | static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; } | |
100 | //! get string value from py object |
|
100 | //! get string value from py object | |
101 | static QString PyObjGetString(PyObject* val, bool strict, bool &ok); |
|
101 | static QString PyObjGetString(PyObject* val, bool strict, bool &ok); | |
102 | //! get bytes from py object |
|
102 | //! get bytes from py object | |
103 | static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok); |
|
103 | static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok); | |
104 | //! get int from py object |
|
104 | //! get int from py object | |
105 | static int PyObjGetInt(PyObject* val, bool strict, bool &ok); |
|
105 | static int PyObjGetInt(PyObject* val, bool strict, bool &ok); | |
106 | //! get int64 from py object |
|
106 | //! get int64 from py object | |
107 | static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok); |
|
107 | static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok); | |
108 | //! get int64 from py object |
|
108 | //! get int64 from py object | |
109 | static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok); |
|
109 | static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok); | |
110 | //! get double from py object |
|
110 | //! get double from py object | |
111 | static double PyObjGetDouble(PyObject* val, bool strict, bool &ok); |
|
111 | static double PyObjGetDouble(PyObject* val, bool strict, bool &ok); | |
112 | //! get bool from py object |
|
112 | //! get bool from py object | |
113 | static bool PyObjGetBool(PyObject* val, bool strict, bool &ok); |
|
113 | static bool PyObjGetBool(PyObject* val, bool strict, bool &ok); | |
114 |
|
114 | |||
115 | //! create a string list from python sequence |
|
115 | //! create a string list from python sequence | |
116 | static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok); |
|
116 | static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok); | |
117 |
|
117 | |||
118 | //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise |
|
118 | //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise | |
119 | //! it will guess from the python type |
|
119 | //! it will guess from the python type | |
120 | static QVariant PyObjToQVariant(PyObject* val, int type = -1); |
|
120 | static QVariant PyObjToQVariant(PyObject* val, int type = -1); | |
121 |
|
121 | |||
122 | //! convert QVariant from PyObject |
|
122 | //! convert QVariant from PyObject | |
123 | static PyObject* QVariantToPyObject(const QVariant& v); |
|
123 | static PyObject* QVariantToPyObject(const QVariant& v); | |
124 |
|
124 | |||
125 | static PyObject* QVariantMapToPyObject(const QVariantMap& m); |
|
125 | static PyObject* QVariantMapToPyObject(const QVariantMap& m); | |
126 | static PyObject* QVariantListToPyObject(const QVariantList& l); |
|
126 | static PyObject* QVariantListToPyObject(const QVariantList& l); | |
127 |
|
127 | |||
128 | //! get human readable string from CPP object (when the metatype is known) |
|
128 | //! get human readable string from CPP object (when the metatype is known) | |
129 | static QString CPPObjectToString(int type, const void* data); |
|
129 | static QString CPPObjectToString(int type, const void* data); | |
130 |
|
130 | |||
131 | //! register a converter callback from python to cpp for given metatype |
|
131 | //! register a converter callback from python to cpp for given metatype | |
132 | static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); } |
|
132 | static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); } | |
133 |
|
133 | |||
134 | //! register a converter callback from cpp to python for given metatype |
|
134 | //! register a converter callback from cpp to python for given metatype | |
135 | static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); } |
|
135 | static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); } | |
136 |
|
136 | |||
137 | //! returns the inner type id of a simple template of the form SomeObject<InnerType> |
|
137 | //! returns the inner type id of a simple template of the form SomeObject<InnerType> | |
138 | static int getInnerTemplateMetaType(const QByteArray& typeName); |
|
138 | static int getInnerTemplateMetaType(const QByteArray& typeName); | |
139 |
|
139 | |||
140 | //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object, |
|
140 | //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object, | |
141 | static PyObject* ConvertQtValueToPythonInternal(int type, const void* data); |
|
141 | static PyObject* ConvertQtValueToPythonInternal(int type, const void* data); | |
142 |
|
142 | |||
143 | public: |
|
143 | public: | |
144 |
|
144 | |||
145 | static PythonQtValueStorage<qint64, 128> global_valueStorage; |
|
145 | static PythonQtValueStorage<qint64, 128> global_valueStorage; | |
146 | static PythonQtValueStorage<void*, 128> global_ptrStorage; |
|
146 | static PythonQtValueStorage<void*, 128> global_ptrStorage; | |
147 | static PythonQtValueStorage<QVariant, 32> global_variantStorage; |
|
147 | static PythonQtValueStorage<QVariant, 32> global_variantStorage; | |
148 |
|
148 | |||
149 | protected: |
|
149 | protected: | |
150 | static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters; |
|
150 | static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters; | |
151 | static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters; |
|
151 | static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters; | |
152 |
|
152 | |||
153 | //! handle automatic conversion of some special types (QColor, QBrush, ...) |
|
153 | //! handle automatic conversion of some special types (QColor, QBrush, ...) | |
154 | static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject); |
|
154 | static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject); | |
155 |
|
155 | |||
156 | //! converts the list of pointers of given type to Python |
|
156 | //! converts the list of pointers of given type to Python | |
157 | static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type); |
|
157 | static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type); | |
158 | //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success |
|
158 | //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success | |
159 | static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict); |
|
159 | static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict); | |
160 |
|
160 | |||
161 | //! cast wrapper to given className if possible |
|
161 | //! cast wrapper to given className if possible | |
162 | static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok); |
|
162 | static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok); | |
163 | }; |
|
163 | }; | |
164 |
|
164 | |||
165 | template<class ListType, class T> |
|
165 | template<class ListType, class T> | |
166 | PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId) |
|
166 | PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId) | |
167 | { |
|
167 | { | |
168 | ListType* list = (ListType*)inList; |
|
168 | ListType* list = (ListType*)inList; | |
169 | static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId))); |
|
169 | static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId))); | |
|
170 | if (innerType == QVariant::Invalid) { | |||
|
171 | std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl; | |||
|
172 | } | |||
170 | PyObject* result = PyTuple_New(list->size()); |
|
173 | PyObject* result = PyTuple_New(list->size()); | |
171 | int i = 0; |
|
174 | int i = 0; | |
172 | foreach (const T& value, *list) { |
|
175 | foreach (const T& value, *list) { | |
173 | PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value)); |
|
176 | PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value)); | |
174 | i++; |
|
177 | i++; | |
175 | } |
|
178 | } | |
176 | return result; |
|
179 | return result; | |
177 | } |
|
180 | } | |
178 |
|
181 | |||
179 | template<class ListType, class T> |
|
182 | template<class ListType, class T> | |
180 | bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/) |
|
183 | bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/) | |
181 | { |
|
184 | { | |
182 | ListType* list = (ListType*)outList; |
|
185 | ListType* list = (ListType*)outList; | |
183 | static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId))); |
|
186 | static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId))); | |
|
187 | if (innerType == QVariant::Invalid) { | |||
|
188 | std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl; | |||
|
189 | } | |||
184 | bool result = false; |
|
190 | bool result = false; | |
185 | if (PySequence_Check(obj)) { |
|
191 | if (PySequence_Check(obj)) { | |
186 | result = true; |
|
192 | result = true; | |
187 | int count = PySequence_Size(obj); |
|
193 | int count = PySequence_Size(obj); | |
188 | PyObject* value; |
|
194 | PyObject* value; | |
189 | for (int i = 0;i<count;i++) { |
|
195 | for (int i = 0;i<count;i++) { | |
190 | value = PySequence_GetItem(obj,i); |
|
196 | value = PySequence_GetItem(obj,i); | |
191 | // this is quite some overhead, but it avoids having another large switch... |
|
197 | // this is quite some overhead, but it avoids having another large switch... | |
192 | QVariant v = PythonQtConv::PyObjToQVariant(value, innerType); |
|
198 | QVariant v = PythonQtConv::PyObjToQVariant(value, innerType); | |
193 | if (v.isValid()) { |
|
199 | if (v.isValid()) { | |
194 | list->push_back(qVariantValue<T>(v)); |
|
200 | list->push_back(qVariantValue<T>(v)); | |
195 | } else { |
|
201 | } else { | |
196 | result = false; |
|
202 | result = false; | |
197 | break; |
|
203 | break; | |
198 | } |
|
204 | } | |
199 | } |
|
205 | } | |
200 | } |
|
206 | } | |
201 | return result; |
|
207 | return result; | |
202 | } |
|
208 | } | |
203 |
|
209 | |||
204 | #endif |
|
210 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now