diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-07-05 21:50:43 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-07-08 21:41:14 +0000 |
commit | c27c7a78a6e4a30b503d8314b0df12636d668efd (patch) | |
tree | 7651f2032754d4dca0c7ab5bf9adb6c40f495956 | |
parent | eaa57f89e6c92ebea1a1715b731d6a4d89578323 (diff) |
Fix 3 strange cases in QSettings.value() round trips of a list
- The "default value" parameter had an int 0 default value, which lead
to strange behavior ['0'] being returned for string lists with
missing keys.
- QStringList was not converted when forcing the type to be list
due to the QByteArray split mechanism.
- String values could not be coerced to a list
Fix the default value to have a default {}.
Add a helper function checking whether a custom type conversion
is actually needed or the default QVariant converter can handle it.
Task-number: PYSIDE-2381
Change-Id: I91b22c05f851c2dc8c3792bd9f1446cfc8ceba51
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 3dfc872e356dd944d9cd03bccd8df5da8b1de472)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/pyside6/PySide6/glue/qtcore.cpp | 40 | ||||
-rw-r--r-- | sources/pyside6/tests/QtCore/qsettings_test.py | 17 |
2 files changed, 56 insertions, 1 deletions
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp index b90a98a51..a706042b4 100644 --- a/sources/pyside6/PySide6/glue/qtcore.cpp +++ b/sources/pyside6/PySide6/glue/qtcore.cpp @@ -99,6 +99,13 @@ static PyObject *convertToPrimitiveType(const QVariant &out, int metaTypeId) static PyObject *settingsTypeCoercion(const QVariant &out, PyTypeObject *typeObj) { if (typeObj == &PyList_Type) { + // Convert any string, etc, to a list of 1 element + if (auto *primitiveValue = convertToPrimitiveType(out, out.typeId())) { + PyObject *list = PyList_New(1); + PyList_SET_ITEM(list, 0, primitiveValue); + return list; + } + const QByteArray out_ba = out.toByteArray(); if (out_ba.isEmpty()) return PyList_New(0); @@ -132,6 +139,36 @@ static PyObject *settingsTypeCoercion(const QVariant &out, PyTypeObject *typeObj return nullptr; } +static bool isEquivalentSettingsType(PyTypeObject *typeObj, int metaTypeId) +{ + switch (metaTypeId) { + case QMetaType::QVariantList: + case QMetaType::QStringList: + return typeObj == &PyList_Type; + case QMetaType::QByteArray: + return typeObj == &PyBytes_Type; + case QMetaType::QString: + return typeObj == &PyUnicode_Type; + case QMetaType::Short: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::UShort: + case QMetaType::ULong: + case QMetaType::ULongLong: + case QMetaType::Int: + case QMetaType::UInt: + return typeObj == &PyLong_Type; + case QMetaType::Double: + case QMetaType::Float: + case QMetaType::Float16: + return typeObj == &PyFloat_Type; + case QMetaType::Bool: + return typeObj == &PyBool_Type; + default: + break; + } + return false; +} // @snippet settings-value-helpers // @snippet qsettings-value @@ -154,7 +191,8 @@ if ((kwds && PyDict_Size(kwds) > 0) || numArgs > 1) { PyTypeObject *typeObj = reinterpret_cast<PyTypeObject*>(%PYARG_3); -if (typeObj && !Shiboken::ObjectType::checkType(typeObj)) { +if (typeObj && !Shiboken::ObjectType::checkType(typeObj) + && !isEquivalentSettingsType(typeObj, out.typeId())) { %PYARG_0 = settingsTypeCoercion(out, typeObj); } else { if (out.isValid()) { diff --git a/sources/pyside6/tests/QtCore/qsettings_test.py b/sources/pyside6/tests/QtCore/qsettings_test.py index 5bae79355..64ceffd70 100644 --- a/sources/pyside6/tests/QtCore/qsettings_test.py +++ b/sources/pyside6/tests/QtCore/qsettings_test.py @@ -51,8 +51,12 @@ class TestQSettings(unittest.TestCase): self.assertTrue(dir.isValid()) file_name = dir.filePath('foo.ini') settings = QSettings(file_name, QSettings.IniFormat) + sample_list = ["a", "b"] + string_list_of_empty = [""] settings.setValue('zero_value', 0) settings.setValue('empty_list', []) + settings.setValue('some_strings', sample_list) + settings.setValue('string_list_of_empty', string_list_of_empty) settings.setValue('bool1', False) settings.setValue('bool2', True) del settings @@ -66,6 +70,10 @@ class TestQSettings(unittest.TestCase): r = settings.value("variable") self.assertEqual(type(r), type(None)) + r = settings.value("variable", type=list) + self.assertEqual(type(r), list) + self.assertEqual(len(r), 0) + # Handling zero value r = settings.value('zero_value') self.assertEqual(type(r), int) @@ -82,6 +90,15 @@ class TestQSettings(unittest.TestCase): self.assertTrue(len(r) == 0) self.assertEqual(type(r), list) + r = settings.value('some_strings') + self.assertEqual(r, sample_list) + + r = settings.value('some_strings', type=list) + self.assertEqual(r, sample_list) + + r = settings.value('string_list_of_empty', type=list) + self.assertEqual(r, string_list_of_empty) + # Booleans r = settings.value('bool1') self.assertEqual(type(r), bool) |