aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-01-06 17:18:06 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-01-11 10:27:16 +0100
commit9bc3eed5c8e267f11fe63cc3fb5068e9fce2f64d (patch)
tree6ab7d88e8974e4e5b698feaa8cd360b693f98828
parente0e24376824efb2a7bf2f00605bdb0f7152d389e (diff)
shiboken6: Add element for opaque containers
Add an element enabling adding opaque containers to existing container-type entries (including builtins). Task-number: PYSIDE-1605 Task-number: PYSIDE-2174 Change-Id: I1b4a94331b264dc5e9503ab795edf882dfaa070f Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml2
-rw-r--r--sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml2
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.cpp20
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase_p.h3
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp30
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser_p.h2
-rw-r--r--sources/shiboken6/doc/typesystem_containers.rst3
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst19
-rw-r--r--sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml15
9 files changed, 78 insertions, 18 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 391e10032..91afc3b2a 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -368,7 +368,7 @@
<!-- FIXME: Which one is it going to be? -->
<container-type name="QList" type="list"
- opaque-containers="int:QIntList;QPoint:QPointList;QPointF:QPointFList;QVector2D:QVector2DList;QVector3D:QVector3DList;QVector4D:QVector4DList">
+ opaque-containers="int:QIntList;QPoint:QPointList;QPointF:QPointFList">
<include file-name="QList" location="global"/>
<declare-function signature="append(T)" return-type="void"/>
<declare-function signature="insert(qsizetype,T)" return-type="void"/>
diff --git a/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml b/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
index f6e98b5cf..673a12f32 100644
--- a/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
+++ b/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
@@ -3126,4 +3126,6 @@
</object-type>
</namespace-type>
+ <opaque-container name="QList" opaque-containers="QVector2D:QVector2DList;QVector3D:QVector3DList;QVector4D:QVector4DList"/>
+
</typesystem>
diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp
index adb092f19..1b2d7e7b7 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp
@@ -129,6 +129,7 @@ struct TypeDatabasePrivate
const CustomTypeEntryPtr &targetLang);
void addBuiltInPrimitiveTypes();
void addBuiltInContainerTypes(const TypeDatabaseParserContextPtr &context);
+ bool addOpaqueContainers(const TypeDatabaseParserContextPtr &context);
TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const;
template <class Predicate>
TypeEntryCList findTypesHelper(const QString &name, Predicate pred) const;
@@ -904,6 +905,22 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
Q_ASSERT(ok);
}
+bool TypeDatabasePrivate::addOpaqueContainers(const TypeDatabaseParserContextPtr &context)
+{
+ const auto &och = context->opaqueContainerHash;
+ for (auto it = och.cbegin(), end = och.cend(); it != end; ++it) {
+ const QString &name = it.key();
+ auto te = findType(name);
+ if (!te || !te->isContainer()) {
+ qCWarning(lcShiboken, "No container \"%s\" found.", qPrintable(name));
+ return false;
+ }
+ auto cte = std::static_pointer_cast<ContainerTypeEntry>(te);
+ cte->appendOpaqueContainers(it.value());
+ }
+ return true;
+}
+
bool TypeDatabase::parseFile(const QString &filename, bool generate)
{
QString filepath = modifiedTypesystemFilepath(filename, {});
@@ -975,7 +992,8 @@ bool TypeDatabasePrivate::parseFile(QIODevice *device, TypeDatabase *db, bool ge
addBuiltInPrimitiveTypes();
addBuiltInContainerTypes(context);
- return resolveSmartPointerInstantiations(context);
+ return addOpaqueContainers(context)
+ && resolveSmartPointerInstantiations(context);
}
bool TypeDatabase::parseFile(const TypeDatabaseParserContextPtr &context,
diff --git a/sources/shiboken6/ApiExtractor/typedatabase_p.h b/sources/shiboken6/ApiExtractor/typedatabase_p.h
index 04c1df145..fc56c7961 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase_p.h
+++ b/sources/shiboken6/ApiExtractor/typedatabase_p.h
@@ -5,6 +5,7 @@
#define TYPEDATABASE_P_H
#include "typesystem_typedefs.h"
+#include "containertypeentry.h"
#include <QtCore/QHash>
#include <QtCore/QString>
@@ -14,9 +15,11 @@ class TypeDatabase;
struct TypeDatabaseParserContext
{
using SmartPointerInstantiations = QHash<SmartPointerTypeEntryPtr, QString>;
+ using OpaqueContainerHash = QHash<QString, OpaqueContainers>;
TypeDatabase *db;
SmartPointerInstantiations smartPointerInstantiations;
+ OpaqueContainerHash opaqueContainerHash;
};
#endif // TYPEDATABASE_P_H
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index f7168adfb..8898c8715 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -465,6 +465,7 @@ static const StackElementHash &stackElementHash()
{u"native-to-target", StackElement::NativeToTarget},
{u"no-null-pointer", StackElement::NoNullPointers},
{u"object-type", StackElement::ObjectTypeEntry},
+ {u"opaque-container", StackElement::OpaqueContainer},
{u"parent", StackElement::ParentOwner},
{u"primitive-type", StackElement::PrimitiveTypeEntry},
{u"property", StackElement::Property},
@@ -1544,6 +1545,28 @@ ContainerTypeEntryPtr
return type;
}
+bool TypeSystemParser::parseOpaqueContainerElement(QXmlStreamAttributes *attributes)
+{
+ QString containerName;
+ OpaqueContainers oc;
+ for (auto i = attributes->size() - 1; i >= 0; --i) {
+ const auto name = attributes->at(i).qualifiedName();
+ if (name == nameAttribute()) {
+ containerName = attributes->takeAt(i).value().toString();
+ } else if (name == opaqueContainerAttribute()) {
+ const auto attribute = attributes->takeAt(i);
+ if (!parseOpaqueContainers(attribute.value(), &oc))
+ return false;
+ }
+ }
+ if (containerName.isEmpty()) {
+ m_error = msgMissingAttribute(nameAttribute());
+ return false;
+ }
+ m_context->opaqueContainerHash[containerName].append(oc);
+ return true;
+}
+
EnumTypeEntryPtr
TypeSystemParser::parseEnumTypeEntry(const ConditionalStreamReader &reader,
const QString &name, const QVersionNumber &since,
@@ -3333,7 +3356,8 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
|| element == StackElement::ConversionRule
|| element == StackElement::AddFunction
|| element == StackElement::DeclareFunction
- || element == StackElement::Template;
+ || element == StackElement::Template
+ || element == StackElement::OpaqueContainer;
if (!topLevel && m_stack.at(m_stack.size() - 2) == StackElement::Root) {
m_error = u"Tag requires parent: '"_s + tagName.toString() + u'\'';
@@ -3503,6 +3527,10 @@ bool TypeSystemParser::startElement(const ConditionalStreamReader &reader, Stack
if (!parseReplace(reader, topElement, &attributes))
return false;
break;
+ case StackElement::OpaqueContainer:
+ if (!parseOpaqueContainerElement(&attributes))
+ return false;
+ break;
default:
break; // nada
}
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser_p.h b/sources/shiboken6/ApiExtractor/typesystemparser_p.h
index 68faab34b..01463f056 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser_p.h
+++ b/sources/shiboken6/ApiExtractor/typesystemparser_p.h
@@ -103,6 +103,7 @@ enum class StackElement {
ArgumentModifiers,
ImportFile,
+ OpaqueContainer,
Unimplemented
};
@@ -172,6 +173,7 @@ private:
ContainerTypeEntryPtr
parseContainerTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
+ bool parseOpaqueContainerElement(QXmlStreamAttributes *attributes);
EnumTypeEntryPtr
parseEnumTypeEntry(const ConditionalStreamReader &, const QString &name,
const QVersionNumber &since, QXmlStreamAttributes *);
diff --git a/sources/shiboken6/doc/typesystem_containers.rst b/sources/shiboken6/doc/typesystem_containers.rst
index 5c4abee44..ffcae88a1 100644
--- a/sources/shiboken6/doc/typesystem_containers.rst
+++ b/sources/shiboken6/doc/typesystem_containers.rst
@@ -19,7 +19,8 @@ instead of a Python list. Manipulations like adding or removing elements
can applied directly to them using the C++ container functions.
This is achieved by specifying the name and the instantiated type
-in the ``opaque-containers`` attribute of :ref:`container-type`.
+in the ``opaque-containers`` attribute of :ref:`container-type`
+or using the :ref:`opaque-container` element for existing container types.
A second use case are public fields of container types. In the normal case,
they are converted to Python containers on read access. By a field modification,
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 6b58faa36..52b0ee4df 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -34,6 +34,7 @@ typesystem
It may contain :ref:`add-function`, :ref:`container-type`,
:ref:`custom-type`, :ref:`enum-type`, :ref:`extra-includes`, :ref:`function`,
:ref:`load-typesystem`, :ref:`namespace`, :ref:`object-type`,
+ :ref:`opaque-container`,
:ref:`primitive-type`, :ref:`rejection`, :ref:`smart-pointer-type`,
:ref:`suppress-warning`, :ref:`template`, :ref:`system_include`,
:ref:`typedef-type` or :ref:`value-type` child nodes.
@@ -549,6 +550,24 @@ container-type
and there are also a number of useful
:ref:`predefined conversion templates <predefined_templates>`.
+.. _opaque-container:
+
+opaque-container
+^^^^^^^^^^^^^^^^
+
+ The ``opaque-container`` element can be used to add further instantiations
+ of :ref:`opaque containers <opaque-containers>` to existing container types
+ (built-in or specified by :ref:`container-type` in included modules).
+ It is a child of the :ref:`typesystem` node.
+
+ .. code-block:: xml
+
+ <typesystem>
+ <oqaque-container name="..." opaque-containers ="..." />
+ </typesystem>
+
+ For the **name** and **opaque-containers** attributes,
+ see :ref:`container-type`.
.. _typedef-type:
diff --git a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
index 3fac1b2b3..b5e0d0532 100644
--- a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
+++ b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
@@ -15,20 +15,7 @@
</conversion-rule>
</primitive-type>
- <container-type name="std::list" type="list"
- opaque-containers="int:StdIntList">
- <include file-name="list" location="global"/>
- <conversion-rule>
- <native-to-target>
- <insert-template name="shiboken_conversion_cppsequence_to_pylist"/>
- </native-to-target>
- <target-to-native>
- <add-conversion type="PySequence">
- <insert-template name="shiboken_conversion_pyiterable_to_cppsequentialcontainer"/>
- </add-conversion>
- </target-to-native>
- </conversion-rule>
- </container-type>
+ <opaque-container name="std::list" opaque-containers="int:StdIntList"/>
<object-type name="Obj"/>
<value-type name="Val">