##// END OF EJS Templates
removed wrong conversion to QVariant when the underlying type id is unknown...
florianlink -
r43:04827ba1f262
parent child
Show More
@@ -1,1097 +1,1099
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) {
212 if (!ptr) {
213 // everything else is stored in a QVariant...
213 // everything else is stored in a QVariant...
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
501 // if no type id is available, conversion to a QVariant makes no sense/is not possible
502 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
502 if (info.typeId != PythonQtMethodInfo::Unknown) {
503 QVariant v = PyObjToQVariant(obj, info.typeId);
503 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
504 if (v.isValid()) {
504 QVariant v = PyObjToQVariant(obj, info.typeId);
505 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
505 if (v.isValid()) {
506 ptr = (void*)((QVariant*)ptr)->constData();
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
507 ptr = (void*)((QVariant*)ptr)->constData();
508 }
507 }
509 }
508 }
510 }
509 }
511 }
510 }
512 }
511 return ptr;
513 return ptr;
512 }
514 }
513
515
514
516
515 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
517 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
516 QStringList v;
518 QStringList v;
517 ok = false;
519 ok = false;
518 // 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
519 // (strings in python are detected to be sequences)
521 // (strings in python are detected to be sequences)
520 if (strict &&
522 if (strict &&
521 (val->ob_type == &PyString_Type ||
523 (val->ob_type == &PyString_Type ||
522 PyUnicode_Check(val))) {
524 PyUnicode_Check(val))) {
523 ok = false;
525 ok = false;
524 return v;
526 return v;
525 }
527 }
526 if (PySequence_Check(val)) {
528 if (PySequence_Check(val)) {
527 int count = PySequence_Size(val);
529 int count = PySequence_Size(val);
528 for (int i = 0;i<count;i++) {
530 for (int i = 0;i<count;i++) {
529 PyObject* value = PySequence_GetItem(val,i);
531 PyObject* value = PySequence_GetItem(val,i);
530 v.append(PyObjGetString(value,false,ok));
532 v.append(PyObjGetString(value,false,ok));
531 }
533 }
532 ok = true;
534 ok = true;
533 }
535 }
534 return v;
536 return v;
535 }
537 }
536
538
537 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
539 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
538 {
540 {
539 QString r;
541 QString r;
540 PyObject* str = PyObject_Repr(val);
542 PyObject* str = PyObject_Repr(val);
541 if (str) {
543 if (str) {
542 r = QString(PyString_AS_STRING(str));
544 r = QString(PyString_AS_STRING(str));
543 Py_DECREF(str);
545 Py_DECREF(str);
544 }
546 }
545 return r;
547 return r;
546 }
548 }
547
549
548 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
550 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
549 QString r;
551 QString r;
550 ok = true;
552 ok = true;
551 if (val->ob_type == &PyString_Type) {
553 if (val->ob_type == &PyString_Type) {
552 r = QString(PyString_AS_STRING(val));
554 r = QString(PyString_AS_STRING(val));
553 } else if (PyUnicode_Check(val)) {
555 } else if (PyUnicode_Check(val)) {
554 #ifdef WIN32
556 #ifdef WIN32
555 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
557 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
556 #else
558 #else
557 PyObject *ptmp = PyUnicode_AsUTF8String(val);
559 PyObject *ptmp = PyUnicode_AsUTF8String(val);
558 if(ptmp) {
560 if(ptmp) {
559 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
561 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
560 Py_DECREF(ptmp);
562 Py_DECREF(ptmp);
561 }
563 }
562 #endif
564 #endif
563 } else if (!strict) {
565 } else if (!strict) {
564 // EXTRA: could also use _Unicode, but why should we?
566 // EXTRA: could also use _Unicode, but why should we?
565 PyObject* str = PyObject_Str(val);
567 PyObject* str = PyObject_Str(val);
566 if (str) {
568 if (str) {
567 r = QString(PyString_AS_STRING(str));
569 r = QString(PyString_AS_STRING(str));
568 Py_DECREF(str);
570 Py_DECREF(str);
569 } else {
571 } else {
570 ok = false;
572 ok = false;
571 }
573 }
572 } else {
574 } else {
573 ok = false;
575 ok = false;
574 }
576 }
575 return r;
577 return r;
576 }
578 }
577
579
578 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
580 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
579 QByteArray r;
581 QByteArray r;
580 ok = true;
582 ok = true;
581 if (val->ob_type == &PyString_Type) {
583 if (val->ob_type == &PyString_Type) {
582 long size = PyString_GET_SIZE(val);
584 long size = PyString_GET_SIZE(val);
583 r = QByteArray(PyString_AS_STRING(val), size);
585 r = QByteArray(PyString_AS_STRING(val), size);
584 } else {
586 } else {
585 ok = false;
587 ok = false;
586 }
588 }
587 return r;
589 return r;
588 }
590 }
589
591
590 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
592 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
591 bool d = false;
593 bool d = false;
592 ok = false;
594 ok = false;
593 if (val == Py_False) {
595 if (val == Py_False) {
594 d = false;
596 d = false;
595 ok = true;
597 ok = true;
596 } else if (val == Py_True) {
598 } else if (val == Py_True) {
597 d = true;
599 d = true;
598 ok = true;
600 ok = true;
599 } else if (!strict) {
601 } else if (!strict) {
600 d = PyObjGetInt(val, false, ok)!=0;
602 d = PyObjGetInt(val, false, ok)!=0;
601 ok = true;
603 ok = true;
602 }
604 }
603 return d;
605 return d;
604 }
606 }
605
607
606 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
608 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
607 int d = 0;
609 int d = 0;
608 ok = true;
610 ok = true;
609 if (val->ob_type == &PyInt_Type) {
611 if (val->ob_type == &PyInt_Type) {
610 d = PyInt_AS_LONG(val);
612 d = PyInt_AS_LONG(val);
611 } else if (!strict) {
613 } else if (!strict) {
612 if (val->ob_type == &PyFloat_Type) {
614 if (val->ob_type == &PyFloat_Type) {
613 d = floor(PyFloat_AS_DOUBLE(val));
615 d = floor(PyFloat_AS_DOUBLE(val));
614 } else if (val->ob_type == &PyLong_Type) {
616 } else if (val->ob_type == &PyLong_Type) {
615 // handle error on overflow!
617 // handle error on overflow!
616 d = PyLong_AsLong(val);
618 d = PyLong_AsLong(val);
617 } else if (val == Py_False) {
619 } else if (val == Py_False) {
618 d = 0;
620 d = 0;
619 } else if (val == Py_True) {
621 } else if (val == Py_True) {
620 d = 1;
622 d = 1;
621 } else {
623 } else {
622 ok = false;
624 ok = false;
623 }
625 }
624 } else {
626 } else {
625 ok = false;
627 ok = false;
626 }
628 }
627 return d;
629 return d;
628 }
630 }
629
631
630 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
632 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
631 qint64 d = 0;
633 qint64 d = 0;
632 ok = true;
634 ok = true;
633 if (val->ob_type == &PyInt_Type) {
635 if (val->ob_type == &PyInt_Type) {
634 d = PyInt_AS_LONG(val);
636 d = PyInt_AS_LONG(val);
635 } else if (val->ob_type == &PyLong_Type) {
637 } else if (val->ob_type == &PyLong_Type) {
636 d = PyLong_AsLongLong(val);
638 d = PyLong_AsLongLong(val);
637 } else if (!strict) {
639 } else if (!strict) {
638 if (val->ob_type == &PyFloat_Type) {
640 if (val->ob_type == &PyFloat_Type) {
639 d = floor(PyFloat_AS_DOUBLE(val));
641 d = floor(PyFloat_AS_DOUBLE(val));
640 } else if (val == Py_False) {
642 } else if (val == Py_False) {
641 d = 0;
643 d = 0;
642 } else if (val == Py_True) {
644 } else if (val == Py_True) {
643 d = 1;
645 d = 1;
644 } else {
646 } else {
645 ok = false;
647 ok = false;
646 }
648 }
647 } else {
649 } else {
648 ok = false;
650 ok = false;
649 }
651 }
650 return d;
652 return d;
651 }
653 }
652
654
653 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
655 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
654 quint64 d = 0;
656 quint64 d = 0;
655 ok = true;
657 ok = true;
656 if (val->ob_type == &PyInt_Type) {
658 if (val->ob_type == &PyInt_Type) {
657 d = PyInt_AS_LONG(val);
659 d = PyInt_AS_LONG(val);
658 } else if (val->ob_type == &PyLong_Type) {
660 } else if (val->ob_type == &PyLong_Type) {
659 d = PyLong_AsLongLong(val);
661 d = PyLong_AsLongLong(val);
660 } else if (!strict) {
662 } else if (!strict) {
661 if (val->ob_type == &PyFloat_Type) {
663 if (val->ob_type == &PyFloat_Type) {
662 d = floor(PyFloat_AS_DOUBLE(val));
664 d = floor(PyFloat_AS_DOUBLE(val));
663 } else if (val == Py_False) {
665 } else if (val == Py_False) {
664 d = 0;
666 d = 0;
665 } else if (val == Py_True) {
667 } else if (val == Py_True) {
666 d = 1;
668 d = 1;
667 } else {
669 } else {
668 ok = false;
670 ok = false;
669 }
671 }
670 } else {
672 } else {
671 ok = false;
673 ok = false;
672 }
674 }
673 return d;
675 return d;
674 }
676 }
675
677
676 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
678 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
677 double d = 0;
679 double d = 0;
678 ok = true;
680 ok = true;
679 if (val->ob_type == &PyFloat_Type) {
681 if (val->ob_type == &PyFloat_Type) {
680 d = PyFloat_AS_DOUBLE(val);
682 d = PyFloat_AS_DOUBLE(val);
681 } else if (!strict) {
683 } else if (!strict) {
682 if (val->ob_type == &PyInt_Type) {
684 if (val->ob_type == &PyInt_Type) {
683 d = PyInt_AS_LONG(val);
685 d = PyInt_AS_LONG(val);
684 } else if (val->ob_type == &PyLong_Type) {
686 } else if (val->ob_type == &PyLong_Type) {
685 d = PyLong_AsLong(val);
687 d = PyLong_AsLong(val);
686 } else if (val == Py_False) {
688 } else if (val == Py_False) {
687 d = 0;
689 d = 0;
688 } else if (val == Py_True) {
690 } else if (val == Py_True) {
689 d = 1;
691 d = 1;
690 } else {
692 } else {
691 ok = false;
693 ok = false;
692 }
694 }
693 } else {
695 } else {
694 ok = false;
696 ok = false;
695 }
697 }
696 return d;
698 return d;
697 }
699 }
698
700
699 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
701 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
700 {
702 {
701 QVariant v;
703 QVariant v;
702 bool ok = true;
704 bool ok = true;
703
705
704 if (type==-1) {
706 if (type==-1) {
705 // no special type requested
707 // no special type requested
706 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
708 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
707 type = QVariant::String;
709 type = QVariant::String;
708 } else if (val->ob_type==&PyInt_Type) {
710 } else if (val->ob_type==&PyInt_Type) {
709 type = QVariant::Int;
711 type = QVariant::Int;
710 } else if (val->ob_type==&PyLong_Type) {
712 } else if (val->ob_type==&PyLong_Type) {
711 type = QVariant::LongLong;
713 type = QVariant::LongLong;
712 } else if (val->ob_type==&PyFloat_Type) {
714 } else if (val->ob_type==&PyFloat_Type) {
713 type = QVariant::Double;
715 type = QVariant::Double;
714 } else if (val == Py_False || val == Py_True) {
716 } else if (val == Py_False || val == Py_True) {
715 type = QVariant::Bool;
717 type = QVariant::Bool;
716 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
718 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
717 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
719 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
718 // c++ wrapper, check if the class names of the c++ objects match
720 // c++ wrapper, check if the class names of the c++ objects match
719 if (wrap->classInfo()->isCPPWrapper()) {
721 if (wrap->classInfo()->isCPPWrapper()) {
720 if (wrap->classInfo()->metaTypeId()>0) {
722 if (wrap->classInfo()->metaTypeId()>0) {
721 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
723 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
722 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
724 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
723 } else {
725 } else {
724 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
726 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
725 // the pointer here...
727 // the pointer here...
726 // is this worth anything? we loose the knowledge of the cpp object type
728 // is this worth anything? we loose the knowledge of the cpp object type
727 v = qVariantFromValue(wrap->_wrappedPtr);
729 v = qVariantFromValue(wrap->_wrappedPtr);
728 }
730 }
729 } else {
731 } else {
730 // this gives us a QObject pointer
732 // this gives us a QObject pointer
731 QObject* myObject = wrap->_obj;
733 QObject* myObject = wrap->_obj;
732 v = qVariantFromValue(myObject);
734 v = qVariantFromValue(myObject);
733 }
735 }
734 return v;
736 return v;
735 } else if (val->ob_type==&PyDict_Type) {
737 } else if (val->ob_type==&PyDict_Type) {
736 type = QVariant::Map;
738 type = QVariant::Map;
737 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
739 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
738 type = QVariant::List;
740 type = QVariant::List;
739 } else if (val == Py_None) {
741 } else if (val == Py_None) {
740 // none is invalid
742 // none is invalid
741 type = QVariant::Invalid;
743 type = QVariant::Invalid;
742 } else {
744 } else {
743 // this used to be:
745 // this used to be:
744 // type = QVariant::String;
746 // type = QVariant::String;
745 // but now we want to transport the Python Objects directly:
747 // but now we want to transport the Python Objects directly:
746 PythonQtObjectPtr o(val);
748 PythonQtObjectPtr o(val);
747 v = qVariantFromValue(o);
749 v = qVariantFromValue(o);
748 return v;
750 return v;
749 }
751 }
750 }
752 }
751 // special type request:
753 // special type request:
752 switch (type) {
754 switch (type) {
753 case QVariant::Invalid:
755 case QVariant::Invalid:
754 return v;
756 return v;
755 break;
757 break;
756 case QVariant::Int:
758 case QVariant::Int:
757 {
759 {
758 int d = PyObjGetInt(val, false, ok);
760 int d = PyObjGetInt(val, false, ok);
759 if (ok) return QVariant(d);
761 if (ok) return QVariant(d);
760 }
762 }
761 break;
763 break;
762 case QVariant::UInt:
764 case QVariant::UInt:
763 {
765 {
764 int d = PyObjGetInt(val, false,ok);
766 int d = PyObjGetInt(val, false,ok);
765 if (ok) v = QVariant((unsigned int)d);
767 if (ok) v = QVariant((unsigned int)d);
766 }
768 }
767 break;
769 break;
768 case QVariant::Bool:
770 case QVariant::Bool:
769 {
771 {
770 int d = PyObjGetBool(val,false,ok);
772 int d = PyObjGetBool(val,false,ok);
771 if (ok) v = QVariant((bool)(d!=0));
773 if (ok) v = QVariant((bool)(d!=0));
772 }
774 }
773 break;
775 break;
774 case QVariant::Double:
776 case QVariant::Double:
775 {
777 {
776 double d = PyObjGetDouble(val,false,ok);
778 double d = PyObjGetDouble(val,false,ok);
777 if (ok) v = QVariant(d);
779 if (ok) v = QVariant(d);
778 break;
780 break;
779 }
781 }
780 case QMetaType::Float:
782 case QMetaType::Float:
781 {
783 {
782 float d = (float) PyObjGetDouble(val,false,ok);
784 float d = (float) PyObjGetDouble(val,false,ok);
783 if (ok) v = qVariantFromValue(d);
785 if (ok) v = qVariantFromValue(d);
784 break;
786 break;
785 }
787 }
786 case QMetaType::Long:
788 case QMetaType::Long:
787 {
789 {
788 long d = (long) PyObjGetLongLong(val,false,ok);
790 long d = (long) PyObjGetLongLong(val,false,ok);
789 if (ok) v = qVariantFromValue(d);
791 if (ok) v = qVariantFromValue(d);
790 break;
792 break;
791 }
793 }
792 case QMetaType::ULong:
794 case QMetaType::ULong:
793 {
795 {
794 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
796 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
795 if (ok) v = qVariantFromValue(d);
797 if (ok) v = qVariantFromValue(d);
796 break;
798 break;
797 }
799 }
798 case QMetaType::Short:
800 case QMetaType::Short:
799 {
801 {
800 short d = (short) PyObjGetInt(val,false,ok);
802 short d = (short) PyObjGetInt(val,false,ok);
801 if (ok) v = qVariantFromValue(d);
803 if (ok) v = qVariantFromValue(d);
802 break;
804 break;
803 }
805 }
804 case QMetaType::UShort:
806 case QMetaType::UShort:
805 {
807 {
806 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
808 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
807 if (ok) v = qVariantFromValue(d);
809 if (ok) v = qVariantFromValue(d);
808 break;
810 break;
809 }
811 }
810 case QMetaType::Char:
812 case QMetaType::Char:
811 {
813 {
812 char d = (char) PyObjGetInt(val,false,ok);
814 char d = (char) PyObjGetInt(val,false,ok);
813 if (ok) v = qVariantFromValue(d);
815 if (ok) v = qVariantFromValue(d);
814 break;
816 break;
815 }
817 }
816 case QMetaType::UChar:
818 case QMetaType::UChar:
817 {
819 {
818 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
820 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
819 if (ok) v = qVariantFromValue(d);
821 if (ok) v = qVariantFromValue(d);
820 break;
822 break;
821 }
823 }
822
824
823 case QVariant::ByteArray:
825 case QVariant::ByteArray:
824 case QVariant::String:
826 case QVariant::String:
825 {
827 {
826 bool ok;
828 bool ok;
827 v = QVariant(PyObjGetString(val, false, ok));
829 v = QVariant(PyObjGetString(val, false, ok));
828 }
830 }
829 break;
831 break;
830
832
831 // these are important for MeVisLab
833 // these are important for MeVisLab
832 case QVariant::Map:
834 case QVariant::Map:
833 {
835 {
834 if (PyMapping_Check(val)) {
836 if (PyMapping_Check(val)) {
835 QMap<QString,QVariant> map;
837 QMap<QString,QVariant> map;
836 PyObject* items = PyMapping_Items(val);
838 PyObject* items = PyMapping_Items(val);
837 if (items) {
839 if (items) {
838 int count = PyList_Size(items);
840 int count = PyList_Size(items);
839 PyObject* value;
841 PyObject* value;
840 PyObject* key;
842 PyObject* key;
841 PyObject* tuple;
843 PyObject* tuple;
842 for (int i = 0;i<count;i++) {
844 for (int i = 0;i<count;i++) {
843 tuple = PyList_GetItem(items,i);
845 tuple = PyList_GetItem(items,i);
844 key = PyTuple_GetItem(tuple, 0);
846 key = PyTuple_GetItem(tuple, 0);
845 value = PyTuple_GetItem(tuple, 1);
847 value = PyTuple_GetItem(tuple, 1);
846 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
848 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
847 }
849 }
848 Py_DECREF(items);
850 Py_DECREF(items);
849 v = map;
851 v = map;
850 }
852 }
851 }
853 }
852 }
854 }
853 break;
855 break;
854 case QVariant::List:
856 case QVariant::List:
855 if (PySequence_Check(val)) {
857 if (PySequence_Check(val)) {
856 QVariantList list;
858 QVariantList list;
857 int count = PySequence_Size(val);
859 int count = PySequence_Size(val);
858 PyObject* value;
860 PyObject* value;
859 for (int i = 0;i<count;i++) {
861 for (int i = 0;i<count;i++) {
860 value = PySequence_GetItem(val,i);
862 value = PySequence_GetItem(val,i);
861 list.append(PyObjToQVariant(value, -1));
863 list.append(PyObjToQVariant(value, -1));
862 }
864 }
863 v = list;
865 v = list;
864 }
866 }
865 break;
867 break;
866 case QVariant::StringList:
868 case QVariant::StringList:
867 {
869 {
868 bool ok;
870 bool ok;
869 QStringList l = PyObjToStringList(val, false, ok);
871 QStringList l = PyObjToStringList(val, false, ok);
870 if (ok) {
872 if (ok) {
871 v = l;
873 v = l;
872 }
874 }
873 }
875 }
874 break;
876 break;
875
877
876 default:
878 default:
877 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
879 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
878 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
880 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
879 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
881 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
880 // construct a new variant from the C++ object if it has the same meta type
882 // construct a new variant from the C++ object if it has the same meta type
881 v = QVariant(type, wrap->_wrappedPtr);
883 v = QVariant(type, wrap->_wrappedPtr);
882 } else {
884 } else {
883 v = QVariant();
885 v = QVariant();
884 }
886 }
885 } else {
887 } else {
886 v = QVariant();
888 v = QVariant();
887 }
889 }
888 }
890 }
889 return v;
891 return v;
890 }
892 }
891
893
892 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
894 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
893 {
895 {
894 if (str.isNull()) {
896 if (str.isNull()) {
895 return PyString_FromString("");
897 return PyString_FromString("");
896 } else {
898 } else {
897 #ifdef WIN32
899 #ifdef WIN32
898 // return PyString_FromString(str.toLatin1().data());
900 // return PyString_FromString(str.toLatin1().data());
899 return PyUnicode_FromUnicode(str.utf16(), str.length());
901 return PyUnicode_FromUnicode(str.utf16(), str.length());
900 #else
902 #else
901 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
903 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
902 #endif
904 #endif
903 }
905 }
904 }
906 }
905
907
906 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
908 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
907 {
909 {
908 PyObject* result = PyTuple_New(list.count());
910 PyObject* result = PyTuple_New(list.count());
909 int i = 0;
911 int i = 0;
910 QString str;
912 QString str;
911 foreach (str, list) {
913 foreach (str, list) {
912 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
914 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
913 i++;
915 i++;
914 }
916 }
915 // why is the error state bad after this?
917 // why is the error state bad after this?
916 PyErr_Clear();
918 PyErr_Clear();
917 return result;
919 return result;
918 }
920 }
919
921
920 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
922 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
921 {
923 {
922 PyObject* result = PyList_New(list.count());
924 PyObject* result = PyList_New(list.count());
923 int i = 0;
925 int i = 0;
924 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
926 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
925 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
927 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
926 i++;
928 i++;
927 }
929 }
928 return result;
930 return result;
929 }
931 }
930
932
931 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
933 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
932 {
934 {
933 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
935 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
934 }
936 }
935
937
936 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
938 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
937 PyObject* result = PyDict_New();
939 PyObject* result = PyDict_New();
938 QVariantMap::const_iterator t = m.constBegin();
940 QVariantMap::const_iterator t = m.constBegin();
939 PyObject* key;
941 PyObject* key;
940 PyObject* val;
942 PyObject* val;
941 for (;t!=m.end();t++) {
943 for (;t!=m.end();t++) {
942 key = QStringToPyObject(t.key());
944 key = QStringToPyObject(t.key());
943 val = QVariantToPyObject(t.value());
945 val = QVariantToPyObject(t.value());
944 PyDict_SetItem(result, key, val);
946 PyDict_SetItem(result, key, val);
945 Py_DECREF(key);
947 Py_DECREF(key);
946 Py_DECREF(val);
948 Py_DECREF(val);
947 }
949 }
948 return result;
950 return result;
949 }
951 }
950
952
951 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
953 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
952 PyObject* result = PyTuple_New(l.count());
954 PyObject* result = PyTuple_New(l.count());
953 int i = 0;
955 int i = 0;
954 QVariant v;
956 QVariant v;
955 foreach (v, l) {
957 foreach (v, l) {
956 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
958 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
957 i++;
959 i++;
958 }
960 }
959 // why is the error state bad after this?
961 // why is the error state bad after this?
960 PyErr_Clear();
962 PyErr_Clear();
961 return result;
963 return result;
962 }
964 }
963
965
964 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
966 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
965 {
967 {
966 PyObject* result = PyTuple_New(list->count());
968 PyObject* result = PyTuple_New(list->count());
967 int i = 0;
969 int i = 0;
968 foreach (void* value, *list) {
970 foreach (void* value, *list) {
969 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
971 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
970 i++;
972 i++;
971 }
973 }
972 return result;
974 return result;
973 }
975 }
974
976
975 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
977 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
976 {
978 {
977 bool result = false;
979 bool result = false;
978 if (PySequence_Check(obj)) {
980 if (PySequence_Check(obj)) {
979 result = true;
981 result = true;
980 int count = PySequence_Size(obj);
982 int count = PySequence_Size(obj);
981 PyObject* value;
983 PyObject* value;
982 for (int i = 0;i<count;i++) {
984 for (int i = 0;i<count;i++) {
983 value = PySequence_GetItem(obj,i);
985 value = PySequence_GetItem(obj,i);
984 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
986 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
985 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
987 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
986 bool ok;
988 bool ok;
987 void* object = castWrapperTo(wrap, type, ok);
989 void* object = castWrapperTo(wrap, type, ok);
988 if (ok) {
990 if (ok) {
989 list->append(object);
991 list->append(object);
990 } else {
992 } else {
991 result = false;
993 result = false;
992 break;
994 break;
993 }
995 }
994 }
996 }
995 }
997 }
996 }
998 }
997 return result;
999 return result;
998 }
1000 }
999
1001
1000 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1002 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1001 {
1003 {
1002 int idx = typeName.indexOf("<");
1004 int idx = typeName.indexOf("<");
1003 if (idx>0) {
1005 if (idx>0) {
1004 int idx2 = typeName.indexOf(">");
1006 int idx2 = typeName.indexOf(">");
1005 if (idx2>0) {
1007 if (idx2>0) {
1006 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1008 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1007 return QMetaType::type(innerType.constData());
1009 return QMetaType::type(innerType.constData());
1008 }
1010 }
1009 }
1011 }
1010 return QMetaType::Void;
1012 return QMetaType::Void;
1011 }
1013 }
1012
1014
1013
1015
1014
1016
1015 QString PythonQtConv::qVariantToString(const QVariant& v) {
1017 QString PythonQtConv::qVariantToString(const QVariant& v) {
1016 return CPPObjectToString(v.userType(), v.constData());
1018 return CPPObjectToString(v.userType(), v.constData());
1017 }
1019 }
1018
1020
1019 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1021 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1020 QString r;
1022 QString r;
1021 switch (type) {
1023 switch (type) {
1022 case QVariant::Size: {
1024 case QVariant::Size: {
1023 const QSize* s = static_cast<const QSize*>(data);
1025 const QSize* s = static_cast<const QSize*>(data);
1024 r = QString::number(s->width()) + ", " + QString::number(s->height());
1026 r = QString::number(s->width()) + ", " + QString::number(s->height());
1025 }
1027 }
1026 break;
1028 break;
1027 case QVariant::SizeF: {
1029 case QVariant::SizeF: {
1028 const QSizeF* s = static_cast<const QSizeF*>(data);
1030 const QSizeF* s = static_cast<const QSizeF*>(data);
1029 r = QString::number(s->width()) + ", " + QString::number(s->height());
1031 r = QString::number(s->width()) + ", " + QString::number(s->height());
1030 }
1032 }
1031 break;
1033 break;
1032 case QVariant::Point: {
1034 case QVariant::Point: {
1033 const QPoint* s = static_cast<const QPoint*>(data);
1035 const QPoint* s = static_cast<const QPoint*>(data);
1034 r = QString::number(s->x()) + ", " + QString::number(s->y());
1036 r = QString::number(s->x()) + ", " + QString::number(s->y());
1035 }
1037 }
1036 break;
1038 break;
1037 case QVariant::PointF: {
1039 case QVariant::PointF: {
1038 const QPointF* s = static_cast<const QPointF*>(data);
1040 const QPointF* s = static_cast<const QPointF*>(data);
1039 r = QString::number(s->x()) + ", " + QString::number(s->y());
1041 r = QString::number(s->x()) + ", " + QString::number(s->y());
1040 }
1042 }
1041 break;
1043 break;
1042 case QVariant::Rect: {
1044 case QVariant::Rect: {
1043 const QRect* s = static_cast<const QRect*>(data);
1045 const QRect* s = static_cast<const QRect*>(data);
1044 r = QString::number(s->x()) + ", " + QString::number(s->y());
1046 r = QString::number(s->x()) + ", " + QString::number(s->y());
1045 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1047 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1046 }
1048 }
1047 break;
1049 break;
1048 case QVariant::RectF: {
1050 case QVariant::RectF: {
1049 const QRectF* s = static_cast<const QRectF*>(data);
1051 const QRectF* s = static_cast<const QRectF*>(data);
1050 r = QString::number(s->x()) + ", " + QString::number(s->y());
1052 r = QString::number(s->x()) + ", " + QString::number(s->y());
1051 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1053 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1052 }
1054 }
1053 break;
1055 break;
1054 case QVariant::Date: {
1056 case QVariant::Date: {
1055 const QDate* s = static_cast<const QDate*>(data);
1057 const QDate* s = static_cast<const QDate*>(data);
1056 r = s->toString(Qt::ISODate);
1058 r = s->toString(Qt::ISODate);
1057 }
1059 }
1058 break;
1060 break;
1059 case QVariant::DateTime: {
1061 case QVariant::DateTime: {
1060 const QDateTime* s = static_cast<const QDateTime*>(data);
1062 const QDateTime* s = static_cast<const QDateTime*>(data);
1061 r = s->toString(Qt::ISODate);
1063 r = s->toString(Qt::ISODate);
1062 }
1064 }
1063 break;
1065 break;
1064 case QVariant::Time: {
1066 case QVariant::Time: {
1065 const QTime* s = static_cast<const QTime*>(data);
1067 const QTime* s = static_cast<const QTime*>(data);
1066 r = s->toString(Qt::ISODate);
1068 r = s->toString(Qt::ISODate);
1067 }
1069 }
1068 break;
1070 break;
1069 case QVariant::Pixmap:
1071 case QVariant::Pixmap:
1070 {
1072 {
1071 const QPixmap* s = static_cast<const QPixmap*>(data);
1073 const QPixmap* s = static_cast<const QPixmap*>(data);
1072 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1074 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1073 }
1075 }
1074 break;
1076 break;
1075 case QVariant::Image:
1077 case QVariant::Image:
1076 {
1078 {
1077 const QImage* s = static_cast<const QImage*>(data);
1079 const QImage* s = static_cast<const QImage*>(data);
1078 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1080 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1079 }
1081 }
1080 break;
1082 break;
1081 case QVariant::Url:
1083 case QVariant::Url:
1082 {
1084 {
1083 const QUrl* s = static_cast<const QUrl*>(data);
1085 const QUrl* s = static_cast<const QUrl*>(data);
1084 r = s->toString();
1086 r = s->toString();
1085 }
1087 }
1086 break;
1088 break;
1087 //TODO: add more printing for other variant types
1089 //TODO: add more printing for other variant types
1088 default:
1090 default:
1089 // this creates a copy, but that should not be expensive for typical simple variants
1091 // this creates a copy, but that should not be expensive for typical simple variants
1090 // (but we do not want to do this for our won user types!
1092 // (but we do not want to do this for our won user types!
1091 if (type>0 && type < (int)QVariant::UserType) {
1093 if (type>0 && type < (int)QVariant::UserType) {
1092 QVariant v(type, data);
1094 QVariant v(type, data);
1093 r = v.toString();
1095 r = v.toString();
1094 }
1096 }
1095 }
1097 }
1096 return r;
1098 return r;
1097 }
1099 }
General Comments 0
You need to be logged in to leave comments. Login now