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