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