aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2024-02-21 16:16:09 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2024-02-22 16:17:27 +0100
commit732be9c2d39ff85b16720821eb29a4ef8e87ab85 (patch)
treec7ec188b63e3f7c5227f7d8a16327212ab23d9ec /sources/pyside6
parentc892b9299db5d240f2753a877b055f13b6239a63 (diff)
Fix conversion of QVariant<->QMatrix<n>x<m>
QMatrix<n>x<m> is a template specialization of QGenericMatrix<n,m,float> which the type name of the QVariant contains. To find the proper Shiboken converter for this, change the name back. As a drive-by, fix @snippet conversion-sbkobject to return a PyObjectWrapper() with warning in cases where the QMetaType is valid but no converter can be found. Fixes: PYSIDE-2599 Pick-to: 6.6 Change-Id: I4f41dcbaa394fcc1732536c0b7a6569f694f3c45 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside6')
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml3
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp53
-rw-r--r--sources/pyside6/tests/pysidetest/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/pysidetest/qvariant_test.py13
-rw-r--r--sources/pyside6/tests/pysidetest/testqvariantenum.h10
-rw-r--r--sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml2
6 files changed, 69 insertions, 13 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 6745f129b..25ceca5c8 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -282,6 +282,9 @@
</primitive-type>
<primitive-type name="QVariant" target-lang-api-name="PyObject">
+ <extra-includes>
+ <include file-name="optional" location="global"/>
+ </extra-includes>
<conversion-rule>
<native-to-target file="../glue/qtcore.cpp" snippet="return-qvariant"/>
<target-to-native>
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index 07e9af0ad..0bf71de04 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -269,6 +269,30 @@ static QVariant QVariant_convertToVariantList(PyObject *list)
}
return QVariant(lst);
}
+
+using SpecificConverter = Shiboken::Conversions::SpecificConverter;
+
+static std::optional<SpecificConverter> converterForQtType(const char *typeNameC)
+{
+ // Fix typedef "QGenericMatrix<3,3,float>" -> QMatrix3x3". The reverse
+ // conversion happens automatically in QMetaType::fromName() in
+ // QVariant_resolveMetaType().
+ QByteArrayView typeNameV(typeNameC);
+ if (typeNameV.startsWith("QGenericMatrix<") && typeNameV.endsWith(",float>")) {
+ QByteArray typeName = typeNameV.toByteArray();
+ typeName.remove(1, 7);
+ typeName.remove(7, 1); // '<'
+ typeName.chop(7);
+ typeName.replace(',', 'x');
+ SpecificConverter matrixConverter(typeName.constData());
+ if (matrixConverter)
+ return matrixConverter;
+ }
+ SpecificConverter converter(typeNameC);
+ if (converter)
+ return converter;
+ return std::nullopt;
+}
// @snippet qvariant-conversion
// @snippet qt-qabs
@@ -1484,15 +1508,23 @@ double in = %CONVERTTOCPP[double](%in);
// @snippet conversion-sbkobject
// a class supported by QVariant?
const QMetaType metaType = QVariant_resolveMetaType(Py_TYPE(%in));
+bool ok = false;
if (metaType.isValid()) {
QVariant var(metaType);
- Shiboken::Conversions::SpecificConverter converter(metaType.name());
- converter.toCpp(pyIn, var.data());
- %out = var;
-} else {
- // If the type was not encountered, return a default PyObjectWrapper
- %out = QVariant::fromValue(PySide::PyObjectWrapper(%in));
+ auto converterO = converterForQtType(metaType.name());
+ ok = converterO.has_value();
+ if (ok) {
+ converterO.value().toCpp(pyIn, var.data());
+ %out = var;
+ } else {
+ qWarning("%s: Cannot find a converter for \"%s\".",
+ __FUNCTION__, metaType.name());
+ }
}
+
+// If the type was not encountered, return a default PyObjectWrapper
+if (!ok)
+ %out = QVariant::fromValue(PySide::PyObjectWrapper(%in));
// @snippet conversion-sbkobject
// @snippet conversion-pydict
@@ -1650,11 +1682,10 @@ default:
break;
}
-Shiboken::Conversions::SpecificConverter converter(cppInRef.typeName());
-if (converter) {
- void *ptr = cppInRef.data();
- return converter.toPython(ptr);
-}
+auto converterO = converterForQtType(cppInRef.typeName());
+if (converterO.has_value())
+ return converterO.value().toPython(cppInRef.data());
+
PyErr_Format(PyExc_RuntimeError, "Can't find converter for '%s'.", %in.typeName());
return 0;
// @snippet return-qvariant
diff --git a/sources/pyside6/tests/pysidetest/CMakeLists.txt b/sources/pyside6/tests/pysidetest/CMakeLists.txt
index 6dc56735d..38f42f342 100644
--- a/sources/pyside6/tests/pysidetest/CMakeLists.txt
+++ b/sources/pyside6/tests/pysidetest/CMakeLists.txt
@@ -46,6 +46,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/testbinding/sharedpointertestbench_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/testbinding/testview_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/testbinding/testbinding_module_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/testbinding/testqvariantenum_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/testbinding/qvariantholder_wrapper.cpp
)
# Get per module include dirs.
diff --git a/sources/pyside6/tests/pysidetest/qvariant_test.py b/sources/pyside6/tests/pysidetest/qvariant_test.py
index 79ac446e3..8b789b2c7 100644
--- a/sources/pyside6/tests/pysidetest/qvariant_test.py
+++ b/sources/pyside6/tests/pysidetest/qvariant_test.py
@@ -11,9 +11,9 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from init_paths import init_test_paths
init_test_paths(True)
-from testbinding import TestObject, TestQVariantEnum
+from testbinding import TestObject, TestQVariantEnum, QVariantHolder
from PySide6.QtCore import Qt, QKeyCombination
-from PySide6.QtGui import QKeySequence, QAction
+from PySide6.QtGui import QKeySequence, QAction, QMatrix3x3
from helper.usesqapplication import UsesQApplication
@@ -64,6 +64,15 @@ class QVariantTest(UsesQApplication):
# check toInt() conversion for IntEnum
self.assertEqual(PyTestQVariantEnum.getNumberFromQVarEnum(Qt.GestureType.TapGesture), 1)
+ def testMatrixTemplates(self):
+ holder = QVariantHolder()
+ matrix = QMatrix3x3()
+ matrix.setToIdentity()
+ holder.setValue(matrix)
+ returned = holder.value()
+ self.assertTrue(returned, QMatrix3x3)
+ self.assertTrue(returned.isIdentity())
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/testqvariantenum.h b/sources/pyside6/tests/pysidetest/testqvariantenum.h
index 46564d268..4b729e3dd 100644
--- a/sources/pyside6/tests/pysidetest/testqvariantenum.h
+++ b/sources/pyside6/tests/pysidetest/testqvariantenum.h
@@ -22,4 +22,14 @@ private:
QVariant m_enum;
};
+class PYSIDETEST_API QVariantHolder // modeled after Q3DParameter, test QVariant conversion
+{
+public:
+ void setValue(QVariant v) { m_variant = v; }
+ QVariant value() const { return m_variant; }
+
+private:
+ QVariant m_variant;
+};
+
#endif // TESTQVARIANT_H
diff --git a/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml b/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml
index bd959f7e3..592d90a83 100644
--- a/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml
+++ b/sources/pyside6/tests/pysidetest/typesystem_pysidetest.xml
@@ -72,6 +72,8 @@
<object-type name="SharedPointerTestbench"/>
+ <value-type name="QVariantHolder"/>
+
<smart-pointer-type name="QSharedPointer" type="shared" getter="data"
reset-method="reset"/>