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