Skip to content

Commit ef257ed

Browse files
committed
simplified QList<Object*> conversion
added support for QList<...> and converters on Qt properties / QVariant conversion
1 parent 75b79cc commit ef257ed

File tree

4 files changed

+175
-99
lines changed

4 files changed

+175
-99
lines changed

src/PythonQtConversion.cpp

Lines changed: 90 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,18 @@ PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::Paramet
8585
return Py_None;
8686
}
8787
} else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
88-
info.name.startsWith("QList<")) {
89-
// it is a QList template:
90-
QByteArray innerType = info.name.mid(6,info.name.length()-7);
91-
if (innerType.endsWith("*")) {
92-
innerType.truncate(innerType.length()-1);
93-
QList<void*>* listPtr = NULL;
94-
if (info.pointerCount == 1) {
95-
listPtr = *((QList<void*>**)data);
96-
} else if (info.pointerCount == 0) {
97-
listPtr = (QList<void*>*)data;
98-
}
99-
if (listPtr) {
100-
return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
101-
} else {
102-
return NULL;
103-
}
88+
info.isQList && (info.innerNamePointerCount == 1)) {
89+
// it is a QList<Obj*> template:
90+
QList<void*>* listPtr = NULL;
91+
if (info.pointerCount == 1) {
92+
listPtr = *((QList<void*>**)data);
93+
} else if (info.pointerCount == 0) {
94+
listPtr = (QList<void*>*)data;
95+
}
96+
if (listPtr) {
97+
return ConvertQListOfPointerTypeToPythonList(listPtr, info.innerName);
98+
} else {
99+
return NULL;
104100
}
105101
}
106102

@@ -208,9 +204,9 @@ PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* dat
208204
}
209205
std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
210206
}
211-
}
212-
Py_INCREF(Py_None);
213-
return Py_None;
207+
}
208+
Py_INCREF(Py_None);
209+
return Py_None;
214210
}
215211

216212
void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
@@ -243,20 +239,15 @@ return Py_None;
243239
// return the ptr to the variant
244240
break;
245241
default:
246-
if (info.typeId == PythonQtMethodInfo::Unknown) {
247-
// check if we have a QList of pointers, which we can circumvent with a QList<void*>
248-
if (info.name.startsWith("QList<")) {
249-
QByteArray innerType = info.name.mid(6,info.name.length()-7);
250-
if (innerType.endsWith("*")) {
251-
static int id = QMetaType::type("QList<void*>");
252-
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
253-
// return the constData pointer that will be filled with the result value later on
254-
ptr = (void*)((QVariant*)ptr)->constData();
255-
}
256-
}
242+
// check if we have a QList of pointers, which we can circumvent with a QList<void*>
243+
if (info.isQList && (info.innerNamePointerCount == 1)) {
244+
static int id = QMetaType::type("QList<void*>");
245+
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
246+
// return the constData pointer that will be filled with the result value later on
247+
ptr = (void*)((QVariant*)ptr)->constData();
257248
}
258249

259-
if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
250+
if (!ptr && info.typeId != PythonQtMethodInfo::Unknown) {
260251
// everything else is stored in a QVariant, if we know the meta type...
261252
PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
262253
// return the constData pointer that will be filled with the result value later on
@@ -631,23 +622,19 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i
631622

632623
if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
633624
// check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
634-
if (info.name.startsWith("QList<")) {
635-
QByteArray innerType = info.name.mid(6,info.name.length()-7);
636-
if (innerType.endsWith("*")) {
637-
innerType.truncate(innerType.length()-1);
638-
static int id = QMetaType::type("QList<void*>");
639-
if (!alreadyAllocatedCPPObject) {
640-
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
641-
ptr = (void*)((QVariant*)ptr)->constData();
642-
} else {
643-
ptr = alreadyAllocatedCPPObject;
644-
}
645-
ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
646-
if (ok) {
647-
return ptr;
648-
} else {
649-
return NULL;
650-
}
625+
if (info.isQList && (info.innerNamePointerCount == 1)) {
626+
static int id = QMetaType::type("QList<void*>");
627+
if (!alreadyAllocatedCPPObject) {
628+
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject, global_variantStorage, QVariant, QVariant::Type(id), ptr);
629+
ptr = (void*)((QVariant*)ptr)->constData();
630+
} else {
631+
ptr = alreadyAllocatedCPPObject;
632+
}
633+
ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, info.innerName, strict);
634+
if (ok) {
635+
return ptr;
636+
} else {
637+
return NULL;
651638
}
652639
}
653640
}
@@ -1138,10 +1125,48 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
11381125
// construct a new variant from the C++ object if it has the same meta type
11391126
v = QVariant(type, wrap->_wrappedPtr);
11401127
} else {
1141-
v = QVariant();
1128+
// Try to convert the object to a QVariant based on the typeName
1129+
bool ok;
1130+
bool isPtr = false;
1131+
QByteArray typeName = QMetaType::typeName(type);
1132+
if (typeName.endsWith("*")) {
1133+
isPtr = true;
1134+
typeName.truncate(typeName.length() - 1);
1135+
}
1136+
void* object = castWrapperTo(wrap, typeName, ok);
1137+
if (ok) {
1138+
if (isPtr) {
1139+
v = QVariant(type, &object);
1140+
}
1141+
else {
1142+
v = QVariant(type, object);
1143+
}
1144+
}
1145+
}
1146+
} else if (type >= QVariant::UserType) {
1147+
// not an instance wrapper, but there might be other converters
1148+
// Maybe we have a special converter that is registered for that type:
1149+
PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(type);
1150+
if (converter) {
1151+
// allocate a default object of the needed type:
1152+
v = QVariant(type, NULL);
1153+
// now call the converter, passing the internal object of the variant
1154+
ok = (*converter)(val, (void*)v.constData(), type, true);
1155+
if (!ok) {
1156+
v = QVariant();
1157+
}
1158+
} else {
1159+
// try QList<AnyObject*>...
1160+
const PythonQtMethodInfo::ParameterInfo& info = PythonQtMethodInfo::getParameterInfoForMetaType(type);
1161+
if (info.isQList && (info.innerNamePointerCount == 1)) {
1162+
// allocate a default object of the needed type:
1163+
v = QVariant(type, NULL);
1164+
ok = ConvertPythonListToQListOfPointerType(val, (QList<void*>*)v.constData(), info.innerName, true);
1165+
if (!ok) {
1166+
v = QVariant();
1167+
}
1168+
}
11421169
}
1143-
} else {
1144-
v = QVariant();
11451170
}
11461171
}
11471172
return v;
@@ -1183,7 +1208,20 @@ PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
11831208

