##// END OF EJS Templates
improved enum overload handling...
florianlink -
r57:50a844a82951
parent child
Show More
@@ -1,1129 +1,1131
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtConversion.cpp
35 // \file PythonQtConversion.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (!info.isPointer) {
65 if (!info.isPointer) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 // (TODO: check what happens if this is a pointer type?!)
83 // (TODO: check what happens if this is a pointer type?!)
84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
85 if (innerType.endsWith("*")) {
85 if (innerType.endsWith("*")) {
86 innerType.truncate(innerType.length()-1);
86 innerType.truncate(innerType.length()-1);
87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
88 }
88 }
89 }
89 }
90
90
91 if (info.typeId >= QMetaType::User) {
91 if (info.typeId >= QMetaType::User) {
92 // if a converter is registered, we use is:
92 // if a converter is registered, we use is:
93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
94 if (converter) {
94 if (converter) {
95 return (*converter)(data, info.typeId);
95 return (*converter)(data, info.typeId);
96 }
96 }
97 }
97 }
98
98
99 // special handling did not match, so we convert the usual way (either pointer or value version):
99 // special handling did not match, so we convert the usual way (either pointer or value version):
100 if (info.isPointer) {
100 if (info.isPointer) {
101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
103 } else {
103 } else {
104 // handle values that are not yet handled and not pointers
104 // handle values that are not yet handled and not pointers
105 return ConvertQtValueToPythonInternal(info.typeId, data);
105 return ConvertQtValueToPythonInternal(info.typeId, data);
106 }
106 }
107 }
107 }
108
108
109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
110 switch (type) {
110 switch (type) {
111 case QMetaType::Void:
111 case QMetaType::Void:
112 Py_INCREF(Py_None);
112 Py_INCREF(Py_None);
113 return Py_None;
113 return Py_None;
114 case QMetaType::Char:
114 case QMetaType::Char:
115 return PyInt_FromLong(*((char*)data));
115 return PyInt_FromLong(*((char*)data));
116 case QMetaType::UChar:
116 case QMetaType::UChar:
117 return PyInt_FromLong(*((unsigned char*)data));
117 return PyInt_FromLong(*((unsigned char*)data));
118 case QMetaType::Short:
118 case QMetaType::Short:
119 return PyInt_FromLong(*((short*)data));
119 return PyInt_FromLong(*((short*)data));
120 case QMetaType::UShort:
120 case QMetaType::UShort:
121 return PyInt_FromLong(*((unsigned short*)data));
121 return PyInt_FromLong(*((unsigned short*)data));
122 case QMetaType::Long:
122 case QMetaType::Long:
123 return PyInt_FromLong(*((long*)data));
123 return PyInt_FromLong(*((long*)data));
124 case QMetaType::ULong:
124 case QMetaType::ULong:
125 // does not fit into simple int of python
125 // does not fit into simple int of python
126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
127 case QMetaType::Bool:
127 case QMetaType::Bool:
128 return PythonQtConv::GetPyBool(*((bool*)data));
128 return PythonQtConv::GetPyBool(*((bool*)data));
129 case QMetaType::Int:
129 case QMetaType::Int:
130 return PyInt_FromLong(*((int*)data));
130 return PyInt_FromLong(*((int*)data));
131 case QMetaType::UInt:
131 case QMetaType::UInt:
132 return PyInt_FromLong(*((unsigned int*)data));
132 return PyInt_FromLong(*((unsigned int*)data));
133 case QMetaType::QChar:
133 case QMetaType::QChar:
134 return PyInt_FromLong(*((short*)data));
134 return PyInt_FromLong(*((short*)data));
135 case QMetaType::Float:
135 case QMetaType::Float:
136 return PyFloat_FromDouble(*((float*)data));
136 return PyFloat_FromDouble(*((float*)data));
137 case QMetaType::Double:
137 case QMetaType::Double:
138 return PyFloat_FromDouble(*((double*)data));
138 return PyFloat_FromDouble(*((double*)data));
139 case QMetaType::LongLong:
139 case QMetaType::LongLong:
140 return PyLong_FromLongLong(*((qint64*)data));
140 return PyLong_FromLongLong(*((qint64*)data));
141 case QMetaType::ULongLong:
141 case QMetaType::ULongLong:
142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
143 case QMetaType::QByteArray: {
143 case QMetaType::QByteArray: {
144 QByteArray* v = (QByteArray*) data;
144 QByteArray* v = (QByteArray*) data;
145 return PyString_FromStringAndSize(*v, v->size());
145 return PyString_FromStringAndSize(*v, v->size());
146 }
146 }
147 case QMetaType::QVariantMap:
147 case QMetaType::QVariantMap:
148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
149 case QMetaType::QVariantList:
149 case QMetaType::QVariantList:
150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
151 case QMetaType::QString:
151 case QMetaType::QString:
152 return PythonQtConv::QStringToPyObject(*((QString*)data));
152 return PythonQtConv::QStringToPyObject(*((QString*)data));
153 case QMetaType::QStringList:
153 case QMetaType::QStringList:
154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
155
155
156 case PythonQtMethodInfo::Variant:
156 case PythonQtMethodInfo::Variant:
157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
158 case QMetaType::QObjectStar:
158 case QMetaType::QObjectStar:
159 case QMetaType::QWidgetStar:
159 case QMetaType::QWidgetStar:
160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
161
161
162 default:
162 default:
163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
166 Py_INCREF(o);
166 Py_INCREF(o);
167 return o;
167 return o;
168 } else {
168 } else {
169 if (type > 0) {
169 if (type > 0) {
170 // if the type is known, we can construct it via QMetaType::construct
170 // if the type is known, we can construct it via QMetaType::construct
171 void* newCPPObject = QMetaType::construct(type, data);
171 void* newCPPObject = QMetaType::construct(type, data);
172 // XXX this could be optimized by using metatypeid directly
172 // XXX this could be optimized by using metatypeid directly
173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
174 wrap->_ownedByPythonQt = true;
174 wrap->_ownedByPythonQt = true;
175 wrap->_useQMetaTypeDestroy = true;
175 wrap->_useQMetaTypeDestroy = true;
176 return (PyObject*)wrap;
176 return (PyObject*)wrap;
177 }
177 }
178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 }
179 }
180 }
180 }
181 Py_INCREF(Py_None);
181 Py_INCREF(Py_None);
182 return Py_None;
182 return Py_None;
183 }
183 }
184
184
185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
186 void* ptr = NULL;
186 void* ptr = NULL;
187 if (info.isPointer) {
187 if (info.isPointer) {
188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
189 } else if (info.enumWrapper) {
189 } else if (info.enumWrapper) {
190 // create enum return value
190 // create enum return value
191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
192 } else {
192 } else {
193 switch (info.typeId) {
193 switch (info.typeId) {
194 case QMetaType::Char:
194 case QMetaType::Char:
195 case QMetaType::UChar:
195 case QMetaType::UChar:
196 case QMetaType::Short:
196 case QMetaType::Short:
197 case QMetaType::UShort:
197 case QMetaType::UShort:
198 case QMetaType::Long:
198 case QMetaType::Long:
199 case QMetaType::ULong:
199 case QMetaType::ULong:
200 case QMetaType::Bool:
200 case QMetaType::Bool:
201 case QMetaType::Int:
201 case QMetaType::Int:
202 case QMetaType::UInt:
202 case QMetaType::UInt:
203 case QMetaType::QChar:
203 case QMetaType::QChar:
204 case QMetaType::Float:
204 case QMetaType::Float:
205 case QMetaType::Double:
205 case QMetaType::Double:
206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
207 break;
207 break;
208 case PythonQtMethodInfo::Variant:
208 case PythonQtMethodInfo::Variant:
209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
210 // return the ptr to the variant
210 // return the ptr to the variant
211 break;
211 break;
212 default:
212 default:
213 if (info.typeId == PythonQtMethodInfo::Unknown) {
213 if (info.typeId == PythonQtMethodInfo::Unknown) {
214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
215 if (info.name.startsWith("QList<")) {
215 if (info.name.startsWith("QList<")) {
216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
217 if (innerType.endsWith("*")) {
217 if (innerType.endsWith("*")) {
218 static int id = QMetaType::type("QList<void*>");
218 static int id = QMetaType::type("QList<void*>");
219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
220 // return the constData pointer that will be filled with the result value later on
220 // return the constData pointer that will be filled with the result value later on
221 ptr = (void*)((QVariant*)ptr)->constData();
221 ptr = (void*)((QVariant*)ptr)->constData();
222 }
222 }
223 }
223 }
224 }
224 }
225
225
226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
227 // everything else is stored in a QVariant, if we know the meta type...
227 // everything else is stored in a QVariant, if we know the meta type...
228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
229 // return the constData pointer that will be filled with the result value later on
229 // return the constData pointer that will be filled with the result value later on
230 ptr = (void*)((QVariant*)ptr)->constData();
230 ptr = (void*)((QVariant*)ptr)->constData();
231 }
231 }
232 }
232 }
233 }
233 }
234 return ptr;
234 return ptr;
235 }
235 }
236
236
237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
238 {
238 {
239 void* object;
239 void* object;
240 if (wrapper->classInfo()->isCPPWrapper()) {
240 if (wrapper->classInfo()->isCPPWrapper()) {
241 object = wrapper->_wrappedPtr;
241 object = wrapper->_wrappedPtr;
242 } else {
242 } else {
243 QObject* tmp = wrapper->_obj;
243 QObject* tmp = wrapper->_obj;
244 object = tmp;
244 object = tmp;
245 }
245 }
246 if (object) {
246 if (object) {
247 // if we can be upcasted to the given name, we pass the casted pointer in:
247 // if we can be upcasted to the given name, we pass the casted pointer in:
248 object = wrapper->classInfo()->castTo(object, className);
248 object = wrapper->classInfo()->castTo(object, className);
249 ok = object!=NULL;
249 ok = object!=NULL;
250 } else {
250 } else {
251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
252 ok = wrapper->classInfo()->inherits(className);
252 ok = wrapper->classInfo()->inherits(className);
253 }
253 }
254 return object;
254 return object;
255 }
255 }
256
256
257 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
257 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
258 {
258 {
259 bool ok;
259 bool ok;
260 void* ptr = NULL;
260 void* ptr = NULL;
261 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
261 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
262 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
262 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
263 // (the Variant case is handled below in a switch)
263 // (the Variant case is handled below in a switch)
264
264
265 // a C++ wrapper (can be passed as pointer or reference)
265 // a C++ wrapper (can be passed as pointer or reference)
266 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
266 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
267 bool ok;
267 bool ok;
268 void* object = castWrapperTo(wrap, info.name, ok);
268 void* object = castWrapperTo(wrap, info.name, ok);
269 if (ok) {
269 if (ok) {
270 if (info.isPointer) {
270 if (info.isPointer) {
271 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
271 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
272 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
272 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
273 } else {
273 } else {
274 // store the wrapped pointer directly, since we are a reference
274 // store the wrapped pointer directly, since we are a reference
275 ptr = object;
275 ptr = object;
276 }
276 }
277 } else {
277 } else {
278 // not matching
278 // not matching
279 }
279 }
280 } else if (info.isPointer) {
280 } else if (info.isPointer) {
281 // a pointer
281 // a pointer
282 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
282 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
283 {
283 {
284 QString str = PyObjGetString(obj, strict, ok);
284 QString str = PyObjGetString(obj, strict, ok);
285 if (ok) {
285 if (ok) {
286 void* ptr2 = NULL;
286 void* ptr2 = NULL;
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
289 }
289 }
290 } else if (info.name == "PyObject") {
290 } else if (info.name == "PyObject") {
291 // handle low level PyObject directly
291 // handle low level PyObject directly
292 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
292 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
293 } else if (obj == Py_None) {
293 } else if (obj == Py_None) {
294 // None is treated as a NULL ptr
294 // None is treated as a NULL ptr
295 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
295 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
296 } else {
296 } else {
297 // if we are not strict, we try if we are passed a 0 integer
297 // if we are not strict, we try if we are passed a 0 integer
298 if (!strict) {
298 if (!strict) {
299 bool ok;
299 bool ok;
300 int value = PyObjGetInt(obj, true, ok);
300 int value = PyObjGetInt(obj, true, ok);
301 if (ok && value==0) {
301 if (ok && value==0) {
302 // TODOXXX is this wise? or should it be expected from the programmer to use None?
302 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
303 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
303 }
304 }
304 }
305 }
305 }
306 }
306 } else {
307 } else {
307 // not a pointer
308 // not a pointer
308 switch (info.typeId) {
309 switch (info.typeId) {
309 case QMetaType::Char:
310 case QMetaType::Char:
310 {
311 {
311 int val = PyObjGetInt(obj, strict, ok);
312 int val = PyObjGetInt(obj, strict, ok);
312 if (ok) {
313 if (ok) {
313 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
314 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
314 }
315 }
315 }
316 }
316 break;
317 break;
317 case QMetaType::UChar:
318 case QMetaType::UChar:
318 {
319 {
319 int val = PyObjGetInt(obj, strict, ok);
320 int val = PyObjGetInt(obj, strict, ok);
320 if (ok) {
321 if (ok) {
321 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
322 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
322 }
323 }
323 }
324 }
324 break;
325 break;
325 case QMetaType::Short:
326 case QMetaType::Short:
326 {
327 {
327 int val = PyObjGetInt(obj, strict, ok);
328 int val = PyObjGetInt(obj, strict, ok);
328 if (ok) {
329 if (ok) {
329 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
330 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
330 }
331 }
331 }
332 }
332 break;
333 break;
333 case QMetaType::UShort:
334 case QMetaType::UShort:
334 {
335 {
335 int val = PyObjGetInt(obj, strict, ok);
336 int val = PyObjGetInt(obj, strict, ok);
336 if (ok) {
337 if (ok) {
337 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
338 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
338 }
339 }
339 }
340 }
340 break;
341 break;
341 case QMetaType::Long:
342 case QMetaType::Long:
342 {
343 {
343 long val = (long)PyObjGetLongLong(obj, strict, ok);
344 long val = (long)PyObjGetLongLong(obj, strict, ok);
344 if (ok) {
345 if (ok) {
345 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
346 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
346 }
347 }
347 }
348 }
348 break;
349 break;
349 case QMetaType::ULong:
350 case QMetaType::ULong:
350 {
351 {
351 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
352 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
352 if (ok) {
353 if (ok) {
353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
354 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
354 }
355 }
355 }
356 }
356 break;
357 break;
357 case QMetaType::Bool:
358 case QMetaType::Bool:
358 {
359 {
359 bool val = PyObjGetBool(obj, strict, ok);
360 bool val = PyObjGetBool(obj, strict, ok);
360 if (ok) {
361 if (ok) {
361 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
362 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
362 }
363 }
363 }
364 }
364 break;
365 break;
365 case QMetaType::Int:
366 case QMetaType::Int:
366 {
367 {
367 int val = PyObjGetInt(obj, strict, ok);
368 int val = PyObjGetInt(obj, strict, ok);
368 if (ok) {
369 if (ok) {
369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
370 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
370 }
371 }
371 }
372 }
372 break;
373 break;
373 case QMetaType::UInt:
374 case QMetaType::UInt:
374 {
375 {
375 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
376 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
376 if (ok) {
377 if (ok) {
377 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
378 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
378 }
379 }
379 }
380 }
380 break;
381 break;
381 case QMetaType::QChar:
382 case QMetaType::QChar:
382 {
383 {
383 int val = PyObjGetInt(obj, strict, ok);
384 int val = PyObjGetInt(obj, strict, ok);
384 if (ok) {
385 if (ok) {
385 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
386 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
386 }
387 }
387 }
388 }
388 break;
389 break;
389 case QMetaType::Float:
390 case QMetaType::Float:
390 {
391 {
391 float val = (float)PyObjGetDouble(obj, strict, ok);
392 float val = (float)PyObjGetDouble(obj, strict, ok);
392 if (ok) {
393 if (ok) {
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
394 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
394 }
395 }
395 }
396 }
396 break;
397 break;
397 case QMetaType::Double:
398 case QMetaType::Double:
398 {
399 {
399 double val = (double)PyObjGetDouble(obj, strict, ok);
400 double val = (double)PyObjGetDouble(obj, strict, ok);
400 if (ok) {
401 if (ok) {
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
402 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
402 }
403 }
403 }
404 }
404 break;
405 break;
405 case QMetaType::LongLong:
406 case QMetaType::LongLong:
406 {
407 {
407 qint64 val = PyObjGetLongLong(obj, strict, ok);
408 qint64 val = PyObjGetLongLong(obj, strict, ok);
408 if (ok) {
409 if (ok) {
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
410 }
411 }
411 }
412 }
412 break;
413 break;
413 case QMetaType::ULongLong:
414 case QMetaType::ULongLong:
414 {
415 {
415 quint64 val = PyObjGetULongLong(obj, strict, ok);
416 quint64 val = PyObjGetULongLong(obj, strict, ok);
416 if (ok) {
417 if (ok) {
417 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
418 }
419 }
419 }
420 }
420 break;
421 break;
421 case QMetaType::QByteArray:
422 case QMetaType::QByteArray:
422 {
423 {
423 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
424 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
424 if (ok) {
425 if (ok) {
425 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
426 ptr = (void*)((QVariant*)ptr)->constData();
427 ptr = (void*)((QVariant*)ptr)->constData();
427 }
428 }
428 }
429 }
429 break;
430 break;
430 case QMetaType::QString:
431 case QMetaType::QString:
431 {
432 {
432 QString str = PyObjGetString(obj, strict, ok);
433 QString str = PyObjGetString(obj, strict, ok);
433 if (ok) {
434 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
435 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
435 ptr = (void*)((QVariant*)ptr)->constData();
436 ptr = (void*)((QVariant*)ptr)->constData();
436 }
437 }
437 }
438 }
438 break;
439 break;
439 case QMetaType::QStringList:
440 case QMetaType::QStringList:
440 {
441 {
441 QStringList l = PyObjToStringList(obj, strict, ok);
442 QStringList l = PyObjToStringList(obj, strict, ok);
442 if (ok) {
443 if (ok) {
443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
444 ptr = (void*)((QVariant*)ptr)->constData();
445 ptr = (void*)((QVariant*)ptr)->constData();
445 }
446 }
446 }
447 }
447 break;
448 break;
448
449
449 case PythonQtMethodInfo::Variant:
450 case PythonQtMethodInfo::Variant:
450 {
451 {
451 QVariant v = PyObjToQVariant(obj);
452 QVariant v = PyObjToQVariant(obj);
452 if (v.isValid()) {
453 if (v.isValid()) {
453 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
454 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
454 }
455 }
455 }
456 }
456 break;
457 break;
457 default:
458 default:
458 {
459 {
459 // check for enum case
460 // check for enum case
460 if (info.enumWrapper) {
461 if (info.enumWrapper) {
461 unsigned int val;
462 unsigned int val;
462 if ((PyObject*)obj->ob_type == info.enumWrapper) {
463 if ((PyObject*)obj->ob_type == info.enumWrapper) {
463 // we have a direct enum type match:
464 // we have a exact enum type match:
464 val = PyInt_AS_LONG(obj);
465 val = PyInt_AS_LONG(obj);
465 ok = true;
466 ok = true;
466 } else {
467 } else if (!strict) {
467 // we try to get an integer, and in strict mode, it may not be a derived int class, so that no other enum can be taken as an int
468 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
468 val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
469 // we want an integer overload to be taken first!
470 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
469 }
471 }
470 if (ok) {
472 if (ok) {
471 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
473 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
472 return ptr;
474 return ptr;
473 } else {
475 } else {
474 return NULL;
476 return NULL;
475 }
477 }
476 }
478 }
477
479
478 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
480 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
479 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
481 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
480 if (info.name.startsWith("QList<")) {
482 if (info.name.startsWith("QList<")) {
481 QByteArray innerType = info.name.mid(6,info.name.length()-7);
483 QByteArray innerType = info.name.mid(6,info.name.length()-7);
482 if (innerType.endsWith("*")) {
484 if (innerType.endsWith("*")) {
483 innerType.truncate(innerType.length()-1);
485 innerType.truncate(innerType.length()-1);
484 static int id = QMetaType::type("QList<void*>");
486 static int id = QMetaType::type("QList<void*>");
485 if (!alreadyAllocatedCPPObject) {
487 if (!alreadyAllocatedCPPObject) {
486 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
488 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
487 ptr = (void*)((QVariant*)ptr)->constData();
489 ptr = (void*)((QVariant*)ptr)->constData();
488 } else {
490 } else {
489 ptr = alreadyAllocatedCPPObject;
491 ptr = alreadyAllocatedCPPObject;
490 }
492 }
491 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
493 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
492 if (ok) {
494 if (ok) {
493 return ptr;
495 return ptr;
494 } else {
496 } else {
495 return NULL;
497 return NULL;
496 }
498 }
497 }
499 }
498 }
500 }
499 }
501 }
500
502
501 // We only do this for registered type > QMetaType::User for performance reasons.
503 // We only do this for registered type > QMetaType::User for performance reasons.
502 if (info.typeId >= QMetaType::User) {
504 if (info.typeId >= QMetaType::User) {
503 // Maybe we have a special converter that is registered for that type:
505 // Maybe we have a special converter that is registered for that type:
504 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
506 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
505 if (converter) {
507 if (converter) {
506 if (!alreadyAllocatedCPPObject) {
508 if (!alreadyAllocatedCPPObject) {
507 // create a new empty variant of concrete type:
509 // create a new empty variant of concrete type:
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
510 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
509 ptr = (void*)((QVariant*)ptr)->constData();
511 ptr = (void*)((QVariant*)ptr)->constData();
510 } else {
512 } else {
511 ptr = alreadyAllocatedCPPObject;
513 ptr = alreadyAllocatedCPPObject;
512 }
514 }
513 // now call the converter, passing the internal object of the variant
515 // now call the converter, passing the internal object of the variant
514 ok = (*converter)(obj, ptr, info.typeId, strict);
516 ok = (*converter)(obj, ptr, info.typeId, strict);
515 if (ok) {
517 if (ok) {
516 return ptr;
518 return ptr;
517 } else {
519 } else {
518 return NULL;
520 return NULL;
519 }
521 }
520 }
522 }
521 }
523 }
522 // if no type id is available, conversion to a QVariant makes no sense/is not possible
524 // if no type id is available, conversion to a QVariant makes no sense/is not possible
523 if (info.typeId != PythonQtMethodInfo::Unknown) {
525 if (info.typeId != PythonQtMethodInfo::Unknown) {
524 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
526 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
525 QVariant v = PyObjToQVariant(obj, info.typeId);
527 QVariant v = PyObjToQVariant(obj, info.typeId);
526 if (v.isValid()) {
528 if (v.isValid()) {
527 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
529 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
528 ptr = (void*)((QVariant*)ptr)->constData();
530 ptr = (void*)((QVariant*)ptr)->constData();
529 }
531 }
530 }
532 }
531 }
533 }
532 }
534 }
533 }
535 }
534 return ptr;
536 return ptr;
535 }
537 }
536
538
537
539
538 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
540 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
539 QStringList v;
541 QStringList v;
540 ok = false;
542 ok = false;
541 // if we are strict, we do not want to convert a string to a stringlist
543 // if we are strict, we do not want to convert a string to a stringlist
542 // (strings in python are detected to be sequences)
544 // (strings in python are detected to be sequences)
543 if (strict &&
545 if (strict &&
544 (val->ob_type == &PyString_Type ||
546 (val->ob_type == &PyString_Type ||
545 PyUnicode_Check(val))) {
547 PyUnicode_Check(val))) {
546 ok = false;
548 ok = false;
547 return v;
549 return v;
548 }
550 }
549 if (PySequence_Check(val)) {
551 if (PySequence_Check(val)) {
550 int count = PySequence_Size(val);
552 int count = PySequence_Size(val);
551 for (int i = 0;i<count;i++) {
553 for (int i = 0;i<count;i++) {
552 PyObject* value = PySequence_GetItem(val,i);
554 PyObject* value = PySequence_GetItem(val,i);
553 v.append(PyObjGetString(value,false,ok));
555 v.append(PyObjGetString(value,false,ok));
554 }
556 }
555 ok = true;
557 ok = true;
556 }
558 }
557 return v;
559 return v;
558 }
560 }
559
561
560 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
562 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
561 {
563 {
562 QString r;
564 QString r;
563 PyObject* str = PyObject_Repr(val);
565 PyObject* str = PyObject_Repr(val);
564 if (str) {
566 if (str) {
565 r = QString(PyString_AS_STRING(str));
567 r = QString(PyString_AS_STRING(str));
566 Py_DECREF(str);
568 Py_DECREF(str);
567 }
569 }
568 return r;
570 return r;
569 }
571 }
570
572
571 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
573 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
572 QString r;
574 QString r;
573 ok = true;
575 ok = true;
574 if (val->ob_type == &PyString_Type) {
576 if (val->ob_type == &PyString_Type) {
575 r = QString(PyString_AS_STRING(val));
577 r = QString(PyString_AS_STRING(val));
576 } else if (PyUnicode_Check(val)) {
578 } else if (PyUnicode_Check(val)) {
577 #ifdef WIN32
579 #ifdef WIN32
578 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
580 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
579 #else
581 #else
580 PyObject *ptmp = PyUnicode_AsUTF8String(val);
582 PyObject *ptmp = PyUnicode_AsUTF8String(val);
581 if(ptmp) {
583 if(ptmp) {
582 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
584 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
583 Py_DECREF(ptmp);
585 Py_DECREF(ptmp);
584 }
586 }
585 #endif
587 #endif
586 } else if (!strict) {
588 } else if (!strict) {
587 // EXTRA: could also use _Unicode, but why should we?
589 // EXTRA: could also use _Unicode, but why should we?
588 PyObject* str = PyObject_Str(val);
590 PyObject* str = PyObject_Str(val);
589 if (str) {
591 if (str) {
590 r = QString(PyString_AS_STRING(str));
592 r = QString(PyString_AS_STRING(str));
591 Py_DECREF(str);
593 Py_DECREF(str);
592 } else {
594 } else {
593 ok = false;
595 ok = false;
594 }
596 }
595 } else {
597 } else {
596 ok = false;
598 ok = false;
597 }
599 }
598 return r;
600 return r;
599 }
601 }
600
602
601 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
603 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
602 QByteArray r;
604 QByteArray r;
603 ok = true;
605 ok = true;
604 if (val->ob_type == &PyString_Type) {
606 if (val->ob_type == &PyString_Type) {
605 long size = PyString_GET_SIZE(val);
607 long size = PyString_GET_SIZE(val);
606 r = QByteArray(PyString_AS_STRING(val), size);
608 r = QByteArray(PyString_AS_STRING(val), size);
607 } else {
609 } else {
608 ok = false;
610 ok = false;
609 }
611 }
610 return r;
612 return r;
611 }
613 }
612
614
613 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
615 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
614 bool d = false;
616 bool d = false;
615 ok = false;
617 ok = false;
616 if (val == Py_False) {
618 if (val == Py_False) {
617 d = false;
619 d = false;
618 ok = true;
620 ok = true;
619 } else if (val == Py_True) {
621 } else if (val == Py_True) {
620 d = true;
622 d = true;
621 ok = true;
623 ok = true;
622 } else if (!strict) {
624 } else if (!strict) {
623 d = PyObjGetInt(val, false, ok)!=0;
625 d = PyObjGetInt(val, false, ok)!=0;
624 ok = true;
626 ok = true;
625 }
627 }
626 return d;
628 return d;
627 }
629 }
628
630
629 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
631 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
630 int d = 0;
632 int d = 0;
631 ok = true;
633 ok = true;
632 if (val->ob_type == &PyInt_Type) {
634 if (val->ob_type == &PyInt_Type) {
633 d = PyInt_AS_LONG(val);
635 d = PyInt_AS_LONG(val);
634 } else if (!strict) {
636 } else if (!strict) {
635 if (PyObject_TypeCheck(val, &PyInt_Type)) {
637 if (PyObject_TypeCheck(val, &PyInt_Type)) {
636 // support for derived int classes, e.g. for our enums
638 // support for derived int classes, e.g. for our enums
637 d = PyInt_AS_LONG(val);
639 d = PyInt_AS_LONG(val);
638 } else if (val->ob_type == &PyFloat_Type) {
640 } else if (val->ob_type == &PyFloat_Type) {
639 d = floor(PyFloat_AS_DOUBLE(val));
641 d = floor(PyFloat_AS_DOUBLE(val));
640 } else if (val->ob_type == &PyLong_Type) {
642 } else if (val->ob_type == &PyLong_Type) {
641 // handle error on overflow!
643 // handle error on overflow!
642 d = PyLong_AsLong(val);
644 d = PyLong_AsLong(val);
643 } else if (val == Py_False) {
645 } else if (val == Py_False) {
644 d = 0;
646 d = 0;
645 } else if (val == Py_True) {
647 } else if (val == Py_True) {
646 d = 1;
648 d = 1;
647 } else {
649 } else {
648 ok = false;
650 ok = false;
649 }
651 }
650 } else {
652 } else {
651 ok = false;
653 ok = false;
652 }
654 }
653 return d;
655 return d;
654 }
656 }
655
657
656 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
658 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
657 qint64 d = 0;
659 qint64 d = 0;
658 ok = true;
660 ok = true;
659 if (val->ob_type == &PyInt_Type) {
661 if (val->ob_type == &PyInt_Type) {
660 d = PyInt_AS_LONG(val);
662 d = PyInt_AS_LONG(val);
661 } else if (val->ob_type == &PyLong_Type) {
663 } else if (val->ob_type == &PyLong_Type) {
662 d = PyLong_AsLongLong(val);
664 d = PyLong_AsLongLong(val);
663 } else if (!strict) {
665 } else if (!strict) {
664 if (PyObject_TypeCheck(val, &PyInt_Type)) {
666 if (PyObject_TypeCheck(val, &PyInt_Type)) {
665 // support for derived int classes, e.g. for our enums
667 // support for derived int classes, e.g. for our enums
666 d = PyInt_AS_LONG(val);
668 d = PyInt_AS_LONG(val);
667 } else if (val->ob_type == &PyFloat_Type) {
669 } else if (val->ob_type == &PyFloat_Type) {
668 d = floor(PyFloat_AS_DOUBLE(val));
670 d = floor(PyFloat_AS_DOUBLE(val));
669 } else if (val == Py_False) {
671 } else if (val == Py_False) {
670 d = 0;
672 d = 0;
671 } else if (val == Py_True) {
673 } else if (val == Py_True) {
672 d = 1;
674 d = 1;
673 } else {
675 } else {
674 ok = false;
676 ok = false;
675 }
677 }
676 } else {
678 } else {
677 ok = false;
679 ok = false;
678 }
680 }
679 return d;
681 return d;
680 }
682 }
681
683
682 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
684 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
683 quint64 d = 0;
685 quint64 d = 0;
684 ok = true;
686 ok = true;
685 if (PyObject_TypeCheck(val, &PyInt_Type)) {
687 if (PyObject_TypeCheck(val, &PyInt_Type)) {
686 d = PyInt_AS_LONG(val);
688 d = PyInt_AS_LONG(val);
687 } else if (val->ob_type == &PyLong_Type) {
689 } else if (val->ob_type == &PyLong_Type) {
688 d = PyLong_AsLongLong(val);
690 d = PyLong_AsLongLong(val);
689 } else if (!strict) {
691 } else if (!strict) {
690 if (PyObject_TypeCheck(val, &PyInt_Type)) {
692 if (PyObject_TypeCheck(val, &PyInt_Type)) {
691 // support for derived int classes, e.g. for our enums
693 // support for derived int classes, e.g. for our enums
692 d = PyInt_AS_LONG(val);
694 d = PyInt_AS_LONG(val);
693 } else if (val->ob_type == &PyFloat_Type) {
695 } else if (val->ob_type == &PyFloat_Type) {
694 d = floor(PyFloat_AS_DOUBLE(val));
696 d = floor(PyFloat_AS_DOUBLE(val));
695 } else if (val == Py_False) {
697 } else if (val == Py_False) {
696 d = 0;
698 d = 0;
697 } else if (val == Py_True) {
699 } else if (val == Py_True) {
698 d = 1;
700 d = 1;
699 } else {
701 } else {
700 ok = false;
702 ok = false;
701 }
703 }
702 } else {
704 } else {
703 ok = false;
705 ok = false;
704 }
706 }
705 return d;
707 return d;
706 }
708 }
707
709
708 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
710 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
709 double d = 0;
711 double d = 0;
710 ok = true;
712 ok = true;
711 if (val->ob_type == &PyFloat_Type) {
713 if (val->ob_type == &PyFloat_Type) {
712 d = PyFloat_AS_DOUBLE(val);
714 d = PyFloat_AS_DOUBLE(val);
713 } else if (!strict) {
715 } else if (!strict) {
714 if (PyObject_TypeCheck(val, &PyInt_Type)) {
716 if (PyObject_TypeCheck(val, &PyInt_Type)) {
715 d = PyInt_AS_LONG(val);
717 d = PyInt_AS_LONG(val);
716 } else if (val->ob_type == &PyLong_Type) {
718 } else if (val->ob_type == &PyLong_Type) {
717 d = PyLong_AsLong(val);
719 d = PyLong_AsLong(val);
718 } else if (val == Py_False) {
720 } else if (val == Py_False) {
719 d = 0;
721 d = 0;
720 } else if (val == Py_True) {
722 } else if (val == Py_True) {
721 d = 1;
723 d = 1;
722 } else {
724 } else {
723 ok = false;
725 ok = false;
724 }
726 }
725 } else {
727 } else {
726 ok = false;
728 ok = false;
727 }
729 }
728 return d;
730 return d;
729 }
731 }
730
732
731 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
733 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
732 {
734 {
733 QVariant v;
735 QVariant v;
734 bool ok = true;
736 bool ok = true;
735
737
736 if (type==-1) {
738 if (type==-1) {
737 // no special type requested
739 // no special type requested
738 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
740 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
739 type = QVariant::String;
741 type = QVariant::String;
740 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
742 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
741 type = QVariant::Int;
743 type = QVariant::Int;
742 } else if (val->ob_type==&PyLong_Type) {
744 } else if (val->ob_type==&PyLong_Type) {
743 type = QVariant::LongLong;
745 type = QVariant::LongLong;
744 } else if (val->ob_type==&PyFloat_Type) {
746 } else if (val->ob_type==&PyFloat_Type) {
745 type = QVariant::Double;
747 type = QVariant::Double;
746 } else if (val == Py_False || val == Py_True) {
748 } else if (val == Py_False || val == Py_True) {
747 type = QVariant::Bool;
749 type = QVariant::Bool;
748 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
750 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
749 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
751 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
750 // c++ wrapper, check if the class names of the c++ objects match
752 // c++ wrapper, check if the class names of the c++ objects match
751 if (wrap->classInfo()->isCPPWrapper()) {
753 if (wrap->classInfo()->isCPPWrapper()) {
752 if (wrap->classInfo()->metaTypeId()>0) {
754 if (wrap->classInfo()->metaTypeId()>0) {
753 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
755 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
754 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
756 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
755 } else {
757 } else {
756 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
758 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
757 // the pointer here...
759 // the pointer here...
758 // is this worth anything? we loose the knowledge of the cpp object type
760 // is this worth anything? we loose the knowledge of the cpp object type
759 v = qVariantFromValue(wrap->_wrappedPtr);
761 v = qVariantFromValue(wrap->_wrappedPtr);
760 }
762 }
761 } else {
763 } else {
762 // this gives us a QObject pointer
764 // this gives us a QObject pointer
763 QObject* myObject = wrap->_obj;
765 QObject* myObject = wrap->_obj;
764 v = qVariantFromValue(myObject);
766 v = qVariantFromValue(myObject);
765 }
767 }
766 return v;
768 return v;
767 } else if (val->ob_type==&PyDict_Type) {
769 } else if (val->ob_type==&PyDict_Type) {
768 type = QVariant::Map;
770 type = QVariant::Map;
769 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
771 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
770 type = QVariant::List;
772 type = QVariant::List;
771 } else if (val == Py_None) {
773 } else if (val == Py_None) {
772 // none is invalid
774 // none is invalid
773 type = QVariant::Invalid;
775 type = QVariant::Invalid;
774 } else {
776 } else {
775 // this used to be:
777 // this used to be:
776 // type = QVariant::String;
778 // type = QVariant::String;
777 // but now we want to transport the Python Objects directly:
779 // but now we want to transport the Python Objects directly:
778 PythonQtObjectPtr o(val);
780 PythonQtObjectPtr o(val);
779 v = qVariantFromValue(o);
781 v = qVariantFromValue(o);
780 return v;
782 return v;
781 }
783 }
782 }
784 }
783 // special type request:
785 // special type request:
784 switch (type) {
786 switch (type) {
785 case QVariant::Invalid:
787 case QVariant::Invalid:
786 return v;
788 return v;
787 break;
789 break;
788 case QVariant::Int:
790 case QVariant::Int:
789 {
791 {
790 int d = PyObjGetInt(val, false, ok);
792 int d = PyObjGetInt(val, false, ok);
791 if (ok) return QVariant(d);
793 if (ok) return QVariant(d);
792 }
794 }
793 break;
795 break;
794 case QVariant::UInt:
796 case QVariant::UInt:
795 {
797 {
796 int d = PyObjGetInt(val, false,ok);
798 int d = PyObjGetInt(val, false,ok);
797 if (ok) v = QVariant((unsigned int)d);
799 if (ok) v = QVariant((unsigned int)d);
798 }
800 }
799 break;
801 break;
800 case QVariant::Bool:
802 case QVariant::Bool:
801 {
803 {
802 int d = PyObjGetBool(val,false,ok);
804 int d = PyObjGetBool(val,false,ok);
803 if (ok) v = QVariant((bool)(d!=0));
805 if (ok) v = QVariant((bool)(d!=0));
804 }
806 }
805 break;
807 break;
806 case QVariant::Double:
808 case QVariant::Double:
807 {
809 {
808 double d = PyObjGetDouble(val,false,ok);
810 double d = PyObjGetDouble(val,false,ok);
809 if (ok) v = QVariant(d);
811 if (ok) v = QVariant(d);
810 break;
812 break;
811 }
813 }
812 case QMetaType::Float:
814 case QMetaType::Float:
813 {
815 {
814 float d = (float) PyObjGetDouble(val,false,ok);
816 float d = (float) PyObjGetDouble(val,false,ok);
815 if (ok) v = qVariantFromValue(d);
817 if (ok) v = qVariantFromValue(d);
816 break;
818 break;
817 }
819 }
818 case QMetaType::Long:
820 case QMetaType::Long:
819 {
821 {
820 long d = (long) PyObjGetLongLong(val,false,ok);
822 long d = (long) PyObjGetLongLong(val,false,ok);
821 if (ok) v = qVariantFromValue(d);
823 if (ok) v = qVariantFromValue(d);
822 break;
824 break;
823 }
825 }
824 case QMetaType::ULong:
826 case QMetaType::ULong:
825 {
827 {
826 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
828 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
827 if (ok) v = qVariantFromValue(d);
829 if (ok) v = qVariantFromValue(d);
828 break;
830 break;
829 }
831 }
830 case QMetaType::Short:
832 case QMetaType::Short:
831 {
833 {
832 short d = (short) PyObjGetInt(val,false,ok);
834 short d = (short) PyObjGetInt(val,false,ok);
833 if (ok) v = qVariantFromValue(d);
835 if (ok) v = qVariantFromValue(d);
834 break;
836 break;
835 }
837 }
836 case QMetaType::UShort:
838 case QMetaType::UShort:
837 {
839 {
838 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
840 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
839 if (ok) v = qVariantFromValue(d);
841 if (ok) v = qVariantFromValue(d);
840 break;
842 break;
841 }
843 }
842 case QMetaType::Char:
844 case QMetaType::Char:
843 {
845 {
844 char d = (char) PyObjGetInt(val,false,ok);
846 char d = (char) PyObjGetInt(val,false,ok);
845 if (ok) v = qVariantFromValue(d);
847 if (ok) v = qVariantFromValue(d);
846 break;
848 break;
847 }
849 }
848 case QMetaType::UChar:
850 case QMetaType::UChar:
849 {
851 {
850 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
852 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
851 if (ok) v = qVariantFromValue(d);
853 if (ok) v = qVariantFromValue(d);
852 break;
854 break;
853 }
855 }
854
856
855 case QVariant::ByteArray:
857 case QVariant::ByteArray:
856 case QVariant::String:
858 case QVariant::String:
857 {
859 {
858 bool ok;
860 bool ok;
859 v = QVariant(PyObjGetString(val, false, ok));
861 v = QVariant(PyObjGetString(val, false, ok));
860 }
862 }
861 break;
863 break;
862
864
863 // these are important for MeVisLab
865 // these are important for MeVisLab
864 case QVariant::Map:
866 case QVariant::Map:
865 {
867 {
866 if (PyMapping_Check(val)) {
868 if (PyMapping_Check(val)) {
867 QMap<QString,QVariant> map;
869 QMap<QString,QVariant> map;
868 PyObject* items = PyMapping_Items(val);
870 PyObject* items = PyMapping_Items(val);
869 if (items) {
871 if (items) {
870 int count = PyList_Size(items);
872 int count = PyList_Size(items);
871 PyObject* value;
873 PyObject* value;
872 PyObject* key;
874 PyObject* key;
873 PyObject* tuple;
875 PyObject* tuple;
874 for (int i = 0;i<count;i++) {
876 for (int i = 0;i<count;i++) {
875 tuple = PyList_GetItem(items,i);
877 tuple = PyList_GetItem(items,i);
876 key = PyTuple_GetItem(tuple, 0);
878 key = PyTuple_GetItem(tuple, 0);
877 value = PyTuple_GetItem(tuple, 1);
879 value = PyTuple_GetItem(tuple, 1);
878 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
880 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
879 }
881 }
880 Py_DECREF(items);
882 Py_DECREF(items);
881 v = map;
883 v = map;
882 }
884 }
883 }
885 }
884 }
886 }
885 break;
887 break;
886 case QVariant::List:
888 case QVariant::List:
887 if (PySequence_Check(val)) {
889 if (PySequence_Check(val)) {
888 QVariantList list;
890 QVariantList list;
889 int count = PySequence_Size(val);
891 int count = PySequence_Size(val);
890 PyObject* value;
892 PyObject* value;
891 for (int i = 0;i<count;i++) {
893 for (int i = 0;i<count;i++) {
892 value = PySequence_GetItem(val,i);
894 value = PySequence_GetItem(val,i);
893 list.append(PyObjToQVariant(value, -1));
895 list.append(PyObjToQVariant(value, -1));
894 }
896 }
895 v = list;
897 v = list;
896 }
898 }
897 break;
899 break;
898 case QVariant::StringList:
900 case QVariant::StringList:
899 {
901 {
900 bool ok;
902 bool ok;
901 QStringList l = PyObjToStringList(val, false, ok);
903 QStringList l = PyObjToStringList(val, false, ok);
902 if (ok) {
904 if (ok) {
903 v = l;
905 v = l;
904 }
906 }
905 }
907 }
906 break;
908 break;
907
909
908 default:
910 default:
909 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
911 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
910 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
912 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
911 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
913 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
912 // construct a new variant from the C++ object if it has the same meta type
914 // construct a new variant from the C++ object if it has the same meta type
913 v = QVariant(type, wrap->_wrappedPtr);
915 v = QVariant(type, wrap->_wrappedPtr);
914 } else {
916 } else {
915 v = QVariant();
917 v = QVariant();
916 }
918 }
917 } else {
919 } else {
918 v = QVariant();
920 v = QVariant();
919 }
921 }
920 }
922 }
921 return v;
923 return v;
922 }
924 }
923
925
924 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
926 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
925 {
927 {
926 if (str.isNull()) {
928 if (str.isNull()) {
927 return PyString_FromString("");
929 return PyString_FromString("");
928 } else {
930 } else {
929 #ifdef WIN32
931 #ifdef WIN32
930 // return PyString_FromString(str.toLatin1().data());
932 // return PyString_FromString(str.toLatin1().data());
931 return PyUnicode_FromUnicode(str.utf16(), str.length());
933 return PyUnicode_FromUnicode(str.utf16(), str.length());
932 #else
934 #else
933 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
935 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
934 #endif
936 #endif
935 }
937 }
936 }
938 }
937
939
938 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
940 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
939 {
941 {
940 PyObject* result = PyTuple_New(list.count());
942 PyObject* result = PyTuple_New(list.count());
941 int i = 0;
943 int i = 0;
942 QString str;
944 QString str;
943 foreach (str, list) {
945 foreach (str, list) {
944 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
946 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
945 i++;
947 i++;
946 }
948 }
947 // why is the error state bad after this?
949 // why is the error state bad after this?
948 PyErr_Clear();
950 PyErr_Clear();
949 return result;
951 return result;
950 }
952 }
951
953
952 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
954 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
953 {
955 {
954 PyObject* result = PyList_New(list.count());
956 PyObject* result = PyList_New(list.count());
955 int i = 0;
957 int i = 0;
956 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
958 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
957 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
959 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
958 i++;
960 i++;
959 }
961 }
960 return result;
962 return result;
961 }
963 }
962
964
963 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
965 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
964 {
966 {
965 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
967 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
966 }
968 }
967
969
968 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
970 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
969 PyObject* result = PyDict_New();
971 PyObject* result = PyDict_New();
970 QVariantMap::const_iterator t = m.constBegin();
972 QVariantMap::const_iterator t = m.constBegin();
971 PyObject* key;
973 PyObject* key;
972 PyObject* val;
974 PyObject* val;
973 for (;t!=m.end();t++) {
975 for (;t!=m.end();t++) {
974 key = QStringToPyObject(t.key());
976 key = QStringToPyObject(t.key());
975 val = QVariantToPyObject(t.value());
977 val = QVariantToPyObject(t.value());
976 PyDict_SetItem(result, key, val);
978 PyDict_SetItem(result, key, val);
977 Py_DECREF(key);
979 Py_DECREF(key);
978 Py_DECREF(val);
980 Py_DECREF(val);
979 }
981 }
980 return result;
982 return result;
981 }
983 }
982
984
983 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
985 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
984 PyObject* result = PyTuple_New(l.count());
986 PyObject* result = PyTuple_New(l.count());
985 int i = 0;
987 int i = 0;
986 QVariant v;
988 QVariant v;
987 foreach (v, l) {
989 foreach (v, l) {
988 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
990 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
989 i++;
991 i++;
990 }
992 }
991 // why is the error state bad after this?
993 // why is the error state bad after this?
992 PyErr_Clear();
994 PyErr_Clear();
993 return result;
995 return result;
994 }
996 }
995
997
996 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
998 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
997 {
999 {
998 PyObject* result = PyTuple_New(list->count());
1000 PyObject* result = PyTuple_New(list->count());
999 int i = 0;
1001 int i = 0;
1000 foreach (void* value, *list) {
1002 foreach (void* value, *list) {
1001 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1003 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1002 i++;
1004 i++;
1003 }
1005 }
1004 return result;
1006 return result;
1005 }
1007 }
1006
1008
1007 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1009 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1008 {
1010 {
1009 bool result = false;
1011 bool result = false;
1010 if (PySequence_Check(obj)) {
1012 if (PySequence_Check(obj)) {
1011 result = true;
1013 result = true;
1012 int count = PySequence_Size(obj);
1014 int count = PySequence_Size(obj);
1013 PyObject* value;
1015 PyObject* value;
1014 for (int i = 0;i<count;i++) {
1016 for (int i = 0;i<count;i++) {
1015 value = PySequence_GetItem(obj,i);
1017 value = PySequence_GetItem(obj,i);
1016 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1018 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1017 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1019 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1018 bool ok;
1020 bool ok;
1019 void* object = castWrapperTo(wrap, type, ok);
1021 void* object = castWrapperTo(wrap, type, ok);
1020 if (ok) {
1022 if (ok) {
1021 list->append(object);
1023 list->append(object);
1022 } else {
1024 } else {
1023 result = false;
1025 result = false;
1024 break;
1026 break;
1025 }
1027 }
1026 }
1028 }
1027 }
1029 }
1028 }
1030 }
1029 return result;
1031 return result;
1030 }
1032 }
1031
1033
1032 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1034 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1033 {
1035 {
1034 int idx = typeName.indexOf("<");
1036 int idx = typeName.indexOf("<");
1035 if (idx>0) {
1037 if (idx>0) {
1036 int idx2 = typeName.indexOf(">");
1038 int idx2 = typeName.indexOf(">");
1037 if (idx2>0) {
1039 if (idx2>0) {
1038 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1040 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1039 return QMetaType::type(innerType.constData());
1041 return QMetaType::type(innerType.constData());
1040 }
1042 }
1041 }
1043 }
1042 return QMetaType::Void;
1044 return QMetaType::Void;
1043 }
1045 }
1044
1046
1045
1047
1046
1048
1047 QString PythonQtConv::qVariantToString(const QVariant& v) {
1049 QString PythonQtConv::qVariantToString(const QVariant& v) {
1048 return CPPObjectToString(v.userType(), v.constData());
1050 return CPPObjectToString(v.userType(), v.constData());
1049 }
1051 }
1050
1052
1051 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1053 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1052 QString r;
1054 QString r;
1053 switch (type) {
1055 switch (type) {
1054 case QVariant::Size: {
1056 case QVariant::Size: {
1055 const QSize* s = static_cast<const QSize*>(data);
1057 const QSize* s = static_cast<const QSize*>(data);
1056 r = QString::number(s->width()) + ", " + QString::number(s->height());
1058 r = QString::number(s->width()) + ", " + QString::number(s->height());
1057 }
1059 }
1058 break;
1060 break;
1059 case QVariant::SizeF: {
1061 case QVariant::SizeF: {
1060 const QSizeF* s = static_cast<const QSizeF*>(data);
1062 const QSizeF* s = static_cast<const QSizeF*>(data);
1061 r = QString::number(s->width()) + ", " + QString::number(s->height());
1063 r = QString::number(s->width()) + ", " + QString::number(s->height());
1062 }
1064 }
1063 break;
1065 break;
1064 case QVariant::Point: {
1066 case QVariant::Point: {
1065 const QPoint* s = static_cast<const QPoint*>(data);
1067 const QPoint* s = static_cast<const QPoint*>(data);
1066 r = QString::number(s->x()) + ", " + QString::number(s->y());
1068 r = QString::number(s->x()) + ", " + QString::number(s->y());
1067 }
1069 }
1068 break;
1070 break;
1069 case QVariant::PointF: {
1071 case QVariant::PointF: {
1070 const QPointF* s = static_cast<const QPointF*>(data);
1072 const QPointF* s = static_cast<const QPointF*>(data);
1071 r = QString::number(s->x()) + ", " + QString::number(s->y());
1073 r = QString::number(s->x()) + ", " + QString::number(s->y());
1072 }
1074 }
1073 break;
1075 break;
1074 case QVariant::Rect: {
1076 case QVariant::Rect: {
1075 const QRect* s = static_cast<const QRect*>(data);
1077 const QRect* s = static_cast<const QRect*>(data);
1076 r = QString::number(s->x()) + ", " + QString::number(s->y());
1078 r = QString::number(s->x()) + ", " + QString::number(s->y());
1077 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1079 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1078 }
1080 }
1079 break;
1081 break;
1080 case QVariant::RectF: {
1082 case QVariant::RectF: {
1081 const QRectF* s = static_cast<const QRectF*>(data);
1083 const QRectF* s = static_cast<const QRectF*>(data);
1082 r = QString::number(s->x()) + ", " + QString::number(s->y());
1084 r = QString::number(s->x()) + ", " + QString::number(s->y());
1083 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1085 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1084 }
1086 }
1085 break;
1087 break;
1086 case QVariant::Date: {
1088 case QVariant::Date: {
1087 const QDate* s = static_cast<const QDate*>(data);
1089 const QDate* s = static_cast<const QDate*>(data);
1088 r = s->toString(Qt::ISODate);
1090 r = s->toString(Qt::ISODate);
1089 }
1091 }
1090 break;
1092 break;
1091 case QVariant::DateTime: {
1093 case QVariant::DateTime: {
1092 const QDateTime* s = static_cast<const QDateTime*>(data);
1094 const QDateTime* s = static_cast<const QDateTime*>(data);
1093 r = s->toString(Qt::ISODate);
1095 r = s->toString(Qt::ISODate);
1094 }
1096 }
1095 break;
1097 break;
1096 case QVariant::Time: {
1098 case QVariant::Time: {
1097 const QTime* s = static_cast<const QTime*>(data);
1099 const QTime* s = static_cast<const QTime*>(data);
1098 r = s->toString(Qt::ISODate);
1100 r = s->toString(Qt::ISODate);
1099 }
1101 }
1100 break;
1102 break;
1101 case QVariant::Pixmap:
1103 case QVariant::Pixmap:
1102 {
1104 {
1103 const QPixmap* s = static_cast<const QPixmap*>(data);
1105 const QPixmap* s = static_cast<const QPixmap*>(data);
1104 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1106 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1105 }
1107 }
1106 break;
1108 break;
1107 case QVariant::Image:
1109 case QVariant::Image:
1108 {
1110 {
1109 const QImage* s = static_cast<const QImage*>(data);
1111 const QImage* s = static_cast<const QImage*>(data);
1110 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1112 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1111 }
1113 }
1112 break;
1114 break;
1113 case QVariant::Url:
1115 case QVariant::Url:
1114 {
1116 {
1115 const QUrl* s = static_cast<const QUrl*>(data);
1117 const QUrl* s = static_cast<const QUrl*>(data);
1116 r = s->toString();
1118 r = s->toString();
1117 }
1119 }
1118 break;
1120 break;
1119 //TODO: add more printing for other variant types
1121 //TODO: add more printing for other variant types
1120 default:
1122 default:
1121 // this creates a copy, but that should not be expensive for typical simple variants
1123 // this creates a copy, but that should not be expensive for typical simple variants
1122 // (but we do not want to do this for our won user types!
1124 // (but we do not want to do this for our won user types!
1123 if (type>0 && type < (int)QVariant::UserType) {
1125 if (type>0 && type < (int)QVariant::UserType) {
1124 QVariant v(type, data);
1126 QVariant v(type, data);
1125 r = v.toString();
1127 r = v.toString();
1126 }
1128 }
1127 }
1129 }
1128 return r;
1130 return r;
1129 }
1131 }
General Comments 0
You need to be logged in to leave comments. Login now