Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/PythonQt/src/PythonQtConversion.cpp
3206 views
1
/*
2
*
3
* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* Further, this software is distributed without any warranty that it is
16
* free of the rightful claim of any third person regarding infringement
17
* or the like. Any license provided herein, whether implied or
18
* otherwise, applies only to this software file. Patent licenses, if
19
* any, provided herein do not apply to combinations of this program with
20
* other software, or any other product whatsoever.
21
*
22
* You should have received a copy of the GNU Lesser General Public
23
* License along with this library; if not, write to the Free Software
24
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
*
26
* Contact information: MeVis Research GmbH, Universitaetsallee 29,
27
* 28359 Bremen, Germany or:
28
*
29
* http://www.mevis.de
30
*
31
*/
32
33
//----------------------------------------------------------------------------------
34
/*!
35
// \file PythonQtConversion.cpp
36
// \author Florian Link
37
// \author Last changed by $Author: florian $
38
// \date 2006-05
39
*/
40
//----------------------------------------------------------------------------------
41
42
#include "PythonQtConversion.h"
43
#include "PythonQtVariants.h"
44
#include "PythonQtVariantWrapper.h"
45
#include <QDateTime>
46
#include <QTime>
47
#include <QDate>
48
49
PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
50
PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
51
PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
52
53
54
PyObject* PythonQtConv::GetPyBool(bool val)
55
{
56
PyObject* r = val?Py_True:Py_False;
57
Py_INCREF(r);
58
return r;
59
}
60
61
PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, void* data) {
62
if (info.typeId == QMetaType::Void) {
63
Py_INCREF(Py_None);
64
return Py_None;
65
} else {
66
if (info.isPointer && (info.typeId == PythonQtMethodInfo::Unknown)) {
67
// convert argList[0] to python
68
PyObject* pyObj = PythonQt::priv()->wrapPtr(*((void**)data), info.name);
69
if (pyObj) {
70
return pyObj;
71
} else {
72
std::cerr << "unknown pointer type " << info.name.data() << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
73
Py_INCREF(Py_None);
74
return Py_None;
75
}
76
} else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77
// a char ptr will probably be a null terminated string, so we support that:
78
return PyString_FromString(*((char**)data));
79
} else {
80
// handle values that are not pointers
81
return ConvertQtValueToPythonInternal(info.typeId, data);
82
}
83
}
84
}
85
86
PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, void* data) {
87
switch (type) {
88
case QMetaType::Void:
89
Py_INCREF(Py_None);
90
return Py_None;
91
case QMetaType::Char:
92
return PyInt_FromLong(*((char*)data));
93
case QMetaType::UChar:
94
return PyInt_FromLong(*((unsigned char*)data));
95
case QMetaType::Short:
96
return PyInt_FromLong(*((short*)data));
97
case QMetaType::UShort:
98
return PyInt_FromLong(*((unsigned short*)data));
99
case QMetaType::Long:
100
return PyInt_FromLong(*((long*)data));
101
case QMetaType::ULong:
102
// does not fit into simple int of python
103
return PyLong_FromUnsignedLong(*((unsigned long*)data));
104
case QMetaType::Bool:
105
return PythonQtConv::GetPyBool(*((bool*)data));
106
case QMetaType::Int:
107
return PyInt_FromLong(*((int*)data));
108
case QMetaType::UInt:
109
return PyInt_FromLong(*((unsigned int*)data));
110
case QMetaType::QChar:
111
return PyInt_FromLong(*((short*)data));
112
case QMetaType::Float:
113
return PyFloat_FromDouble(*((float*)data));
114
case QMetaType::Double:
115
return PyFloat_FromDouble(*((double*)data));
116
case QMetaType::LongLong:
117
return PyLong_FromLongLong(*((qint64*)data));
118
case QMetaType::ULongLong:
119
return PyLong_FromUnsignedLongLong(*((quint64*)data));
120
case QMetaType::QByteArray:
121
return PyString_FromString(*((QByteArray*)data));
122
case QMetaType::QVariantMap:
123
return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
124
case QMetaType::QVariantList:
125
return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
126
case QMetaType::QString:
127
return PythonQtConv::QStringToPyObject(*((QString*)data));
128
case QMetaType::QStringList:
129
return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
130
131
case PythonQtMethodInfo::Variant:
132
return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
133
case QMetaType::QObjectStar:
134
case QMetaType::QWidgetStar:
135
return PythonQt::priv()->wrapQObject(*((QObject**)data));
136
137
// the following cases could be handled by the default case, but it is faster to do it with
138
// direct casts:
139
case QMetaType::QDate:
140
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDate*)data)));
141
case QMetaType::QTime:
142
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QTime*)data)));
143
case QMetaType::QDateTime:
144
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDateTime*)data)));
145
case QMetaType::QRect:
146
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRect*)data)));
147
case QMetaType::QSize:
148
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSize*)data)));
149
case QMetaType::QPoint:
150
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPoint*)data)));
151
case QMetaType::QColor:
152
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QColor*)data)));
153
case QMetaType::QPixmap:
154
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPixmap*)data)));
155
case QMetaType::QUrl:
156
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QUrl*)data)));
157
case QMetaType::QRectF:
158
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRectF*)data)));
159
case QMetaType::QSizeF:
160
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizeF*)data)));
161
case QMetaType::QLine:
162
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLine*)data)));
163
case QMetaType::QLineF:
164
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLineF*)data)));
165
case QMetaType::QPointF:
166
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPointF*)data)));
167
case QMetaType::QRegExp:
168
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegExp*)data)));
169
case QMetaType::QBitArray:
170
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBitArray*)data)));
171
case QMetaType::QLocale:
172
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLocale*)data)));
173
case QMetaType::QFont:
174
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QFont*)data)));
175
case QMetaType::QBrush:
176
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBrush*)data)));
177
case QMetaType::QPalette:
178
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPalette*)data)));
179
case QMetaType::QIcon:
180
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QIcon*)data)));
181
case QMetaType::QImage:
182
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QImage*)data)));
183
case QMetaType::QPolygon:
184
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPolygon*)data)));
185
case QMetaType::QRegion:
186
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegion*)data)));
187
case QMetaType::QBitmap:
188
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QBitmap*)data)));
189
case QMetaType::QCursor:
190
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QCursor*)data)));
191
case QMetaType::QSizePolicy:
192
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizePolicy*)data)));
193
case QMetaType::QKeySequence:
194
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QKeySequence*)data)));
195
case QMetaType::QPen:
196
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QPen*)data)));
197
case QMetaType::QTextLength:
198
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextLength*)data)));
199
case QMetaType::QTextFormat:
200
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextFormat*)data)));
201
case QMetaType::QMatrix:
202
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QMatrix*)data)));
203
default:
204
if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
205
PyObject* o = ((PythonQtObjectPtr*)data)->object();
206
Py_INCREF(o);
207
return o;
208
} else {
209
QVariant v(type, data);
210
if (v.isValid()) {
211
return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(v);
212
} else {
213
std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
214
}
215
}
216
}
217
Py_INCREF(Py_None);
218
return Py_None;
219
}
220
221
void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
222
void* ptr = NULL;
223
if (info.isPointer) {
224
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
225
} else {
226
switch (info.typeId) {
227
case QMetaType::Char:
228
case QMetaType::UChar:
229
case QMetaType::Short:
230
case QMetaType::UShort:
231
case QMetaType::Long:
232
case QMetaType::ULong:
233
case QMetaType::Bool:
234
case QMetaType::Int:
235
case QMetaType::UInt:
236
case QMetaType::QChar:
237
case QMetaType::Float:
238
case QMetaType::Double:
239
PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
240
break;
241
case PythonQtMethodInfo::Variant:
242
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
243
// return the ptr to the variant
244
break;
245
default:
246
// everything else is stored in a QVariant...
247
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
248
// return the constData pointer that will be filled with the result value later on
249
ptr = (void*)((QVariant*)ptr)->constData();
250
}
251
}
252
return ptr;
253
}
254
255
void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
256
{
257
bool ok;
258
void* ptr = NULL;
259
if (info.isPointer) {
260
if (obj->ob_type == &PythonQtWrapper_Type) {
261
PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
262
// c++ wrapper, check if the class names of the c++ objects match
263
if (wrap->_info->isCPPWrapper()) {
264
//TODO: we could support inheritance on cpp wrappers as well
265
if (wrap->_info->wrappedCPPClassName() == info.name) {
266
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_wrappedPtr, ptr);
267
} else {
268
// not matching
269
}
270
} else {
271
if (wrap->_info->inherits(info.name)) {
272
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_obj, ptr);
273
} else {
274
// not matching
275
}
276
}
277
} else
278
if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) {
279
QString str = PyObjGetString(obj, strict, ok);
280
if (ok) {
281
void* ptr2 = NULL;
282
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
283
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
284
}
285
} else if (info.name == "PyObject") {
286
// handle low level PyObject directly
287
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
288
} else if (obj == Py_None) {
289
// None is treated as a NULL ptr
290
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
291
} else {
292
// if we are not strict, we try if we are passed a 0 integer
293
if (!strict) {
294
bool ok;
295
int value = PyObjGetInt(obj, true, ok);
296
if (ok && value==0) {
297
PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
298
}
299
}
300
// EXTRA: we could support pointers to other simple types, but this would not make sense in most situations
301
}
302
303
} else {
304
// not a pointer
305
switch (info.typeId) {
306
case QMetaType::Char:
307
{
308
int val = PyObjGetInt(obj, strict, ok);
309
if (ok) {
310
PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
311
}
312
}
313
break;
314
case QMetaType::UChar:
315
{
316
int val = PyObjGetInt(obj, strict, ok);
317
if (ok) {
318
PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
319
}
320
}
321
break;
322
case QMetaType::Short:
323
{
324
int val = PyObjGetInt(obj, strict, ok);
325
if (ok) {
326
PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
327
}
328
}
329
break;
330
case QMetaType::UShort:
331
{
332
int val = PyObjGetInt(obj, strict, ok);
333
if (ok) {
334
PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
335
}
336
}
337
break;
338
case QMetaType::Long:
339
{
340
long val = (long)PyObjGetLongLong(obj, strict, ok);
341
if (ok) {
342
PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
343
}
344
}
345
break;
346
case QMetaType::ULong:
347
{
348
unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
349
if (ok) {
350
PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
351
}
352
}
353
break;
354
case QMetaType::Bool:
355
{
356
bool val = PyObjGetBool(obj, strict, ok);
357
if (ok) {
358
PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
359
}
360
}
361
break;
362
case QMetaType::Int:
363
{
364
int val = PyObjGetInt(obj, strict, ok);
365
if (ok) {
366
PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
367
}
368
}
369
break;
370
case QMetaType::UInt:
371
{
372
unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
373
if (ok) {
374
PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
375
}
376
}
377
break;
378
case QMetaType::QChar:
379
{
380
int val = PyObjGetInt(obj, strict, ok);
381
if (ok) {
382
PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
383
}
384
}
385
break;
386
case QMetaType::Float:
387
{
388
float val = (float)PyObjGetDouble(obj, strict, ok);
389
if (ok) {
390
PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
391
}
392
}
393
break;
394
case QMetaType::Double:
395
{
396
double val = (double)PyObjGetDouble(obj, strict, ok);
397
if (ok) {
398
PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
399
}
400
}
401
break;
402
case QMetaType::LongLong:
403
{
404
qint64 val = PyObjGetLongLong(obj, strict, ok);
405
if (ok) {
406
PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
407
}
408
}
409
break;
410
case QMetaType::ULongLong:
411
{
412
quint64 val = PyObjGetULongLong(obj, strict, ok);
413
if (ok) {
414
PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
415
}
416
}
417
break;
418
case QMetaType::QByteArray:
419
{
420
QString str = PyObjGetString(obj, strict, ok);
421
if (ok) {
422
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr);
423
ptr = (void*)((QVariant*)ptr)->constData();
424
}
425
}
426
break;
427
case QMetaType::QString:
428
{
429
QString str = PyObjGetString(obj, strict, ok);
430
if (ok) {
431
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
432
ptr = (void*)((QVariant*)ptr)->constData();
433
}
434
}
435
break;
436
case QMetaType::QStringList:
437
{
438
QStringList l = PyObjToStringList(obj, strict, ok);
439
if (ok) {
440
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
441
ptr = (void*)((QVariant*)ptr)->constData();
442
}
443
}
444
break;
445
446
case PythonQtMethodInfo::Variant:
447
{
448
QVariant v = PyObjToQVariant(obj);
449
if (v.isValid()) {
450
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
451
}
452
}
453
break;
454
case PythonQtMethodInfo::Unknown:
455
{
456
if (PythonQt::priv()->isEnumType(meta, info.name)) {
457
unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
458
if (ok) {
459
PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
460
}
461
}
462
}
463
break;
464
default:
465
{
466
// for all other types, we use the same qvariant conversion and pass out the constData of the variant:
467
QVariant v = PyObjToQVariant(obj, info.typeId);
468
if (v.isValid()) {
469
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
470
ptr = (void*)((QVariant*)ptr)->constData();
471
}
472
}
473
}
474
}
475
return ptr;
476
}
477
478
479
QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
480
QStringList v;
481
ok = false;
482
// if we are strict, we do not want to convert a string to a stringlist
483
// (strings in python are detected to be sequences)
484
if (strict &&
485
(val->ob_type == &PyString_Type ||
486
PyUnicode_Check(val))) {
487
ok = false;
488
return v;
489
}
490
if (PySequence_Check(val)) {
491
int count = PySequence_Size(val);
492
for (int i = 0;i<count;i++) {
493
PyObject* value = PySequence_GetItem(val,i);
494
v.append(PyObjGetString(value,false,ok));
495
}
496
ok = true;
497
}
498
return v;
499
}
500
501
QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
502
{
503
QString r;
504
PyObject* str = PyObject_Repr(val);
505
if (str) {
506
r = QString(PyString_AS_STRING(str));
507
Py_DECREF(str);
508
}
509
return r;
510
}
511
512
QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
513
QString r;
514
ok = true;
515
if (val->ob_type == &PyString_Type) {
516
r = QString(PyString_AS_STRING(val));
517
} else if (PyUnicode_Check(val)) {
518
#ifdef WIN32
519
r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
520
#else
521
PyObject *ptmp = PyUnicode_AsUTF8String(val);
522
if(ptmp) {
523
r = QString::fromUtf8(PyString_AS_STRING(ptmp));
524
Py_DECREF(ptmp);
525
}
526
#endif
527
} else if (!strict) {
528
// EXTRA: could also use _Unicode, but why should we?
529
PyObject* str = PyObject_Str(val);
530
if (str) {
531
r = QString(PyString_AS_STRING(str));
532
Py_DECREF(str);
533
} else {
534
ok = false;
535
}
536
} else {
537
ok = false;
538
}
539
return r;
540
}
541
542
bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
543
bool d = false;
544
ok = false;
545
if (val == Py_False) {
546
d = false;
547
ok = true;
548
} else if (val == Py_True) {
549
d = true;
550
ok = true;
551
} else if (!strict) {
552
d = PyObjGetInt(val, false, ok)!=0;
553
ok = true;
554
}
555
return d;
556
}
557
558
int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
559
int d = 0;
560
ok = true;
561
if (val->ob_type == &PyInt_Type) {
562
d = PyInt_AS_LONG(val);
563
} else if (!strict) {
564
if (val->ob_type == &PyFloat_Type) {
565
d = floor(PyFloat_AS_DOUBLE(val));
566
} else if (val->ob_type == &PyLong_Type) {
567
// handle error on overflow!
568
d = PyLong_AsLong(val);
569
} else if (val == Py_False) {
570
d = 0;
571
} else if (val == Py_True) {
572
d = 1;
573
} else {
574
ok = false;
575
}
576
} else {
577
ok = false;
578
}
579
return d;
580
}
581
582
qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
583
qint64 d = 0;
584
ok = true;
585
if (val->ob_type == &PyInt_Type) {
586
d = PyInt_AS_LONG(val);
587
} else if (val->ob_type == &PyLong_Type) {
588
d = PyLong_AsLongLong(val);
589
} else if (!strict) {
590
if (val->ob_type == &PyFloat_Type) {
591
d = floor(PyFloat_AS_DOUBLE(val));
592
} else if (val == Py_False) {
593
d = 0;
594
} else if (val == Py_True) {
595
d = 1;
596
} else {
597
ok = false;
598
}
599
} else {
600
ok = false;
601
}
602
return d;
603
}
604
605
quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
606
quint64 d = 0;
607
ok = true;
608
if (val->ob_type == &PyInt_Type) {
609
d = PyInt_AS_LONG(val);
610
} else if (val->ob_type == &PyLong_Type) {
611
d = PyLong_AsLongLong(val);
612
} else if (!strict) {
613
if (val->ob_type == &PyFloat_Type) {
614
d = floor(PyFloat_AS_DOUBLE(val));
615
} else if (val == Py_False) {
616
d = 0;
617
} else if (val == Py_True) {
618
d = 1;
619
} else {
620
ok = false;
621
}
622
} else {
623
ok = false;
624
}
625
return d;
626
}
627
628
double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
629
double d = 0;
630
ok = true;
631
if (val->ob_type == &PyFloat_Type) {
632
d = PyFloat_AS_DOUBLE(val);
633
} else if (!strict) {
634
if (val->ob_type == &PyInt_Type) {
635
d = PyInt_AS_LONG(val);
636
} else if (val->ob_type == &PyLong_Type) {
637
d = PyLong_AsLong(val);
638
} else if (val == Py_False) {
639
d = 0;
640
} else if (val == Py_True) {
641
d = 1;
642
} else {
643
ok = false;
644
}
645
} else {
646
ok = false;
647
}
648
return d;
649
}
650
651
QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
652
{
653
QVariant v;
654
bool ok = true;
655
656
if (type==-1) {
657
// no special type requested
658
if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
659
type = QVariant::String;
660
} else if (val->ob_type==&PyInt_Type) {
661
type = QVariant::Int;
662
} else if (val->ob_type==&PyLong_Type) {
663
type = QVariant::LongLong;
664
} else if (val->ob_type==&PyFloat_Type) {
665
type = QVariant::Double;
666
} else if (val == Py_False || val == Py_True) {
667
type = QVariant::Bool;
668
} else if (val->ob_type == &PythonQtWrapper_Type) {
669
PythonQtWrapper* wrap = (PythonQtWrapper*)val;
670
// c++ wrapper, check if the class names of the c++ objects match
671
if (wrap->_info->isCPPWrapper()) {
672
// is this worth anything? we loose the knowledge of the cpp object type
673
v = qVariantFromValue(wrap->_wrappedPtr);
674
} else {
675
v = qVariantFromValue(wrap->_obj);
676
}
677
return v;
678
} else if (val->ob_type==&PyDict_Type) {
679
type = QVariant::Map;
680
} else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
681
type = QVariant::List;
682
} else if (val == Py_None) {
683
// none is invalid
684
type = QVariant::Invalid;
685
} else if (val->ob_type == &PythonQtVariantWrapper_Type) {
686
PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
687
if (varWrap->_variant->userType() == type) {
688
v = *varWrap->_variant;
689
return v;
690
}
691
} else {
692
// this used to be:
693
// type = QVariant::String;
694
// but now we want to transport the Python Objects directly:
695
PythonQtObjectPtr o(val);
696
v = qVariantFromValue(o);
697
return v;
698
}
699
}
700
// special type request:
701
switch (type) {
702
case QVariant::Invalid:
703
return v;
704
break;
705
case QVariant::Int:
706
{
707
int d = PyObjGetInt(val, false, ok);
708
if (ok) return QVariant(d);
709
}
710
break;
711
case QVariant::UInt:
712
{
713
int d = PyObjGetInt(val, false,ok);
714
if (ok) v = QVariant((unsigned int)d);
715
}
716
break;
717
case QVariant::Bool:
718
{
719
int d = PyObjGetBool(val,false,ok);
720
if (ok) v = QVariant((bool)(d!=0));
721
}
722
break;
723
case QVariant::Double:
724
{
725
double d = PyObjGetDouble(val,false,ok);
726
if (ok) v = QVariant(d);
727
break;
728
}
729
case QMetaType::Float:
730
{
731
float d = (float) PyObjGetDouble(val,false,ok);
732
if (ok) v = qVariantFromValue(d);
733
break;
734
}
735
case QMetaType::Long:
736
{
737
long d = (long) PyObjGetLongLong(val,false,ok);
738
if (ok) v = qVariantFromValue(d);
739
break;
740
}
741
case QMetaType::ULong:
742
{
743
unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
744
if (ok) v = qVariantFromValue(d);
745
break;
746
}
747
case QMetaType::Short:
748
{
749
short d = (short) PyObjGetInt(val,false,ok);
750
if (ok) v = qVariantFromValue(d);
751
break;
752
}
753
case QMetaType::UShort:
754
{
755
unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
756
if (ok) v = qVariantFromValue(d);
757
break;
758
}
759
case QMetaType::Char:
760
{
761
char d = (char) PyObjGetInt(val,false,ok);
762
if (ok) v = qVariantFromValue(d);
763
break;
764
}
765
case QMetaType::UChar:
766
{
767
unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
768
if (ok) v = qVariantFromValue(d);
769
break;
770
}
771
772
case QVariant::ByteArray:
773
case QVariant::String:
774
{
775
bool ok;
776
v = QVariant(PyObjGetString(val, false, ok));
777
}
778
break;
779
780
// these are important for MeVisLab
781
case QVariant::Map:
782
{
783
if (PyMapping_Check(val)) {
784
QMap<QString,QVariant> map;
785
PyObject* items = PyMapping_Items(val);
786
if (items) {
787
int count = PyList_Size(items);
788
PyObject* value;
789
PyObject* key;
790
PyObject* tuple;
791
for (int i = 0;i<count;i++) {
792
tuple = PyList_GetItem(items,i);
793
key = PyTuple_GetItem(tuple, 0);
794
value = PyTuple_GetItem(tuple, 1);
795
map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
796
}
797
Py_DECREF(items);
798
v = map;
799
}
800
}
801
}
802
break;
803
case QVariant::List:
804
if (PySequence_Check(val)) {
805
QVariantList list;
806
int count = PySequence_Size(val);
807
PyObject* value;
808
for (int i = 0;i<count;i++) {
809
value = PySequence_GetItem(val,i);
810
list.append(PyObjToQVariant(value, -1));
811
}
812
v = list;
813
}
814
break;
815
case QVariant::StringList:
816
{
817
bool ok;
818
QStringList l = PyObjToStringList(val, false, ok);
819
if (ok) {
820
v = l;
821
}
822
}
823
break;
824
825
default:
826
if (val->ob_type == &PythonQtVariantWrapper_Type) {
827
PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
828
if (varWrap->_variant->userType() == type) {
829
v = *varWrap->_variant;
830
}
831
} else {
832
v = QVariant();
833
}
834
}
835
return v;
836
}
837
838
PyObject* PythonQtConv::QStringToPyObject(const QString& str)
839
{
840
if (str.isNull()) {
841
return PyString_FromString("");
842
} else {
843
#ifdef WIN32
844
// return PyString_FromString(str.toLatin1().data());
845
return PyUnicode_FromUnicode(str.utf16(), str.length());
846
#else
847
return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
848
#endif
849
}
850
}
851
852
PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
853
{
854
PyObject* result = PyTuple_New(list.count());
855
int i = 0;
856
QString str;
857
foreach (str, list) {
858
PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
859
i++;
860
}
861
// why is the error state bad after this?
862
PyErr_Clear();
863
return result;
864
}
865
866
PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
867
{
868
PyObject* result = PyList_New(list.count());
869
int i = 0;
870
for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
871
PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
872
i++;
873
}
874
return result;
875
}
876
877
PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
878
{
879
return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
880
}
881
882
PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
883
PyObject* result = PyDict_New();
884
QVariantMap::const_iterator t = m.constBegin();
885
PyObject* key;
886
PyObject* val;
887
for (;t!=m.end();t++) {
888
key = QStringToPyObject(t.key());
889
val = QVariantToPyObject(t.value());
890
PyDict_SetItem(result, key, val);
891
Py_DECREF(key);
892
Py_DECREF(val);
893
}
894
return result;
895
}
896
897
PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
898
PyObject* result = PyTuple_New(l.count());
899
int i = 0;
900
QVariant v;
901
foreach (v, l) {
902
PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
903
i++;
904
}
905
// why is the error state bad after this?
906
PyErr_Clear();
907
return result;
908
}
909
910
911