11841209
PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
11851210
{
1186-
return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1211+
if (!v.isValid()) {
1212+
Py_INCREF(Py_None);
1213+
return Py_None;
1214+
}
1215+
PyObject* obj = NULL;
1216+
if (v.userType() >= QMetaType::User && !PythonQt::priv()->isPythonQtObjectPtrMetaId(v.userType())) {
1217+
// try the slower way, which supports more conversions, e.g. QList<QObject*>
1218+
const PythonQtMethodInfo::ParameterInfo& info = PythonQtMethodInfo::getParameterInfoForMetaType(v.userType());
1219+
obj = ConvertQtValueToPython(info, v.constData());
1220+
} else {
1221+
// try the quick way to convert it, since it is a built-in type:
1222+
obj = ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1223+
}
1224+
return obj;
11871225
}
11881226

11891227
template <typename Map>
@@ -1262,31 +1300,6 @@ bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<vo
12621300
return result;
12631301
}
12641302

1265-
int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1266-
{
1267-
int idx = typeName.indexOf("<");
1268-
if (idx>0) {
1269-
int idx2 = typeName.lastIndexOf(">");
1270-
if (idx2>0) {
1271-
QByteArray innerType = typeName.mid(idx+1,idx2-idx-1).trimmed();
1272-
return QMetaType::type(innerType.constData());
1273-
}
1274-
}
1275-
return QMetaType::Void;
1276-
}
1277-
1278-
QByteArray PythonQtConv::getInnerTemplateTypeName(const QByteArray& typeName)
1279-
{
1280-
int idx = typeName.indexOf("<");
1281-
if (idx > 0) {
1282-
int idx2 = typeName.lastIndexOf(">");
1283-
if (idx2 > 0) {
1284-
return typeName.mid(idx + 1, idx2 - idx - 1).trimmed();
1285-
}
1286-
}
1287-
return QByteArray();
1288-
}
1289-
12901303

