Skip to content

Commit cd4761f

Browse files
committed
allow to override QVariantList conversion
autodetect RichCompare
1 parent 922109d commit cd4761f

File tree

7 files changed

+60
-5
lines changed

7 files changed

+60
-5
lines changed

src/PythonQtClassInfo.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ PythonQtClassInfo::PythonQtClassInfo() {
6161
_typeSlots = 0;
6262
_isQObject = false;
6363
_enumsCreated = false;
64+
_richCompareDetectionDone = false;
6465
_searchPolymorphicHandlerOnParent = true;
6566
_searchRefCountCB = true;
6667
_refCallback = NULL;
@@ -1034,6 +1035,34 @@ PythonQtClassInfo* PythonQtClassInfo::getClassInfoForProperty( const QString& na
10341035
}
10351036
return NULL;
10361037
}
1038+
1039+
bool PythonQtClassInfo::supportsRichCompare()
1040+
{
1041+
if (_typeSlots & PythonQt::Type_RichCompare) {
1042+
return true;
1043+
}
1044+
if (!_richCompareDetectionDone) {
1045+
_richCompareDetectionDone = true;
1046+
static QList<QByteArray> names;
1047+
if (names.isEmpty()) {
1048+
names << "__eq__";
1049+
names << "__ne__";
1050+
names << "__lt__";
1051+
names << "__le__";
1052+
names << "__gt__";
1053+
names << "__ge__";
1054+
}
1055+
foreach (const QByteArray& name, names) {
1056+
if (member(name)._type == PythonQtMemberInfo::Slot) {
1057+
// we found one of the operators, so we can support the type slot
1058+
_typeSlots |= PythonQt::Type_RichCompare;
1059+
break;
1060+
}
1061+
}
1062+
}
1063+
return (_typeSlots & PythonQt::Type_RichCompare);
1064+
}
1065+
10371066
//-------------------------------------------------------------------------
10381067

10391068
PythonQtMemberInfo::PythonQtMemberInfo( PythonQtSlotInfo* info )

src/PythonQtClassInfo.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
185185
void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
186186
_shellSetInstanceWrapperCB = cb;
187187
}
188-
188+
189189
//! get the shell set instance wrapper cb
190190
PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
191191
return _shellSetInstanceWrapperCB;
@@ -230,6 +230,12 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
230230
//! Returns the class info for given property, if available.
231231
PythonQtClassInfo* getClassInfoForProperty( const QString& name );
232232

233+
//! Returns if the class supports rich compare. This tests for
234+
//! __eq__, __ne__, __lt__, __le__, __gt__, __ge__ slots and if
235+
//! any of the slots is present it returns true and modifies the
236+
//! _typeSlots with Type_RichCompare. The result is cached internally.
237+
bool supportsRichCompare();
238+
233239
private:
234240
void updateRefCountingCBs();
235241

@@ -289,6 +295,7 @@ class PYTHONQT_EXPORT PythonQtClassInfo {
289295

290296
bool _isQObject;
291297
bool _enumsCreated;
298+
bool _richCompareDetectionDone;
292299
bool _searchPolymorphicHandlerOnParent;
293300
bool _searchRefCountCB;
294301

src/PythonQtConversion.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStora
5555
QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
5656
QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
5757

58+
PythonQtConvertPythonSequenceToQVariantListCB* PythonQtConv::_pythonSequenceToQVariantListCB = NULL;
59+
5860
PyObject* PythonQtConv::GetPyBool(bool val)
5961
{
6062
PyObject* r = val?Py_True:Py_False;
@@ -1028,13 +1030,13 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
10281030
v = qVariantFromValue(myObject);
10291031
}
10301032
return v;
1033+
} else if (val == Py_None) {
1034+
// none is invalid
1035+
type = QVariant::Invalid;
10311036
} else if (PyDict_Check(val)) {
10321037
type = QVariant::Map;
10331038
} else if (PyList_Check(val) || PyTuple_Check(val) || PySequence_Check(val)) {
10341039
type = QVariant::List;
1035-
} else if (val == Py_None) {
1036-
// none is invalid
1037-
type = QVariant::Invalid;
10381040
} else {
10391041
// this used to be:
10401042
// type = QVariant::String;
@@ -1152,6 +1154,12 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
11521154
break;
11531155
case QVariant::List:
11541156
if (PySequence_Check(val)) {
1157+
if (_pythonSequenceToQVariantListCB) {
1158+
QVariant result = (*_pythonSequenceToQVariantListCB)(val);
1159+
if (result.isValid()) {
1160+
return result;
1161+
}
1162+
}
11551163
int count = PySequence_Size(val);
11561164
if (count >= 0) {
11571165
// only get items if size is valid (>= 0)

src/PythonQtConversion.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
5454
typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
55+
typedef QVariant PythonQtConvertPythonSequenceToQVariantListCB(PyObject* inObject);
5556

5657
#define PythonQtRegisterListTemplateConverter(type, innertype) \
5758
{ int typeId = qRegisterMetaType<type<innertype > >(#type"<"#innertype">"); \
@@ -164,6 +165,10 @@ class PYTHONQT_EXPORT PythonQtConv {
164165
//! register a converter callback from cpp to python for given metatype
165166
static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
166167

168+
//! set a callback that is called when a Python sequence should be converted to a QVariantList
169+
//! to allow special conversion.
170+
static void setPythonSequenceToQVariantListCallback(PythonQtConvertPythonSequenceToQVariantListCB* cb) { _pythonSequenceToQVariantListCB = cb; }
171+
167172
//! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
168173
static PyObject* convertQtValueToPythonInternal(int type, const void* data);
169174

@@ -194,6 +199,7 @@ class PYTHONQT_EXPORT PythonQtConv {
194199
protected:
195200
static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
196201
static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
202+
static PythonQtConvertPythonSequenceToQVariantListCB* _pythonSequenceToQVariantListCB;
197203

198204
//! handle automatic conversion of some special types (QColor, QBrush, ...)
199205
static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);

src/PythonQtInstanceWrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wr
238238
}
239239
}
240240

241-
if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
241+
if (!wrapper->classInfo()->supportsRichCompare()) {
242242
// shortcut if richcompare is not supported:
243243
if (validPtrs && code == Py_EQ) {
244244
return PythonQtConv::GetPyBool(areSamePtrs);

src/PythonQtStdOut.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*arg
4747
self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
4848

4949
self->softspace = 0;
50+
self->closed = false;
5051
self->_cb = NULL;
5152

5253
return (PyObject *)self;
@@ -117,6 +118,9 @@ static PyMemberDef PythonQtStdOutRedirect_members[] = {
117118
{const_cast<char*>("softspace"), T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
118119
const_cast<char*>("soft space flag")
119120
},
121+
{ const_cast<char*>("closed"), T_BOOL, offsetof(PythonQtStdOutRedirect, closed), 0,
122+
const_cast<char*>("soft space flag")
123+
},
120124
{NULL} /* Sentinel */
121125
};
122126

src/PythonQtStdOut.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef struct {
5959
PyObject_HEAD
6060
PythonQtOutputChangedCB* _cb;
6161
int softspace;
62+
bool closed;
6263
} PythonQtStdOutRedirect;
6364

6465
#endif

0 commit comments

Comments
 (0)