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