##// END OF EJS Templates
improved strictness when enum values are used...
florianlink -
r52:947ce094f432
parent child
Show More
@@ -1,1102 +1,1108
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 && info.typeId!=PythonQtMethodInfo::Unknown) {
213 213 // everything else is stored in a QVariant, if we know the meta type...
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 502 if (info.typeId != PythonQtMethodInfo::Unknown) {
503 503 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
504 504 QVariant v = PyObjToQVariant(obj, info.typeId);
505 505 if (v.isValid()) {
506 506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
507 507 ptr = (void*)((QVariant*)ptr)->constData();
508 508 }
509 509 }
510 510 }
511 511 }
512 512 }
513 513 return ptr;
514 514 }
515 515
516 516
517 517 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
518 518 QStringList v;
519 519 ok = false;
520 520 // if we are strict, we do not want to convert a string to a stringlist
521 521 // (strings in python are detected to be sequences)
522 522 if (strict &&
523 523 (val->ob_type == &PyString_Type ||
524 524 PyUnicode_Check(val))) {
525 525 ok = false;
526 526 return v;
527 527 }
528 528 if (PySequence_Check(val)) {
529 529 int count = PySequence_Size(val);
530 530 for (int i = 0;i<count;i++) {
531 531 PyObject* value = PySequence_GetItem(val,i);
532 532 v.append(PyObjGetString(value,false,ok));
533 533 }
534 534 ok = true;
535 535 }
536 536 return v;
537 537 }
538 538
539 539 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
540 540 {
541 541 QString r;
542 542 PyObject* str = PyObject_Repr(val);
543 543 if (str) {
544 544 r = QString(PyString_AS_STRING(str));
545 545 Py_DECREF(str);
546 546 }
547 547 return r;
548 548 }
549 549
550 550 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
551 551 QString r;
552 552 ok = true;
553 553 if (val->ob_type == &PyString_Type) {
554 554 r = QString(PyString_AS_STRING(val));
555 555 } else if (PyUnicode_Check(val)) {
556 556 #ifdef WIN32
557 557 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
558 558 #else
559 559 PyObject *ptmp = PyUnicode_AsUTF8String(val);
560 560 if(ptmp) {
561 561 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
562 562 Py_DECREF(ptmp);
563 563 }
564 564 #endif
565 565 } else if (!strict) {
566 566 // EXTRA: could also use _Unicode, but why should we?
567 567 PyObject* str = PyObject_Str(val);
568 568 if (str) {
569 569 r = QString(PyString_AS_STRING(str));
570 570 Py_DECREF(str);
571 571 } else {
572 572 ok = false;
573 573 }
574 574 } else {
575 575 ok = false;
576 576 }
577 577 return r;
578 578 }
579 579
580 580 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
581 581 QByteArray r;
582 582 ok = true;
583 583 if (val->ob_type == &PyString_Type) {
584 584 long size = PyString_GET_SIZE(val);
585 585 r = QByteArray(PyString_AS_STRING(val), size);
586 586 } else {
587 587 ok = false;
588 588 }
589 589 return r;
590 590 }
591 591
592 592 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
593 593 bool d = false;
594 594 ok = false;
595 595 if (val == Py_False) {
596 596 d = false;
597 597 ok = true;
598 598 } else if (val == Py_True) {
599 599 d = true;
600 600 ok = true;
601 601 } else if (!strict) {
602 602 d = PyObjGetInt(val, false, ok)!=0;
603 603 ok = true;
604 604 }
605 605 return d;
606 606 }
607 607
608 608 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
609 609 int d = 0;
610 610 ok = true;
611 611 if (val->ob_type == &PyInt_Type) {
612 612 d = PyInt_AS_LONG(val);
613 613 } else if (!strict) {
614 614 if (PyObject_TypeCheck(val, &PyInt_Type)) {
615 615 // support for derived int classes, e.g. for our enums
616 616 d = PyInt_AS_LONG(val);
617 617 } else if (val->ob_type == &PyFloat_Type) {
618 618 d = floor(PyFloat_AS_DOUBLE(val));
619 619 } else if (val->ob_type == &PyLong_Type) {
620 620 // handle error on overflow!
621 621 d = PyLong_AsLong(val);
622 622 } else if (val == Py_False) {
623 623 d = 0;
624 624 } else if (val == Py_True) {
625 625 d = 1;
626 626 } else {
627 627 ok = false;
628 628 }
629 629 } else {
630 630 ok = false;
631 631 }
632 632 return d;
633 633 }
634 634
635 635 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
636 636 qint64 d = 0;
637 637 ok = true;
638 if (PyObject_TypeCheck(val, &PyInt_Type)) {
638 if (val->ob_type == &PyInt_Type) {
639 639 d = PyInt_AS_LONG(val);
640 640 } else if (val->ob_type == &PyLong_Type) {
641 641 d = PyLong_AsLongLong(val);
642 642 } else if (!strict) {
643 if (val->ob_type == &PyFloat_Type) {
643 if (PyObject_TypeCheck(val, &PyInt_Type)) {
644 // support for derived int classes, e.g. for our enums
645 d = PyInt_AS_LONG(val);
646 } else if (val->ob_type == &PyFloat_Type) {
644 647 d = floor(PyFloat_AS_DOUBLE(val));
645 648 } else if (val == Py_False) {
646 649 d = 0;
647 650 } else if (val == Py_True) {
648 651 d = 1;
649 652 } else {
650 653 ok = false;
651 654 }
652 655 } else {
653 656 ok = false;
654 657 }
655 658 return d;
656 659 }
657 660
658 661 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
659 662 quint64 d = 0;
660 663 ok = true;
661 664 if (PyObject_TypeCheck(val, &PyInt_Type)) {
662 665 d = PyInt_AS_LONG(val);
663 666 } else if (val->ob_type == &PyLong_Type) {
664 667 d = PyLong_AsLongLong(val);
665 668 } else if (!strict) {
666 if (val->ob_type == &PyFloat_Type) {
669 if (PyObject_TypeCheck(val, &PyInt_Type)) {
670 // support for derived int classes, e.g. for our enums
671 d = PyInt_AS_LONG(val);
672 } else if (val->ob_type == &PyFloat_Type) {
667 673 d = floor(PyFloat_AS_DOUBLE(val));
668 674 } else if (val == Py_False) {
669 675 d = 0;
670 676 } else if (val == Py_True) {
671 677 d = 1;
672 678 } else {
673 679 ok = false;
674 680 }
675 681 } else {
676 682 ok = false;
677 683 }
678 684 return d;
679 685 }
680 686
681 687 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
682 688 double d = 0;
683 689 ok = true;
684 690 if (val->ob_type == &PyFloat_Type) {
685 691 d = PyFloat_AS_DOUBLE(val);
686 692 } else if (!strict) {
687 693 if (PyObject_TypeCheck(val, &PyInt_Type)) {
688 694 d = PyInt_AS_LONG(val);
689 695 } else if (val->ob_type == &PyLong_Type) {
690 696 d = PyLong_AsLong(val);
691 697 } else if (val == Py_False) {
692 698 d = 0;
693 699 } else if (val == Py_True) {
694 700 d = 1;
695 701 } else {
696 702 ok = false;
697 703 }
698 704 } else {
699 705 ok = false;
700 706 }
701 707 return d;
702 708 }
703 709
704 710 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
705 711 {
706 712 QVariant v;
707 713 bool ok = true;
708 714
709 715 if (type==-1) {
710 716 // no special type requested
711 717 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
712 718 type = QVariant::String;
713 719 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
714 720 type = QVariant::Int;
715 721 } else if (val->ob_type==&PyLong_Type) {
716 722 type = QVariant::LongLong;
717 723 } else if (val->ob_type==&PyFloat_Type) {
718 724 type = QVariant::Double;
719 725 } else if (val == Py_False || val == Py_True) {
720 726 type = QVariant::Bool;
721 727 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
722 728 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
723 729 // c++ wrapper, check if the class names of the c++ objects match
724 730 if (wrap->classInfo()->isCPPWrapper()) {
725 731 if (wrap->classInfo()->metaTypeId()>0) {
726 732 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
727 733 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
728 734 } else {
729 735 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
730 736 // the pointer here...
731 737 // is this worth anything? we loose the knowledge of the cpp object type
732 738 v = qVariantFromValue(wrap->_wrappedPtr);
733 739 }
734 740 } else {
735 741 // this gives us a QObject pointer
736 742 QObject* myObject = wrap->_obj;
737 743 v = qVariantFromValue(myObject);
738 744 }
739 745 return v;
740 746 } else if (val->ob_type==&PyDict_Type) {
741 747 type = QVariant::Map;
742 748 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
743 749 type = QVariant::List;
744 750 } else if (val == Py_None) {
745 751 // none is invalid
746 752 type = QVariant::Invalid;
747 753 } else {
748 754 // this used to be:
749 755 // type = QVariant::String;
750 756 // but now we want to transport the Python Objects directly:
751 757 PythonQtObjectPtr o(val);
752 758 v = qVariantFromValue(o);
753 759 return v;
754 760 }
755 761 }
756 762 // special type request:
757 763 switch (type) {
758 764 case QVariant::Invalid:
759 765 return v;
760 766 break;
761 767 case QVariant::Int:
762 768 {
763 769 int d = PyObjGetInt(val, false, ok);
764 770 if (ok) return QVariant(d);
765 771 }
766 772 break;
767 773 case QVariant::UInt:
768 774 {
769 775 int d = PyObjGetInt(val, false,ok);
770 776 if (ok) v = QVariant((unsigned int)d);
771 777 }
772 778 break;
773 779 case QVariant::Bool:
774 780 {
775 781 int d = PyObjGetBool(val,false,ok);
776 782 if (ok) v = QVariant((bool)(d!=0));
777 783 }
778 784 break;
779 785 case QVariant::Double:
780 786 {
781 787 double d = PyObjGetDouble(val,false,ok);
782 788 if (ok) v = QVariant(d);
783 789 break;
784 790 }
785 791 case QMetaType::Float:
786 792 {
787 793 float d = (float) PyObjGetDouble(val,false,ok);
788 794 if (ok) v = qVariantFromValue(d);
789 795 break;
790 796 }
791 797 case QMetaType::Long:
792 798 {
793 799 long d = (long) PyObjGetLongLong(val,false,ok);
794 800 if (ok) v = qVariantFromValue(d);
795 801 break;
796 802 }
797 803 case QMetaType::ULong:
798 804 {
799 805 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
800 806 if (ok) v = qVariantFromValue(d);
801 807 break;
802 808 }
803 809 case QMetaType::Short:
804 810 {
805 811 short d = (short) PyObjGetInt(val,false,ok);
806 812 if (ok) v = qVariantFromValue(d);
807 813 break;
808 814 }
809 815 case QMetaType::UShort:
810 816 {
811 817 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
812 818 if (ok) v = qVariantFromValue(d);
813 819 break;
814 820 }
815 821 case QMetaType::Char:
816 822 {
817 823 char d = (char) PyObjGetInt(val,false,ok);
818 824 if (ok) v = qVariantFromValue(d);
819 825 break;
820 826 }
821 827 case QMetaType::UChar:
822 828 {
823 829 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
824 830 if (ok) v = qVariantFromValue(d);
825 831 break;
826 832 }
827 833
828 834 case QVariant::ByteArray:
829 835 case QVariant::String:
830 836 {
831 837 bool ok;
832 838 v = QVariant(PyObjGetString(val, false, ok));
833 839 }
834 840 break;
835 841
836 842 // these are important for MeVisLab
837 843 case QVariant::Map:
838 844 {
839 845 if (PyMapping_Check(val)) {
840 846 QMap<QString,QVariant> map;
841 847 PyObject* items = PyMapping_Items(val);
842 848 if (items) {
843 849 int count = PyList_Size(items);
844 850 PyObject* value;
845 851 PyObject* key;
846 852 PyObject* tuple;
847 853 for (int i = 0;i<count;i++) {
848 854 tuple = PyList_GetItem(items,i);
849 855 key = PyTuple_GetItem(tuple, 0);
850 856 value = PyTuple_GetItem(tuple, 1);
851 857 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
852 858 }
853 859 Py_DECREF(items);
854 860 v = map;
855 861 }
856 862 }
857 863 }
858 864 break;
859 865 case QVariant::List:
860 866 if (PySequence_Check(val)) {
861 867 QVariantList list;
862 868 int count = PySequence_Size(val);
863 869 PyObject* value;
864 870 for (int i = 0;i<count;i++) {
865 871 value = PySequence_GetItem(val,i);
866 872 list.append(PyObjToQVariant(value, -1));
867 873 }
868 874 v = list;
869 875 }
870 876 break;
871 877 case QVariant::StringList:
872 878 {
873 879 bool ok;
874 880 QStringList l = PyObjToStringList(val, false, ok);
875 881 if (ok) {
876 882 v = l;
877 883 }
878 884 }
879 885 break;
880 886
881 887 default:
882 888 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
883 889 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
884 890 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
885 891 // construct a new variant from the C++ object if it has the same meta type
886 892 v = QVariant(type, wrap->_wrappedPtr);
887 893 } else {
888 894 v = QVariant();
889 895 }
890 896 } else {
891 897 v = QVariant();
892 898 }
893 899 }
894 900 return v;
895 901 }
896 902
897 903 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
898 904 {
899 905 if (str.isNull()) {
900 906 return PyString_FromString("");
901 907 } else {
902 908 #ifdef WIN32
903 909 // return PyString_FromString(str.toLatin1().data());
904 910 return PyUnicode_FromUnicode(str.utf16(), str.length());
905 911 #else
906 912 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
907 913 #endif
908 914 }
909 915 }
910 916
911 917 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
912 918 {
913 919 PyObject* result = PyTuple_New(list.count());
914 920 int i = 0;
915 921 QString str;
916 922 foreach (str, list) {
917 923 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
918 924 i++;
919 925 }
920 926 // why is the error state bad after this?
921 927 PyErr_Clear();
922 928 return result;
923 929 }
924 930
925 931 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
926 932 {
927 933 PyObject* result = PyList_New(list.count());
928 934 int i = 0;
929 935 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
930 936 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
931 937 i++;
932 938 }
933 939 return result;
934 940 }
935 941
936 942 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
937 943 {
938 944 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
939 945 }
940 946
941 947 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
942 948 PyObject* result = PyDict_New();
943 949 QVariantMap::const_iterator t = m.constBegin();
944 950 PyObject* key;
945 951 PyObject* val;
946 952 for (;t!=m.end();t++) {
947 953 key = QStringToPyObject(t.key());
948 954 val = QVariantToPyObject(t.value());
949 955 PyDict_SetItem(result, key, val);
950 956 Py_DECREF(key);
951 957 Py_DECREF(val);
952 958 }
953 959 return result;
954 960 }
955 961
956 962 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
957 963 PyObject* result = PyTuple_New(l.count());
958 964 int i = 0;
959 965 QVariant v;
960 966 foreach (v, l) {
961 967 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
962 968 i++;
963 969 }
964 970 // why is the error state bad after this?
965 971 PyErr_Clear();
966 972 return result;
967 973 }
968 974
969 975 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
970 976 {
971 977 PyObject* result = PyTuple_New(list->count());
972 978 int i = 0;
973 979 foreach (void* value, *list) {
974 980 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
975 981 i++;
976 982 }
977 983 return result;
978 984 }
979 985
980 986 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
981 987 {
982 988 bool result = false;
983 989 if (PySequence_Check(obj)) {
984 990 result = true;
985 991 int count = PySequence_Size(obj);
986 992 PyObject* value;
987 993 for (int i = 0;i<count;i++) {
988 994 value = PySequence_GetItem(obj,i);
989 995 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
990 996 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
991 997 bool ok;
992 998 void* object = castWrapperTo(wrap, type, ok);
993 999 if (ok) {
994 1000 list->append(object);
995 1001 } else {
996 1002 result = false;
997 1003 break;
998 1004 }
999 1005 }
1000 1006 }
1001 1007 }
1002 1008 return result;
1003 1009 }
1004 1010
1005 1011 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1006 1012 {
1007 1013 int idx = typeName.indexOf("<");
1008 1014 if (idx>0) {
1009 1015 int idx2 = typeName.indexOf(">");
1010 1016 if (idx2>0) {
1011 1017 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1012 1018 return QMetaType::type(innerType.constData());
1013 1019 }
1014 1020 }
1015 1021 return QMetaType::Void;
1016 1022 }
1017 1023
1018 1024
1019 1025
1020 1026 QString PythonQtConv::qVariantToString(const QVariant& v) {
1021 1027 return CPPObjectToString(v.userType(), v.constData());
1022 1028 }
1023 1029
1024 1030 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1025 1031 QString r;
1026 1032 switch (type) {
1027 1033 case QVariant::Size: {
1028 1034 const QSize* s = static_cast<const QSize*>(data);
1029 1035 r = QString::number(s->width()) + ", " + QString::number(s->height());
1030 1036 }
1031 1037 break;
1032 1038 case QVariant::SizeF: {
1033 1039 const QSizeF* s = static_cast<const QSizeF*>(data);
1034 1040 r = QString::number(s->width()) + ", " + QString::number(s->height());
1035 1041 }
1036 1042 break;
1037 1043 case QVariant::Point: {
1038 1044 const QPoint* s = static_cast<const QPoint*>(data);
1039 1045 r = QString::number(s->x()) + ", " + QString::number(s->y());
1040 1046 }
1041 1047 break;
1042 1048 case QVariant::PointF: {
1043 1049 const QPointF* s = static_cast<const QPointF*>(data);
1044 1050 r = QString::number(s->x()) + ", " + QString::number(s->y());
1045 1051 }
1046 1052 break;
1047 1053 case QVariant::Rect: {
1048 1054 const QRect* s = static_cast<const QRect*>(data);
1049 1055 r = QString::number(s->x()) + ", " + QString::number(s->y());
1050 1056 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1051 1057 }
1052 1058 break;
1053 1059 case QVariant::RectF: {
1054 1060 const QRectF* s = static_cast<const QRectF*>(data);
1055 1061 r = QString::number(s->x()) + ", " + QString::number(s->y());
1056 1062 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1057 1063 }
1058 1064 break;
1059 1065 case QVariant::Date: {
1060 1066 const QDate* s = static_cast<const QDate*>(data);
1061 1067 r = s->toString(Qt::ISODate);
1062 1068 }
1063 1069 break;
1064 1070 case QVariant::DateTime: {
1065 1071 const QDateTime* s = static_cast<const QDateTime*>(data);
1066 1072 r = s->toString(Qt::ISODate);
1067 1073 }
1068 1074 break;
1069 1075 case QVariant::Time: {
1070 1076 const QTime* s = static_cast<const QTime*>(data);
1071 1077 r = s->toString(Qt::ISODate);
1072 1078 }
1073 1079 break;
1074 1080 case QVariant::Pixmap:
1075 1081 {
1076 1082 const QPixmap* s = static_cast<const QPixmap*>(data);
1077 1083 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1078 1084 }
1079 1085 break;
1080 1086 case QVariant::Image:
1081 1087 {
1082 1088 const QImage* s = static_cast<const QImage*>(data);
1083 1089 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1084 1090 }
1085 1091 break;
1086 1092 case QVariant::Url:
1087 1093 {
1088 1094 const QUrl* s = static_cast<const QUrl*>(data);
1089 1095 r = s->toString();
1090 1096 }
1091 1097 break;
1092 1098 //TODO: add more printing for other variant types
1093 1099 default:
1094 1100 // this creates a copy, but that should not be expensive for typical simple variants
1095 1101 // (but we do not want to do this for our won user types!
1096 1102 if (type>0 && type < (int)QVariant::UserType) {
1097 1103 QVariant v(type, data);
1098 1104 r = v.toString();
1099 1105 }
1100 1106 }
1101 1107 return r;
1102 1108 }
General Comments 0
You need to be logged in to leave comments. Login now