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