##// END OF EJS Templates
fixed bad initialization of ok, swapped QColor constructors to check the error in test...
florianlink -
r59:a2cbf55b6b26
parent child
Show More
@@ -1,1131 +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 = false;
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;
268 void* object = castWrapperTo(wrap, info.name, ok);
267 void* object = castWrapperTo(wrap, info.name, ok);
269 if (ok) {
268 if (ok) {
270 if (info.isPointer) {
269 if (info.isPointer) {
271 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
270 // 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);
271 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
273 } else {
272 } else {
274 // store the wrapped pointer directly, since we are a reference
273 // store the wrapped pointer directly, since we are a reference
275 ptr = object;
274 ptr = object;
276 }
275 }
277 } else {
276 } else {
278 // not matching
277 // not matching
279 }
278 }
280 } else if (info.isPointer) {
279 } else if (info.isPointer) {
281 // a pointer
280 // a pointer
282 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
281 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
283 {
282 {
284 QString str = PyObjGetString(obj, strict, ok);
283 QString str = PyObjGetString(obj, strict, ok);
285 if (ok) {
284 if (ok) {
286 void* ptr2 = NULL;
285 void* ptr2 = NULL;
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
286 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);
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
289 }
288 }
290 } else if (info.name == "PyObject") {
289 } else if (info.name == "PyObject") {
291 // handle low level PyObject directly
290 // handle low level PyObject directly
292 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
291 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
293 } else if (obj == Py_None) {
292 } else if (obj == Py_None) {
294 // None is treated as a NULL ptr
293 // None is treated as a NULL ptr
295 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
294 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
296 } else {
295 } else {
297 // if we are not strict, we try if we are passed a 0 integer
296 // if we are not strict, we try if we are passed a 0 integer
298 if (!strict) {
297 if (!strict) {
299 bool ok;
298 bool ok;
300 int value = PyObjGetInt(obj, true, ok);
299 int value = PyObjGetInt(obj, true, ok);
301 if (ok && value==0) {
300 if (ok && value==0) {
302 // TODOXXX is this wise? or should it be expected from the programmer to use None?
301 // TODOXXX is this wise? or should it be expected from the programmer to use None?
303 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
302 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
304 }
303 }
305 }
304 }
306 }
305 }
307 } else {
306 } else {
308 // not a pointer
307 // not a pointer
309 switch (info.typeId) {
308 switch (info.typeId) {
310 case QMetaType::Char:
309 case QMetaType::Char:
311 {
310 {
312 int val = PyObjGetInt(obj, strict, ok);
311 int val = PyObjGetInt(obj, strict, ok);
313 if (ok) {
312 if (ok) {
314 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
313 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
315 }
314 }
316 }
315 }
317 break;
316 break;
318 case QMetaType::UChar:
317 case QMetaType::UChar:
319 {
318 {
320 int val = PyObjGetInt(obj, strict, ok);
319 int val = PyObjGetInt(obj, strict, ok);
321 if (ok) {
320 if (ok) {
322 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
321 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
323 }
322 }
324 }
323 }
325 break;
324 break;
326 case QMetaType::Short:
325 case QMetaType::Short:
327 {
326 {
328 int val = PyObjGetInt(obj, strict, ok);
327 int val = PyObjGetInt(obj, strict, ok);
329 if (ok) {
328 if (ok) {
330 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
329 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
331 }
330 }
332 }
331 }
333 break;
332 break;
334 case QMetaType::UShort:
333 case QMetaType::UShort:
335 {
334 {
336 int val = PyObjGetInt(obj, strict, ok);
335 int val = PyObjGetInt(obj, strict, ok);
337 if (ok) {
336 if (ok) {
338 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
337 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
339 }
338 }
340 }
339 }
341 break;
340 break;
342 case QMetaType::Long:
341 case QMetaType::Long:
343 {
342 {
344 long val = (long)PyObjGetLongLong(obj, strict, ok);
343 long val = (long)PyObjGetLongLong(obj, strict, ok);
345 if (ok) {
344 if (ok) {
346 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
345 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
347 }
346 }
348 }
347 }
349 break;
348 break;
350 case QMetaType::ULong:
349 case QMetaType::ULong:
351 {
350 {
352 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
351 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
353 if (ok) {
352 if (ok) {
354 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
355 }
354 }
356 }
355 }
357 break;
356 break;
358 case QMetaType::Bool:
357 case QMetaType::Bool:
359 {
358 {
360 bool val = PyObjGetBool(obj, strict, ok);
359 bool val = PyObjGetBool(obj, strict, ok);
361 if (ok) {
360 if (ok) {
362 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
361 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
363 }
362 }
364 }
363 }
365 break;
364 break;
366 case QMetaType::Int:
365 case QMetaType::Int:
367 {
366 {
368 int val = PyObjGetInt(obj, strict, ok);
367 int val = PyObjGetInt(obj, strict, ok);
369 if (ok) {
368 if (ok) {
370 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
371 }
370 }
372 }
371 }
373 break;
372 break;
374 case QMetaType::UInt:
373 case QMetaType::UInt:
375 {
374 {
376 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
375 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
377 if (ok) {
376 if (ok) {
378 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
377 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
379 }
378 }
380 }
379 }
381 break;
380 break;
382 case QMetaType::QChar:
381 case QMetaType::QChar:
383 {
382 {
384 int val = PyObjGetInt(obj, strict, ok);
383 int val = PyObjGetInt(obj, strict, ok);
385 if (ok) {
384 if (ok) {
386 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
385 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
387 }
386 }
388 }
387 }
389 break;
388 break;
390 case QMetaType::Float:
389 case QMetaType::Float:
391 {
390 {
392 float val = (float)PyObjGetDouble(obj, strict, ok);
391 float val = (float)PyObjGetDouble(obj, strict, ok);
393 if (ok) {
392 if (ok) {
394 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
395 }
394 }
396 }
395 }
397 break;
396 break;
398 case QMetaType::Double:
397 case QMetaType::Double:
399 {
398 {
400 double val = (double)PyObjGetDouble(obj, strict, ok);
399 double val = (double)PyObjGetDouble(obj, strict, ok);
401 if (ok) {
400 if (ok) {
402 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
403 }
402 }
404 }
403 }
405 break;
404 break;
406 case QMetaType::LongLong:
405 case QMetaType::LongLong:
407 {
406 {
408 qint64 val = PyObjGetLongLong(obj, strict, ok);
407 qint64 val = PyObjGetLongLong(obj, strict, ok);
409 if (ok) {
408 if (ok) {
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
411 }
410 }
412 }
411 }
413 break;
412 break;
414 case QMetaType::ULongLong:
413 case QMetaType::ULongLong:
415 {
414 {
416 quint64 val = PyObjGetULongLong(obj, strict, ok);
415 quint64 val = PyObjGetULongLong(obj, strict, ok);
417 if (ok) {
416 if (ok) {
418 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
417 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
419 }
418 }
420 }
419 }
421 break;
420 break;
422 case QMetaType::QByteArray:
421 case QMetaType::QByteArray:
423 {
422 {
424 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
423 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
425 if (ok) {
424 if (ok) {
426 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
425 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
427 ptr = (void*)((QVariant*)ptr)->constData();
426 ptr = (void*)((QVariant*)ptr)->constData();
428 }
427 }
429 }
428 }
430 break;
429 break;
431 case QMetaType::QString:
430 case QMetaType::QString:
432 {
431 {
433 QString str = PyObjGetString(obj, strict, ok);
432 QString str = PyObjGetString(obj, strict, ok);
434 if (ok) {
433 if (ok) {
435 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
436 ptr = (void*)((QVariant*)ptr)->constData();
435 ptr = (void*)((QVariant*)ptr)->constData();
437 }
436 }
438 }
437 }
439 break;
438 break;
440 case QMetaType::QStringList:
439 case QMetaType::QStringList:
441 {
440 {
442 QStringList l = PyObjToStringList(obj, strict, ok);
441 QStringList l = PyObjToStringList(obj, strict, ok);
443 if (ok) {
442 if (ok) {
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
445 ptr = (void*)((QVariant*)ptr)->constData();
444 ptr = (void*)((QVariant*)ptr)->constData();
446 }
445 }
447 }
446 }
448 break;
447 break;
449
448
450 case PythonQtMethodInfo::Variant:
449 case PythonQtMethodInfo::Variant:
451 {
450 {
452 QVariant v = PyObjToQVariant(obj);
451 QVariant v = PyObjToQVariant(obj);
453 if (v.isValid()) {
452 if (v.isValid()) {
454 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
453 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
455 }
454 }
456 }
455 }
457 break;
456 break;
458 default:
457 default:
459 {
458 {
460 // check for enum case
459 // check for enum case
461 if (info.enumWrapper) {
460 if (info.enumWrapper) {
462 unsigned int val;
461 unsigned int val;
462 ok = false;
463 if ((PyObject*)obj->ob_type == info.enumWrapper) {
463 if ((PyObject*)obj->ob_type == info.enumWrapper) {
464 // we have a exact enum type match:
464 // we have a exact enum type match:
465 val = PyInt_AS_LONG(obj);
465 val = PyInt_AS_LONG(obj);
466 ok = true;
466 ok = true;
467 } else if (!strict) {
467 } else if (!strict) {
468 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
468 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
469 // we want an integer overload to be taken first!
469 // we want an integer overload to be taken first!
470 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
470 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
471 }
471 }
472 if (ok) {
472 if (ok) {
473 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);
474 return ptr;
474 return ptr;
475 } else {
475 } else {
476 return NULL;
476 return NULL;
477 }
477 }
478 }
478 }
479
479
480 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
480 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
481 // 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
482 if (info.name.startsWith("QList<")) {
482 if (info.name.startsWith("QList<")) {
483 QByteArray innerType = info.name.mid(6,info.name.length()-7);
483 QByteArray innerType = info.name.mid(6,info.name.length()-7);
484 if (innerType.endsWith("*")) {
484 if (innerType.endsWith("*")) {
485 innerType.truncate(innerType.length()-1);
485 innerType.truncate(innerType.length()-1);
486 static int id = QMetaType::type("QList<void*>");
486 static int id = QMetaType::type("QList<void*>");
487 if (!alreadyAllocatedCPPObject) {
487 if (!alreadyAllocatedCPPObject) {
488 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);
489 ptr = (void*)((QVariant*)ptr)->constData();
489 ptr = (void*)((QVariant*)ptr)->constData();
490 } else {
490 } else {
491 ptr = alreadyAllocatedCPPObject;
491 ptr = alreadyAllocatedCPPObject;
492 }
492 }
493 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
493 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
494 if (ok) {
494 if (ok) {
495 return ptr;
495 return ptr;
496 } else {
496 } else {
497 return NULL;
497 return NULL;
498 }
498 }
499 }
499 }
500 }
500 }
501 }
501 }
502
502
503 // 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.
504 if (info.typeId >= QMetaType::User) {
504 if (info.typeId >= QMetaType::User) {
505 // 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:
506 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
506 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
507 if (converter) {
507 if (converter) {
508 if (!alreadyAllocatedCPPObject) {
508 if (!alreadyAllocatedCPPObject) {
509 // create a new empty variant of concrete type:
509 // create a new empty variant of concrete type:
510 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);
511 ptr = (void*)((QVariant*)ptr)->constData();
511 ptr = (void*)((QVariant*)ptr)->constData();
512 } else {
512 } else {
513 ptr = alreadyAllocatedCPPObject;
513 ptr = alreadyAllocatedCPPObject;
514 }
514 }
515 // now call the converter, passing the internal object of the variant
515 // now call the converter, passing the internal object of the variant
516 ok = (*converter)(obj, ptr, info.typeId, strict);
516 ok = (*converter)(obj, ptr, info.typeId, strict);
517 if (ok) {
517 if (ok) {
518 return ptr;
518 return ptr;
519 } else {
519 } else {
520 return NULL;
520 return NULL;
521 }
521 }
522 }
522 }
523 }
523 }
524 // 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
525 if (info.typeId != PythonQtMethodInfo::Unknown) {
525 if (info.typeId != PythonQtMethodInfo::Unknown) {
526 // 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:
527 QVariant v = PyObjToQVariant(obj, info.typeId);
527 QVariant v = PyObjToQVariant(obj, info.typeId);
528 if (v.isValid()) {
528 if (v.isValid()) {
529 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
529 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
530 ptr = (void*)((QVariant*)ptr)->constData();
530 ptr = (void*)((QVariant*)ptr)->constData();
531 }
531 }
532 }
532 }
533 }
533 }
534 }
534 }
535 }
535 }
536 return ptr;
536 return ptr;
537 }
537 }
538
538
539
539
540 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
540 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
541 QStringList v;
541 QStringList v;
542 ok = false;
542 ok = false;
543 // 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
544 // (strings in python are detected to be sequences)
544 // (strings in python are detected to be sequences)
545 if (strict &&
545 if (strict &&
546 (val->ob_type == &PyString_Type ||
546 (val->ob_type == &PyString_Type ||
547 PyUnicode_Check(val))) {
547 PyUnicode_Check(val))) {
548 ok = false;
548 ok = false;
549 return v;
549 return v;
550 }
550 }
551 if (PySequence_Check(val)) {
551 if (PySequence_Check(val)) {
552 int count = PySequence_Size(val);
552 int count = PySequence_Size(val);
553 for (int i = 0;i<count;i++) {
553 for (int i = 0;i<count;i++) {
554 PyObject* value = PySequence_GetItem(val,i);
554 PyObject* value = PySequence_GetItem(val,i);
555 v.append(PyObjGetString(value,false,ok));
555 v.append(PyObjGetString(value,false,ok));
556 }
556 }
557 ok = true;
557 ok = true;
558 }
558 }
559 return v;
559 return v;
560 }
560 }
561
561
562 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
562 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
563 {
563 {
564 QString r;
564 QString r;
565 PyObject* str = PyObject_Repr(val);
565 PyObject* str = PyObject_Repr(val);
566 if (str) {
566 if (str) {
567 r = QString(PyString_AS_STRING(str));
567 r = QString(PyString_AS_STRING(str));
568 Py_DECREF(str);
568 Py_DECREF(str);
569 }
569 }
570 return r;
570 return r;
571 }
571 }
572
572
573 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
573 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
574 QString r;
574 QString r;
575 ok = true;
575 ok = true;
576 if (val->ob_type == &PyString_Type) {
576 if (val->ob_type == &PyString_Type) {
577 r = QString(PyString_AS_STRING(val));
577 r = QString(PyString_AS_STRING(val));
578 } else if (PyUnicode_Check(val)) {
578 } else if (PyUnicode_Check(val)) {
579 #ifdef WIN32
579 #ifdef WIN32
580 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
580 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
581 #else
581 #else
582 PyObject *ptmp = PyUnicode_AsUTF8String(val);
582 PyObject *ptmp = PyUnicode_AsUTF8String(val);
583 if(ptmp) {
583 if(ptmp) {
584 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
584 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
585 Py_DECREF(ptmp);
585 Py_DECREF(ptmp);
586 }
586 }
587 #endif
587 #endif
588 } else if (!strict) {
588 } else if (!strict) {
589 // EXTRA: could also use _Unicode, but why should we?
589 // EXTRA: could also use _Unicode, but why should we?
590 PyObject* str = PyObject_Str(val);
590 PyObject* str = PyObject_Str(val);
591 if (str) {
591 if (str) {
592 r = QString(PyString_AS_STRING(str));
592 r = QString(PyString_AS_STRING(str));
593 Py_DECREF(str);
593 Py_DECREF(str);
594 } else {
594 } else {
595 ok = false;
595 ok = false;
596 }
596 }
597 } else {
597 } else {
598 ok = false;
598 ok = false;
599 }
599 }
600 return r;
600 return r;
601 }
601 }
602
602
603 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
603 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
604 QByteArray r;
604 QByteArray r;
605 ok = true;
605 ok = true;
606 if (val->ob_type == &PyString_Type) {
606 if (val->ob_type == &PyString_Type) {
607 long size = PyString_GET_SIZE(val);
607 long size = PyString_GET_SIZE(val);
608 r = QByteArray(PyString_AS_STRING(val), size);
608 r = QByteArray(PyString_AS_STRING(val), size);
609 } else {
609 } else {
610 ok = false;
610 ok = false;
611 }
611 }
612 return r;
612 return r;
613 }
613 }
614
614
615 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
615 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
616 bool d = false;
616 bool d = false;
617 ok = false;
617 ok = false;
618 if (val == Py_False) {
618 if (val == Py_False) {
619 d = false;
619 d = false;
620 ok = true;
620 ok = true;
621 } else if (val == Py_True) {
621 } else if (val == Py_True) {
622 d = true;
622 d = true;
623 ok = true;
623 ok = true;
624 } else if (!strict) {
624 } else if (!strict) {
625 d = PyObjGetInt(val, false, ok)!=0;
625 d = PyObjGetInt(val, false, ok)!=0;
626 ok = true;
626 ok = true;
627 }
627 }
628 return d;
628 return d;
629 }
629 }
630
630
631 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
631 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
632 int d = 0;
632 int d = 0;
633 ok = true;
633 ok = true;
634 if (val->ob_type == &PyInt_Type) {
634 if (val->ob_type == &PyInt_Type) {
635 d = PyInt_AS_LONG(val);
635 d = PyInt_AS_LONG(val);
636 } else if (!strict) {
636 } else if (!strict) {
637 if (PyObject_TypeCheck(val, &PyInt_Type)) {
637 if (PyObject_TypeCheck(val, &PyInt_Type)) {
638 // support for derived int classes, e.g. for our enums
638 // support for derived int classes, e.g. for our enums
639 d = PyInt_AS_LONG(val);
639 d = PyInt_AS_LONG(val);
640 } else if (val->ob_type == &PyFloat_Type) {
640 } else if (val->ob_type == &PyFloat_Type) {
641 d = floor(PyFloat_AS_DOUBLE(val));
641 d = floor(PyFloat_AS_DOUBLE(val));
642 } else if (val->ob_type == &PyLong_Type) {
642 } else if (val->ob_type == &PyLong_Type) {
643 // handle error on overflow!
643 // handle error on overflow!
644 d = PyLong_AsLong(val);
644 d = PyLong_AsLong(val);
645 } else if (val == Py_False) {
645 } else if (val == Py_False) {
646 d = 0;
646 d = 0;
647 } else if (val == Py_True) {
647 } else if (val == Py_True) {
648 d = 1;
648 d = 1;
649 } else {
649 } else {
650 ok = false;
650 ok = false;
651 }
651 }
652 } else {
652 } else {
653 ok = false;
653 ok = false;
654 }
654 }
655 return d;
655 return d;
656 }
656 }
657
657
658 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
658 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
659 qint64 d = 0;
659 qint64 d = 0;
660 ok = true;
660 ok = true;
661 if (val->ob_type == &PyInt_Type) {
661 if (val->ob_type == &PyInt_Type) {
662 d = PyInt_AS_LONG(val);
662 d = PyInt_AS_LONG(val);
663 } else if (val->ob_type == &PyLong_Type) {
663 } else if (val->ob_type == &PyLong_Type) {
664 d = PyLong_AsLongLong(val);
664 d = PyLong_AsLongLong(val);
665 } else if (!strict) {
665 } else if (!strict) {
666 if (PyObject_TypeCheck(val, &PyInt_Type)) {
666 if (PyObject_TypeCheck(val, &PyInt_Type)) {
667 // support for derived int classes, e.g. for our enums
667 // support for derived int classes, e.g. for our enums
668 d = PyInt_AS_LONG(val);
668 d = PyInt_AS_LONG(val);
669 } else if (val->ob_type == &PyFloat_Type) {
669 } else if (val->ob_type == &PyFloat_Type) {
670 d = floor(PyFloat_AS_DOUBLE(val));
670 d = floor(PyFloat_AS_DOUBLE(val));
671 } else if (val == Py_False) {
671 } else if (val == Py_False) {
672 d = 0;
672 d = 0;
673 } else if (val == Py_True) {
673 } else if (val == Py_True) {
674 d = 1;
674 d = 1;
675 } else {
675 } else {
676 ok = false;
676 ok = false;
677 }
677 }
678 } else {
678 } else {
679 ok = false;
679 ok = false;
680 }
680 }
681 return d;
681 return d;
682 }
682 }
683
683
684 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
684 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
685 quint64 d = 0;
685 quint64 d = 0;
686 ok = true;
686 ok = true;
687 if (PyObject_TypeCheck(val, &PyInt_Type)) {
687 if (PyObject_TypeCheck(val, &PyInt_Type)) {
688 d = PyInt_AS_LONG(val);
688 d = PyInt_AS_LONG(val);
689 } else if (val->ob_type == &PyLong_Type) {
689 } else if (val->ob_type == &PyLong_Type) {
690 d = PyLong_AsLongLong(val);
690 d = PyLong_AsLongLong(val);
691 } else if (!strict) {
691 } else if (!strict) {
692 if (PyObject_TypeCheck(val, &PyInt_Type)) {
692 if (PyObject_TypeCheck(val, &PyInt_Type)) {
693 // support for derived int classes, e.g. for our enums
693 // support for derived int classes, e.g. for our enums
694 d = PyInt_AS_LONG(val);
694 d = PyInt_AS_LONG(val);
695 } else if (val->ob_type == &PyFloat_Type) {
695 } else if (val->ob_type == &PyFloat_Type) {
696 d = floor(PyFloat_AS_DOUBLE(val));
696 d = floor(PyFloat_AS_DOUBLE(val));
697 } else if (val == Py_False) {
697 } else if (val == Py_False) {
698 d = 0;
698 d = 0;
699 } else if (val == Py_True) {
699 } else if (val == Py_True) {
700 d = 1;
700 d = 1;
701 } else {
701 } else {
702 ok = false;
702 ok = false;
703 }
703 }
704 } else {
704 } else {
705 ok = false;
705 ok = false;
706 }
706 }
707 return d;
707 return d;
708 }
708 }
709
709
710 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
710 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
711 double d = 0;
711 double d = 0;
712 ok = true;
712 ok = true;
713 if (val->ob_type == &PyFloat_Type) {
713 if (val->ob_type == &PyFloat_Type) {
714 d = PyFloat_AS_DOUBLE(val);
714 d = PyFloat_AS_DOUBLE(val);
715 } else if (!strict) {
715 } else if (!strict) {
716 if (PyObject_TypeCheck(val, &PyInt_Type)) {
716 if (PyObject_TypeCheck(val, &PyInt_Type)) {
717 d = PyInt_AS_LONG(val);
717 d = PyInt_AS_LONG(val);
718 } else if (val->ob_type == &PyLong_Type) {
718 } else if (val->ob_type == &PyLong_Type) {
719 d = PyLong_AsLong(val);
719 d = PyLong_AsLong(val);
720 } else if (val == Py_False) {
720 } else if (val == Py_False) {
721 d = 0;
721 d = 0;
722 } else if (val == Py_True) {
722 } else if (val == Py_True) {
723 d = 1;
723 d = 1;
724 } else {
724 } else {
725 ok = false;
725 ok = false;
726 }
726 }
727 } else {
727 } else {
728 ok = false;
728 ok = false;
729 }
729 }
730 return d;
730 return d;
731 }
731 }
732
732
733 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
733 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
734 {
734 {
735 QVariant v;
735 QVariant v;
736 bool ok = true;
736 bool ok = true;
737
737
738 if (type==-1) {
738 if (type==-1) {
739 // no special type requested
739 // no special type requested
740 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
740 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
741 type = QVariant::String;
741 type = QVariant::String;
742 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
742 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
743 type = QVariant::Int;
743 type = QVariant::Int;
744 } else if (val->ob_type==&PyLong_Type) {
744 } else if (val->ob_type==&PyLong_Type) {
745 type = QVariant::LongLong;
745 type = QVariant::LongLong;
746 } else if (val->ob_type==&PyFloat_Type) {
746 } else if (val->ob_type==&PyFloat_Type) {
747 type = QVariant::Double;
747 type = QVariant::Double;
748 } else if (val == Py_False || val == Py_True) {
748 } else if (val == Py_False || val == Py_True) {
749 type = QVariant::Bool;
749 type = QVariant::Bool;
750 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
750 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
751 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
751 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
752 // 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
753 if (wrap->classInfo()->isCPPWrapper()) {
753 if (wrap->classInfo()->isCPPWrapper()) {
754 if (wrap->classInfo()->metaTypeId()>0) {
754 if (wrap->classInfo()->metaTypeId()>0) {
755 // 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!)
756 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
756 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
757 } else {
757 } else {
758 // 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
759 // the pointer here...
759 // the pointer here...
760 // 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
761 v = qVariantFromValue(wrap->_wrappedPtr);
761 v = qVariantFromValue(wrap->_wrappedPtr);
762 }
762 }
763 } else {
763 } else {
764 // this gives us a QObject pointer
764 // this gives us a QObject pointer
765 QObject* myObject = wrap->_obj;
765 QObject* myObject = wrap->_obj;
766 v = qVariantFromValue(myObject);
766 v = qVariantFromValue(myObject);
767 }
767 }
768 return v;
768 return v;
769 } else if (val->ob_type==&PyDict_Type) {
769 } else if (val->ob_type==&PyDict_Type) {
770 type = QVariant::Map;
770 type = QVariant::Map;
771 } 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)) {
772 type = QVariant::List;
772 type = QVariant::List;
773 } else if (val == Py_None) {
773 } else if (val == Py_None) {
774 // none is invalid
774 // none is invalid
775 type = QVariant::Invalid;
775 type = QVariant::Invalid;
776 } else {
776 } else {
777 // this used to be:
777 // this used to be:
778 // type = QVariant::String;
778 // type = QVariant::String;
779 // but now we want to transport the Python Objects directly:
779 // but now we want to transport the Python Objects directly:
780 PythonQtObjectPtr o(val);
780 PythonQtObjectPtr o(val);
781 v = qVariantFromValue(o);
781 v = qVariantFromValue(o);
782 return v;
782 return v;
783 }
783 }
784 }
784 }
785 // special type request:
785 // special type request:
786 switch (type) {
786 switch (type) {
787 case QVariant::Invalid:
787 case QVariant::Invalid:
788 return v;
788 return v;
789 break;
789 break;
790 case QVariant::Int:
790 case QVariant::Int:
791 {
791 {
792 int d = PyObjGetInt(val, false, ok);
792 int d = PyObjGetInt(val, false, ok);
793 if (ok) return QVariant(d);
793 if (ok) return QVariant(d);
794 }
794 }
795 break;
795 break;
796 case QVariant::UInt:
796 case QVariant::UInt:
797 {
797 {
798 int d = PyObjGetInt(val, false,ok);
798 int d = PyObjGetInt(val, false,ok);
799 if (ok) v = QVariant((unsigned int)d);
799 if (ok) v = QVariant((unsigned int)d);
800 }
800 }
801 break;
801 break;
802 case QVariant::Bool:
802 case QVariant::Bool:
803 {
803 {
804 int d = PyObjGetBool(val,false,ok);
804 int d = PyObjGetBool(val,false,ok);
805 if (ok) v = QVariant((bool)(d!=0));
805 if (ok) v = QVariant((bool)(d!=0));
806 }
806 }
807 break;
807 break;
808 case QVariant::Double:
808 case QVariant::Double:
809 {
809 {
810 double d = PyObjGetDouble(val,false,ok);
810 double d = PyObjGetDouble(val,false,ok);
811 if (ok) v = QVariant(d);
811 if (ok) v = QVariant(d);
812 break;
812 break;
813 }
813 }
814 case QMetaType::Float:
814 case QMetaType::Float:
815 {
815 {
816 float d = (float) PyObjGetDouble(val,false,ok);
816 float d = (float) PyObjGetDouble(val,false,ok);
817 if (ok) v = qVariantFromValue(d);
817 if (ok) v = qVariantFromValue(d);
818 break;
818 break;
819 }
819 }
820 case QMetaType::Long:
820 case QMetaType::Long:
821 {
821 {
822 long d = (long) PyObjGetLongLong(val,false,ok);
822 long d = (long) PyObjGetLongLong(val,false,ok);
823 if (ok) v = qVariantFromValue(d);
823 if (ok) v = qVariantFromValue(d);
824 break;
824 break;
825 }
825 }
826 case QMetaType::ULong:
826 case QMetaType::ULong:
827 {
827 {
828 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
828 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
829 if (ok) v = qVariantFromValue(d);
829 if (ok) v = qVariantFromValue(d);
830 break;
830 break;
831 }
831 }
832 case QMetaType::Short:
832 case QMetaType::Short:
833 {
833 {
834 short d = (short) PyObjGetInt(val,false,ok);
834 short d = (short) PyObjGetInt(val,false,ok);
835 if (ok) v = qVariantFromValue(d);
835 if (ok) v = qVariantFromValue(d);
836 break;
836 break;
837 }
837 }
838 case QMetaType::UShort:
838 case QMetaType::UShort:
839 {
839 {
840 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
840 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
841 if (ok) v = qVariantFromValue(d);
841 if (ok) v = qVariantFromValue(d);
842 break;
842 break;
843 }
843 }
844 case QMetaType::Char:
844 case QMetaType::Char:
845 {
845 {
846 char d = (char) PyObjGetInt(val,false,ok);
846 char d = (char) PyObjGetInt(val,false,ok);
847 if (ok) v = qVariantFromValue(d);
847 if (ok) v = qVariantFromValue(d);
848 break;
848 break;
849 }
849 }
850 case QMetaType::UChar:
850 case QMetaType::UChar:
851 {
851 {
852 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
852 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
853 if (ok) v = qVariantFromValue(d);
853 if (ok) v = qVariantFromValue(d);
854 break;
854 break;
855 }
855 }
856
856
857 case QVariant::ByteArray:
857 case QVariant::ByteArray:
858 case QVariant::String:
858 case QVariant::String:
859 {
859 {
860 bool ok;
860 bool ok;
861 v = QVariant(PyObjGetString(val, false, ok));
861 v = QVariant(PyObjGetString(val, false, ok));
862 }
862 }
863 break;
863 break;
864
864
865 // these are important for MeVisLab
865 // these are important for MeVisLab
866 case QVariant::Map:
866 case QVariant::Map:
867 {
867 {
868 if (PyMapping_Check(val)) {
868 if (PyMapping_Check(val)) {
869 QMap<QString,QVariant> map;
869 QMap<QString,QVariant> map;
870 PyObject* items = PyMapping_Items(val);
870 PyObject* items = PyMapping_Items(val);
871 if (items) {
871 if (items) {
872 int count = PyList_Size(items);
872 int count = PyList_Size(items);
873 PyObject* value;
873 PyObject* value;
874 PyObject* key;
874 PyObject* key;
875 PyObject* tuple;
875 PyObject* tuple;
876 for (int i = 0;i<count;i++) {
876 for (int i = 0;i<count;i++) {
877 tuple = PyList_GetItem(items,i);
877 tuple = PyList_GetItem(items,i);
878 key = PyTuple_GetItem(tuple, 0);
878 key = PyTuple_GetItem(tuple, 0);
879 value = PyTuple_GetItem(tuple, 1);
879 value = PyTuple_GetItem(tuple, 1);
880 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
880 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
881 }
881 }
882 Py_DECREF(items);
882 Py_DECREF(items);
883 v = map;
883 v = map;
884 }
884 }
885 }
885 }
886 }
886 }
887 break;
887 break;
888 case QVariant::List:
888 case QVariant::List:
889 if (PySequence_Check(val)) {
889 if (PySequence_Check(val)) {
890 QVariantList list;
890 QVariantList list;
891 int count = PySequence_Size(val);
891 int count = PySequence_Size(val);
892 PyObject* value;
892 PyObject* value;
893 for (int i = 0;i<count;i++) {
893 for (int i = 0;i<count;i++) {
894 value = PySequence_GetItem(val,i);
894 value = PySequence_GetItem(val,i);
895 list.append(PyObjToQVariant(value, -1));
895 list.append(PyObjToQVariant(value, -1));
896 }
896 }
897 v = list;
897 v = list;
898 }
898 }
899 break;
899 break;
900 case QVariant::StringList:
900 case QVariant::StringList:
901 {
901 {
902 bool ok;
902 bool ok;
903 QStringList l = PyObjToStringList(val, false, ok);
903 QStringList l = PyObjToStringList(val, false, ok);
904 if (ok) {
904 if (ok) {
905 v = l;
905 v = l;
906 }
906 }
907 }
907 }
908 break;
908 break;
909
909
910 default:
910 default:
911 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
911 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
912 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
912 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
913 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
913 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
914 // 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
915 v = QVariant(type, wrap->_wrappedPtr);
915 v = QVariant(type, wrap->_wrappedPtr);
916 } else {
916 } else {
917 v = QVariant();
917 v = QVariant();
918 }
918 }
919 } else {
919 } else {
920 v = QVariant();
920 v = QVariant();
921 }
921 }
922 }
922 }
923 return v;
923 return v;
924 }
924 }
925
925
926 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
926 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
927 {
927 {
928 if (str.isNull()) {
928 if (str.isNull()) {
929 return PyString_FromString("");
929 return PyString_FromString("");
930 } else {
930 } else {
931 #ifdef WIN32
931 #ifdef WIN32
932 // return PyString_FromString(str.toLatin1().data());
932 // return PyString_FromString(str.toLatin1().data());
933 return PyUnicode_FromUnicode(str.utf16(), str.length());
933 return PyUnicode_FromUnicode(str.utf16(), str.length());
934 #else
934 #else
935 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);
936 #endif
936 #endif
937 }
937 }
938 }
938 }
939
939
940 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
940 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
941 {
941 {
942 PyObject* result = PyTuple_New(list.count());
942 PyObject* result = PyTuple_New(list.count());
943 int i = 0;
943 int i = 0;
944 QString str;
944 QString str;
945 foreach (str, list) {
945 foreach (str, list) {
946 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
946 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
947 i++;
947 i++;
948 }
948 }
949 // why is the error state bad after this?
949 // why is the error state bad after this?
950 PyErr_Clear();
950 PyErr_Clear();
951 return result;
951 return result;
952 }
952 }
953
953
954 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
954 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
955 {
955 {
956 PyObject* result = PyList_New(list.count());
956 PyObject* result = PyList_New(list.count());
957 int i = 0;
957 int i = 0;
958 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
958 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
959 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
959 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
960 i++;
960 i++;
961 }
961 }
962 return result;
962 return result;
963 }
963 }
964
964
965 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
965 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
966 {
966 {
967 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
967 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
968 }
968 }
969
969
970 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
970 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
971 PyObject* result = PyDict_New();
971 PyObject* result = PyDict_New();
972 QVariantMap::const_iterator t = m.constBegin();
972 QVariantMap::const_iterator t = m.constBegin();
973 PyObject* key;
973 PyObject* key;
974 PyObject* val;
974 PyObject* val;
975 for (;t!=m.end();t++) {
975 for (;t!=m.end();t++) {
976 key = QStringToPyObject(t.key());
976 key = QStringToPyObject(t.key());
977 val = QVariantToPyObject(t.value());
977 val = QVariantToPyObject(t.value());
978 PyDict_SetItem(result, key, val);
978 PyDict_SetItem(result, key, val);
979 Py_DECREF(key);
979 Py_DECREF(key);
980 Py_DECREF(val);
980 Py_DECREF(val);
981 }
981 }
982 return result;
982 return result;
983 }
983 }
984
984
985 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
985 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
986 PyObject* result = PyTuple_New(l.count());
986 PyObject* result = PyTuple_New(l.count());
987 int i = 0;
987 int i = 0;
988 QVariant v;
988 QVariant v;
989 foreach (v, l) {
989 foreach (v, l) {
990 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
990 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
991 i++;
991 i++;
992 }
992 }
993 // why is the error state bad after this?
993 // why is the error state bad after this?
994 PyErr_Clear();
994 PyErr_Clear();
995 return result;
995 return result;
996 }
996 }
997
997
998 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
998 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
999 {
999 {
1000 PyObject* result = PyTuple_New(list->count());
1000 PyObject* result = PyTuple_New(list->count());
1001 int i = 0;
1001 int i = 0;
1002 foreach (void* value, *list) {
1002 foreach (void* value, *list) {
1003 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1003 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1004 i++;
1004 i++;
1005 }
1005 }
1006 return result;
1006 return result;
1007 }
1007 }
1008
1008
1009 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*/)
1010 {
1010 {
1011 bool result = false;
1011 bool result = false;
1012 if (PySequence_Check(obj)) {
1012 if (PySequence_Check(obj)) {
1013 result = true;
1013 result = true;
1014 int count = PySequence_Size(obj);
1014 int count = PySequence_Size(obj);
1015 PyObject* value;
1015 PyObject* value;
1016 for (int i = 0;i<count;i++) {
1016 for (int i = 0;i<count;i++) {
1017 value = PySequence_GetItem(obj,i);
1017 value = PySequence_GetItem(obj,i);
1018 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1018 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1019 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1019 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1020 bool ok;
1020 bool ok;
1021 void* object = castWrapperTo(wrap, type, ok);
1021 void* object = castWrapperTo(wrap, type, ok);
1022 if (ok) {
1022 if (ok) {
1023 list->append(object);
1023 list->append(object);
1024 } else {
1024 } else {
1025 result = false;
1025 result = false;
1026 break;
1026 break;
1027 }
1027 }
1028 }
1028 }
1029 }
1029 }
1030 }
1030 }
1031 return result;
1031 return result;
1032 }
1032 }
1033
1033
1034 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1034 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1035 {
1035 {
1036 int idx = typeName.indexOf("<");
1036 int idx = typeName.indexOf("<");
1037 if (idx>0) {
1037 if (idx>0) {
1038 int idx2 = typeName.indexOf(">");
1038 int idx2 = typeName.indexOf(">");
1039 if (idx2>0) {
1039 if (idx2>0) {
1040 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1040 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1041 return QMetaType::type(innerType.constData());
1041 return QMetaType::type(innerType.constData());
1042 }
1042 }
1043 }
1043 }
1044 return QMetaType::Void;
1044 return QMetaType::Void;
1045 }
1045 }
1046
1046
1047
1047
1048
1048
1049 QString PythonQtConv::qVariantToString(const QVariant& v) {
1049 QString PythonQtConv::qVariantToString(const QVariant& v) {
1050 return CPPObjectToString(v.userType(), v.constData());
1050 return CPPObjectToString(v.userType(), v.constData());
1051 }
1051 }
1052
1052
1053 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1053 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1054 QString r;
1054 QString r;
1055 switch (type) {
1055 switch (type) {
1056 case QVariant::Size: {
1056 case QVariant::Size: {
1057 const QSize* s = static_cast<const QSize*>(data);
1057 const QSize* s = static_cast<const QSize*>(data);
1058 r = QString::number(s->width()) + ", " + QString::number(s->height());
1058 r = QString::number(s->width()) + ", " + QString::number(s->height());
1059 }
1059 }
1060 break;
1060 break;
1061 case QVariant::SizeF: {
1061 case QVariant::SizeF: {
1062 const QSizeF* s = static_cast<const QSizeF*>(data);
1062 const QSizeF* s = static_cast<const QSizeF*>(data);
1063 r = QString::number(s->width()) + ", " + QString::number(s->height());
1063 r = QString::number(s->width()) + ", " + QString::number(s->height());
1064 }
1064 }
1065 break;
1065 break;
1066 case QVariant::Point: {
1066 case QVariant::Point: {
1067 const QPoint* s = static_cast<const QPoint*>(data);
1067 const QPoint* s = static_cast<const QPoint*>(data);
1068 r = QString::number(s->x()) + ", " + QString::number(s->y());
1068 r = QString::number(s->x()) + ", " + QString::number(s->y());
1069 }
1069 }
1070 break;
1070 break;
1071 case QVariant::PointF: {
1071 case QVariant::PointF: {
1072 const QPointF* s = static_cast<const QPointF*>(data);
1072 const QPointF* s = static_cast<const QPointF*>(data);
1073 r = QString::number(s->x()) + ", " + QString::number(s->y());
1073 r = QString::number(s->x()) + ", " + QString::number(s->y());
1074 }
1074 }
1075 break;
1075 break;
1076 case QVariant::Rect: {
1076 case QVariant::Rect: {
1077 const QRect* s = static_cast<const QRect*>(data);
1077 const QRect* s = static_cast<const QRect*>(data);
1078 r = QString::number(s->x()) + ", " + QString::number(s->y());
1078 r = QString::number(s->x()) + ", " + QString::number(s->y());
1079 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1079 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1080 }
1080 }
1081 break;
1081 break;
1082 case QVariant::RectF: {
1082 case QVariant::RectF: {
1083 const QRectF* s = static_cast<const QRectF*>(data);
1083 const QRectF* s = static_cast<const QRectF*>(data);
1084 r = QString::number(s->x()) + ", " + QString::number(s->y());
1084 r = QString::number(s->x()) + ", " + QString::number(s->y());
1085 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1085 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1086 }
1086 }
1087 break;
1087 break;
1088 case QVariant::Date: {
1088 case QVariant::Date: {
1089 const QDate* s = static_cast<const QDate*>(data);
1089 const QDate* s = static_cast<const QDate*>(data);
1090 r = s->toString(Qt::ISODate);
1090 r = s->toString(Qt::ISODate);
1091 }
1091 }
1092 break;
1092 break;
1093 case QVariant::DateTime: {
1093 case QVariant::DateTime: {
1094 const QDateTime* s = static_cast<const QDateTime*>(data);
1094 const QDateTime* s = static_cast<const QDateTime*>(data);
1095 r = s->toString(Qt::ISODate);
1095 r = s->toString(Qt::ISODate);
1096 }
1096 }
1097 break;
1097 break;
1098 case QVariant::Time: {
1098 case QVariant::Time: {
1099 const QTime* s = static_cast<const QTime*>(data);
1099 const QTime* s = static_cast<const QTime*>(data);
1100 r = s->toString(Qt::ISODate);
1100 r = s->toString(Qt::ISODate);
1101 }
1101 }
1102 break;
1102 break;
1103 case QVariant::Pixmap:
1103 case QVariant::Pixmap:
1104 {
1104 {
1105 const QPixmap* s = static_cast<const QPixmap*>(data);
1105 const QPixmap* s = static_cast<const QPixmap*>(data);
1106 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1106 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1107 }
1107 }
1108 break;
1108 break;
1109 case QVariant::Image:
1109 case QVariant::Image:
1110 {
1110 {
1111 const QImage* s = static_cast<const QImage*>(data);
1111 const QImage* s = static_cast<const QImage*>(data);
1112 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1112 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1113 }
1113 }
1114 break;
1114 break;
1115 case QVariant::Url:
1115 case QVariant::Url:
1116 {
1116 {
1117 const QUrl* s = static_cast<const QUrl*>(data);
1117 const QUrl* s = static_cast<const QUrl*>(data);
1118 r = s->toString();
1118 r = s->toString();
1119 }
1119 }
1120 break;
1120 break;
1121 //TODO: add more printing for other variant types
1121 //TODO: add more printing for other variant types
1122 default:
1122 default:
1123 // 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
1124 // (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!
1125 if (type>0 && type < (int)QVariant::UserType) {
1125 if (type>0 && type < (int)QVariant::UserType) {
1126 QVariant v(type, data);
1126 QVariant v(type, data);
1127 r = v.toString();
1127 r = v.toString();
1128 }
1128 }
1129 }
1129 }
1130 return r;
1130 return r;
1131 }
1131 }
General Comments 0
You need to be logged in to leave comments. Login now