12911304
QString PythonQtConv::CPPObjectToString(int type, const void* data) {
12921305
QString r;

src/PythonQtConversion.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,6 @@ class PYTHONQT_EXPORT PythonQtConv {
165165
//! register a converter callback from cpp to python for given metatype
166166
static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
167167

168-
//! returns the inner type id of a simple template of the form SomeObject<InnerType>
169-
static int getInnerTemplateMetaType(const QByteArray& typeName);
170-
171-
//! returns the inner type name of a simple template of the form SomeObject<InnerType>
172-
static QByteArray getInnerTemplateTypeName(const QByteArray& typeName);
173-
174168
//! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
175169
static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
176170

@@ -207,7 +201,7 @@ template<class ListType, class T>
207201
PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
208202
{
209203
ListType* list = (ListType*)inList;
210-
static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
204+
static const int innerType = PythonQtMethodInfo::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
211205
if (innerType == QVariant::Invalid) {
212206
std::cerr << "PythonQtConvertListOfValueTypeToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
213207
}
@@ -224,7 +218,7 @@ template<class ListType, class T>
224218
bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
225219
{
226220
ListType* list = (ListType*)outList;
227-
static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
221+
static const int innerType = PythonQtMethodInfo::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
228222
if (innerType == QVariant::Invalid) {
229223
std::cerr << "PythonQtConvertPythonListToListOfValueType: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
230224
}
@@ -256,7 +250,7 @@ template<class ListType, class T>
256250
PyObject* PythonQtConvertListOfKnownClassToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
257251
{
258252
ListType* list = (ListType*)inList;
259-
static PythonQtClassInfo* innerType = PythonQt::priv()->getClassInfo(PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId))));
253+
static PythonQtClassInfo* innerType = PythonQt::priv()->getClassInfo(PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId))));
260254
if (innerType == NULL) {
261255
std::cerr << "PythonQtConvertListOfKnownClassToPythonList: unknown inner type " << innerType->className().constData() << std::endl;
262256
}
@@ -276,7 +270,7 @@ template<class ListType, class T>
276270
bool PythonQtConvertPythonListToListOfKnownClass(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
277271
{
278272
ListType* list = (ListType*)outList;
279-
static PythonQtClassInfo* innerType = PythonQt::priv()->getClassInfo(PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId))));
273+
static PythonQtClassInfo* innerType = PythonQt::priv()->getClassInfo(PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId))));
280274
if (innerType == NULL) {
281275
std::cerr << "PythonQtConvertListOfKnownClassToPythonList: unknown inner type " << innerType->className().constData() << std::endl;
282276
}
@@ -317,7 +311,7 @@ PyObject* PythonQtConvertPairToPython(const void* /*QPair<T1,T2>* */ inPair, int
317311
static int innerType1 = -1;
318312
static int innerType2 = -1;
319313
if (innerType1==-1) {
320-
QByteArray innerTypes = PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
314+
QByteArray innerTypes = PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
321315
QList<QByteArray> names = innerTypes.split(',');
322316
innerType1 = QMetaType::type(names.at(0).trimmed());
323317
innerType2 = QMetaType::type(names.at(1).trimmed());
@@ -338,7 +332,7 @@ bool PythonQtConvertPythonToPair(PyObject* obj, void* /*QPair<T1,T2>* */ outPair
338332
static int innerType1 = -1;
339333
static int innerType2 = -1;
340334
if (innerType1 == -1) {
341-
QByteArray innerTypes = PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
335+
QByteArray innerTypes = PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
342336
QList<QByteArray> names = innerTypes.split(',');
343337
innerType1 = QMetaType::type(names.at(0).trimmed());
344338
innerType2 = QMetaType::type(names.at(1).trimmed());
@@ -381,7 +375,7 @@ template<class ListType, class T1, class T2>
381375
PyObject* PythonQtConvertListOfPairToPythonList(const void* /*QList<QPair<T1,T2> >* */ inList, int metaTypeId)
382376
{
383377
ListType* list = (ListType*)inList;
384-
static int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
378+
static int innerType = PythonQtMethodInfo::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
385379
if (innerType == QVariant::Invalid) {
386380
std::cerr << "PythonQtConvertListOfPairToPythonList: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
387381
}
@@ -400,7 +394,7 @@ template<class ListType, class T1, class T2>
400394
bool PythonQtConvertPythonListToListOfPair(PyObject* obj, void* /*QList<QPair<T1,T2> >* */ outList, int metaTypeId, bool /*strict*/)
401395
{
402396
ListType* list = (ListType*)outList;
403-
static int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
397+
static int innerType = PythonQtMethodInfo::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
404398
if (innerType == QVariant::Invalid) {
405399
std::cerr << "PythonQtConvertPythonListToListOfPair: unknown inner type " << QMetaType::typeName(metaTypeId) << std::endl;
406400
}
@@ -433,7 +427,7 @@ PyObject* PythonQtConvertIntegerMapToPython(const void* /*QMap<int, T>* */ inMap
433427
MapType* map = (MapType*)inMap;
434428
static int innerType = -1;
435429
if (innerType == -1) {
436-
QByteArray innerTypes = PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
430+
QByteArray innerTypes = PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
437431
QList<QByteArray> names = innerTypes.split(',');
438432
innerType = QMetaType::type(names.at(1).trimmed());
439433
}
@@ -461,7 +455,7 @@ bool PythonQtConvertPythonToIntegerMap(PyObject* val, void* /*QMap<int, T>* */ o
461455
MapType* map = (MapType*)outMap;
462456
static int innerType = -1;
463457
if (innerType == -1) {
464-
QByteArray innerTypes = PythonQtConv::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
458+
QByteArray innerTypes = PythonQtMethodInfo::getInnerTemplateTypeName(QByteArray(QMetaType::typeName(metaTypeId)));
465459
QList<QByteArray> names = innerTypes.split(',');
466460
innerType = QMetaType::type(names.at(1).trimmed());
467461
}

0 commit comments

Comments
 (0)