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