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