Add conversions for certain Qt types to/from python native types

This commit is contained in:
baldurk
2017-03-28 16:31:58 +01:00
parent 094c4164dc
commit 7a5bf26325
+298
View File
@@ -444,6 +444,304 @@ struct TypeConversion<rdctype::str, false>
return PyUnicode_FromStringAndSize(in.elems, in.count);
}
};
#ifdef ENABLE_QT_CONVERT
template <>
struct TypeConversion<QString, false>
{
static int ConvertFromPy(PyObject *in, QString &out)
{
if(PyUnicode_Check(in))
{
PyObject *bytes = PyUnicode_AsUTF8String(in);
if(!bytes)
return SWIG_ERROR;
char *buf = NULL;
Py_ssize_t size = 0;
int ret = PyBytes_AsStringAndSize(bytes, &buf, &size);
if(ret == 0)
{
out = QString::fromUtf8(buf, (int)(size - 1));
Py_DecRef(bytes);
return SWIG_OK;
}
Py_DecRef(bytes);
return SWIG_ERROR;
}
return SWIG_ERROR;
}
static PyObject *ConvertToPy(PyObject *self, const QString &in)
{
QByteArray bytes = in.toUtf8();
return PyUnicode_FromStringAndSize(bytes.data(), bytes.size());
}
};
template <>
struct TypeConversion<QDateTime, false>
{
static int ConvertFromPy(PyObject *in, QDateTime &out)
{
if(!PyDateTime_Check(in))
return SWIG_TypeError;
QDate date(PyDateTime_GET_YEAR(in), PyDateTime_GET_MONTH(in), PyDateTime_GET_DAY(in));
QTime time(PyDateTime_DATE_GET_HOUR(in), PyDateTime_DATE_GET_MINUTE(in),
PyDateTime_DATE_GET_SECOND(in), PyDateTime_DATE_GET_MICROSECOND(in) / 1000);
out = QDateTime(date, time, QTimeZone::utc());
return SWIG_OK;
}
static PyObject *ConvertToPy(PyObject *self, const QDateTime &in)
{
QDate date = in.date();
QTime time = in.time();
return PyDateTime_FromDateAndTime(date.year(), date.month(), date.day(), time.hour(),
time.minute(), time.second(), time.msec() * 1000);
}
};
template <typename Container, typename U>
struct ContainerConversion
{
// we add some extra parameters so the typemaps for array can use these to get
// nicer failure error messages out with the index that failed
static int ConvertFromPy(PyObject *in, Container &out, int *failIdx)
{
if(!PyList_Check(in))
return SWIG_TypeError;
Py_ssize_t len = PyList_Size(in);
for(Py_ssize_t i = 0; i < len; i++)
{
U u;
int ret = TypeConversion<U>::ConvertFromPy(PyList_GetItem(in, i), u);
if(!SWIG_IsOK(ret))
{
if(failIdx)
*failIdx = i;
return ret;
}
out.append(u);
}
return SWIG_OK;
}
static int ConvertFromPy(PyObject *in, Container &out) { return ConvertFromPy(in, out, NULL); }
static PyObject *ConvertToPyInPlace(PyObject *self, PyObject *list, const Container &in,
int *failIdx)
{
for(int i = 0; i < in.size(); i++)
{
PyObject *elem = TypeConversion<U>::ConvertToPy(self, in[i]);
if(elem)
{
PyList_Append(list, elem);
}
else
{
if(failIdx)
*failIdx = i;
return NULL;
}
}
return list;
}
static PyObject *ConvertToPy(PyObject *self, const Container &in, int *failIdx)
{
PyObject *list = PyList_New(0);
if(!list)
return NULL;
PyObject *ret = ConvertToPyInPlace(self, list, in, failIdx);
// if a failure happened, don't leak the list we created
if(!ret)
Py_XDECREF(list);
return ret;
}
static PyObject *ConvertToPy(PyObject *self, const Container &in)
{
return ConvertToPy(self, in, NULL);
}
};
template <typename U>
struct TypeConversion<QList<U>, false> : ContainerConversion<QList<U>, U>
{
};
template <>
struct TypeConversion<QStringList, false> : ContainerConversion<QList<QString>, QString>
{
};
template <typename U>
struct TypeConversion<QVector<U>, false> : ContainerConversion<QVector<U>, U>
{
};
// specialisation for pair
template <typename A, typename B>
struct TypeConversion<QPair<A, B>, false>
{
static int ConvertFromPy(PyObject *in, QPair<A, B> &out)
{
if(!PyTuple_Check(in))
return SWIG_TypeError;
Py_ssize_t size = PyTuple_Size(in);
if(size != 2)
return SWIG_TypeError;
int ret = TypeConversion<A>::ConvertFromPy(PyTuple_GetItem(in, 0), out.first);
if(SWIG_IsOK(ret))
ret = TypeConversion<B>::ConvertFromPy(PyTuple_GetItem(in, 1), out.second);
return ret;
}
static PyObject *ConvertToPy(PyObject *self, const QPair<A, B> &in)
{
PyObject *first = TypeConversion<A>::ConvertToPy(self, in.first);
if(!first)
return NULL;
PyObject *second = TypeConversion<B>::ConvertToPy(self, in.second);
if(!second)
return NULL;
PyObject *ret = PyTuple_New(2);
if(!ret)
return NULL;
PyTuple_SetItem(ret, 0, first);
PyTuple_SetItem(ret, 1, second);
return ret;
}
};
template <typename K, typename V>
struct TypeConversion<QMap<K, V>, false>
{
// we add some extra parameters so the typemaps for array can use these to get
// nicer failure error messages out with the index that failed
static int ConvertFromPy(PyObject *in, QMap<K, V> &out, int *failIdx)
{
if(!PyDict_Check(in))
return SWIG_TypeError;
PyObject *keys = PyDict_Keys(in);
if(!keys)
return SWIG_TypeError;
Py_ssize_t len = PyList_Size(keys);
for(Py_ssize_t i = 0; i < len; i++)
{
K k;
V v;
PyObject *key = PyList_GetItem(keys, i);
PyObject *value = PyDict_GetItem(in, key);
int ret = TypeConversion<K>::ConvertFromPy(key, k);
int ret2 = TypeConversion<V>::ConvertFromPy(value, v);
if(!SWIG_IsOK(ret) || !SWIG_IsOK(ret2))
{
if(failIdx)
*failIdx = i;
Py_DecRef(keys);
if(!SWIG_IsOK(ret))
return ret;
else
return ret2;
}
out.insert(k, v);
}
Py_DecRef(keys);
return SWIG_OK;
}
static int ConvertFromPy(PyObject *in, QMap<K, V> &out) { return ConvertFromPy(in, out, NULL); }
static PyObject *ConvertToPyInPlace(PyObject *self, PyObject *pymap, const QMap<K, V> &in,
int *failIdx)
{
QList<K> keys = in.keys();
for(int i = 0; i < keys.size(); i++)
{
const K &k = keys[i];
PyObject *key = TypeConversion<K>::ConvertToPy(self, k);
if(key)
{
PyObject *value = TypeConversion<V>::ConvertToPy(self, in[k]);
if(value)
{
PyDict_SetItem(pymap, key, value);
continue;
}
}
if(failIdx)
*failIdx = i;
return NULL;
}
return pymap;
}
static PyObject *ConvertToPy(PyObject *self, const QMap<K, V> &in, int *failIdx)
{
PyObject *list = PyDict_New();
if(!list)
return NULL;
PyObject *ret = ConvertToPyInPlace(self, list, in, failIdx);
// if a failure happened, don't leak the map we created
if(!ret)
Py_XDECREF(list);
return ret;
}
static PyObject *ConvertToPy(PyObject *self, const QMap<K, V> &in)
{
return ConvertToPy(self, in, NULL);
}
};
#endif
// free functions forward to struct
template <typename T>
int ConvertFromPy(PyObject *in, T &out)