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