aboutsummaryrefslogtreecommitdiffstats
path: root/examples/qml
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qml')
-rw-r--r--examples/qml/editingmodel/MovingRectangle.qml78
-rw-r--r--examples/qml/editingmodel/doc/editingmodel.rst14
-rw-r--r--examples/qml/editingmodel/doc/qabstractlistmodelqml.pngbin0 -> 45810 bytes
-rw-r--r--examples/qml/editingmodel/main.py21
-rw-r--r--examples/qml/editingmodel/main.pyproject3
-rw-r--r--examples/qml/editingmodel/main.qml106
-rw-r--r--examples/qml/editingmodel/model.py157
-rw-r--r--examples/qml/referenceexamples/adding/adding.pyproject5
-rw-r--r--examples/qml/referenceexamples/adding/doc/adding.rst67
-rw-r--r--examples/qml/referenceexamples/adding/example.qml9
-rw-r--r--examples/qml/referenceexamples/adding/main.py30
-rw-r--r--examples/qml/referenceexamples/adding/person.py35
-rw-r--r--examples/qml/referenceexamples/attached/attached.pyproject3
-rw-r--r--examples/qml/referenceexamples/attached/birthdayparty.py63
-rw-r--r--examples/qml/referenceexamples/attached/doc/attached.rst12
-rw-r--r--examples/qml/referenceexamples/attached/example.qml22
-rw-r--r--examples/qml/referenceexamples/attached/main.py46
-rw-r--r--examples/qml/referenceexamples/attached/person.py46
-rw-r--r--examples/qml/referenceexamples/binding/binding.pyproject3
-rw-r--r--examples/qml/referenceexamples/binding/birthdayparty.py83
-rw-r--r--examples/qml/referenceexamples/binding/doc/binding.rst17
-rw-r--r--examples/qml/referenceexamples/binding/example.qml29
-rw-r--r--examples/qml/referenceexamples/binding/happybirthdaysong.py47
-rw-r--r--examples/qml/referenceexamples/binding/main.py52
-rw-r--r--examples/qml/referenceexamples/binding/person.py53
-rw-r--r--examples/qml/referenceexamples/coercion/birthdayparty.py41
-rw-r--r--examples/qml/referenceexamples/coercion/coercion.pyproject3
-rw-r--r--examples/qml/referenceexamples/coercion/doc/coercion.rst35
-rw-r--r--examples/qml/referenceexamples/coercion/example.qml16
-rw-r--r--examples/qml/referenceexamples/coercion/main.py36
-rw-r--r--examples/qml/referenceexamples/coercion/person.py47
-rw-r--r--examples/qml/referenceexamples/default/birthdayparty.py42
-rw-r--r--examples/qml/referenceexamples/default/default.pyproject3
-rw-r--r--examples/qml/referenceexamples/default/doc/default.rst30
-rw-r--r--examples/qml/referenceexamples/default/example.qml15
-rw-r--r--examples/qml/referenceexamples/default/main.py36
-rw-r--r--examples/qml/referenceexamples/default/person.py46
-rw-r--r--examples/qml/referenceexamples/extended/doc/extended.rst41
-rw-r--r--examples/qml/referenceexamples/extended/example.qml8
-rw-r--r--examples/qml/referenceexamples/extended/extended.pyproject3
-rw-r--r--examples/qml/referenceexamples/extended/main.py95
-rw-r--r--examples/qml/referenceexamples/grouped/birthdayparty.py42
-rw-r--r--examples/qml/referenceexamples/grouped/doc/grouped.rst17
-rw-r--r--examples/qml/referenceexamples/grouped/example.qml33
-rw-r--r--examples/qml/referenceexamples/grouped/grouped.pyproject3
-rw-r--r--examples/qml/referenceexamples/grouped/main.py43
-rw-r--r--examples/qml/referenceexamples/grouped/person.py85
-rw-r--r--examples/qml/referenceexamples/methods/birthdayparty.py47
-rw-r--r--examples/qml/referenceexamples/methods/doc/methods.rst15
-rw-r--r--examples/qml/referenceexamples/methods/example.qml19
-rw-r--r--examples/qml/referenceexamples/methods/main.py32
-rw-r--r--examples/qml/referenceexamples/methods/methods.pyproject3
-rw-r--r--examples/qml/referenceexamples/methods/person.py34
-rw-r--r--examples/qml/referenceexamples/properties/birthdayparty.py41
-rw-r--r--examples/qml/referenceexamples/properties/doc/properties.rst89
-rw-r--r--examples/qml/referenceexamples/properties/example.qml16
-rw-r--r--examples/qml/referenceexamples/properties/main.py34
-rw-r--r--examples/qml/referenceexamples/properties/person.py35
-rw-r--r--examples/qml/referenceexamples/properties/properties.pyproject6
-rw-r--r--examples/qml/referenceexamples/valuesource/birthdayparty.py76
-rw-r--r--examples/qml/referenceexamples/valuesource/doc/valuesource.rst20
-rw-r--r--examples/qml/referenceexamples/valuesource/example.qml27
-rw-r--r--examples/qml/referenceexamples/valuesource/happybirthdaysong.py47
-rw-r--r--examples/qml/referenceexamples/valuesource/main.py51
-rw-r--r--examples/qml/referenceexamples/valuesource/person.py46
-rw-r--r--examples/qml/referenceexamples/valuesource/valuesource.pyproject3
-rw-r--r--examples/qml/signals/pytoqml1/main.py31
-rw-r--r--examples/qml/signals/pytoqml1/pytoqml1.pyproject3
-rw-r--r--examples/qml/signals/pytoqml1/view.qml36
-rw-r--r--examples/qml/signals/pytoqml2/main.py54
-rw-r--r--examples/qml/signals/pytoqml2/pytoqml2.pyproject3
-rw-r--r--examples/qml/signals/pytoqml2/view.qml30
-rw-r--r--examples/qml/signals/qmltopy1/main.py50
-rw-r--r--examples/qml/signals/qmltopy1/qmltopy1.pyproject3
-rw-r--r--examples/qml/signals/qmltopy1/view.qml54
-rw-r--r--examples/qml/signals/qmltopy2/main.py45
-rw-r--r--examples/qml/signals/qmltopy2/qmltopy2.pyproject3
-rw-r--r--examples/qml/signals/qmltopy2/view.qml49
-rw-r--r--examples/qml/signals/qmltopy3/main.py33
-rw-r--r--examples/qml/signals/qmltopy3/qmltopy3.pyproject3
-rw-r--r--examples/qml/signals/qmltopy3/view.qml66
-rw-r--r--examples/qml/signals/qmltopy4/main.py33
-rw-r--r--examples/qml/signals/qmltopy4/qmltopy4.pyproject3
-rw-r--r--examples/qml/signals/qmltopy4/view.qml31
-rw-r--r--examples/qml/textproperties/doc/textproperties.pngbin0 -> 14082 bytes
-rw-r--r--examples/qml/textproperties/doc/textproperties.rst9
-rw-r--r--examples/qml/textproperties/main.py76
-rw-r--r--examples/qml/textproperties/textproperties.pyproject3
-rw-r--r--examples/qml/textproperties/view.qml160
-rw-r--r--examples/qml/tutorials/extending/chapter1-basics/app.qml27
-rw-r--r--examples/qml/tutorials/extending/chapter1-basics/basics.py68
-rw-r--r--examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter2-methods/app.qml33
-rw-r--r--examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter2-methods/methods.py75
-rw-r--r--examples/qml/tutorials/extending/chapter3-bindings/app.qml41
-rw-r--r--examples/qml/tutorials/extending/chapter3-bindings/bindings.py79
-rw-r--r--examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml23
-rw-r--r--examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter4-customPropertyTypes/customPropertyTypes.py82
-rw-r--r--examples/qml/tutorials/extending/chapter5-listproperties/app.qml33
-rw-r--r--examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter5-listproperties/listproperties.py96
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/Charts/piechart.py40
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/Charts/pieslice.py52
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/Charts/plugins.pngbin0 -> 5014 bytes
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/app.qml32
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pyproject3
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/doc/chapter6-plugins.rst21
-rw-r--r--examples/qml/tutorials/extending/chapter6-plugins/doc/plugins.pngbin0 -> 5014 bytes
-rw-r--r--examples/qml/usingmodel/doc/usingmodel.pngbin0 -> 2791 bytes
-rw-r--r--examples/qml/usingmodel/doc/usingmodel.rst9
-rw-r--r--examples/qml/usingmodel/usingmodel.py70
-rw-r--r--examples/qml/usingmodel/usingmodel.pyproject3
-rw-r--r--examples/qml/usingmodel/view.qml29
116 files changed, 3971 insertions, 0 deletions
diff --git a/examples/qml/editingmodel/MovingRectangle.qml b/examples/qml/editingmodel/MovingRectangle.qml
new file mode 100644
index 000000000..b99a5f4dc
--- /dev/null
+++ b/examples/qml/editingmodel/MovingRectangle.qml
@@ -0,0 +1,78 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+
+import QtQuick
+import QtQuick.Controls
+
+Rectangle {
+ id: root
+ property int modelIndex
+ property Item dragParent
+ property Item sizeParent
+ property alias text: zone.text
+ property alias bgColor: root.color
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ color: backgroundColor
+ anchors.fill: sizeParent
+ border.color: "yellow"
+ border.width: 0
+ TextArea {
+ id: zone
+ anchors.centerIn: parent
+ text: display
+ onTextChanged: model.edit = text
+ }
+
+ MouseArea {
+ id: zoneMouseArea
+ anchors.fill: parent
+
+ acceptedButtons: Qt.MiddleButton
+ onClicked: function(mouse) {
+ if (mouse.button == Qt.MiddleButton)
+ lv.model.remove(index)
+ else
+ mouse.accepted = false
+ }
+ }
+ DragHandler {
+ id: dragHandler
+ xAxis {
+
+ enabled: true
+ minimum: 0
+ maximum: lv.width - droparea.width
+ }
+ yAxis.enabled: false
+ acceptedButtons: Qt.LeftButton
+ }
+ Drag.active: dragHandler.active
+ Drag.source: root
+ Drag.hotSpot.x: width / 2
+
+ states: [
+ State {
+ when: dragHandler.active
+ ParentChange {
+ target: root
+ parent: root.dragParent
+ }
+
+ AnchorChanges {
+ target: root
+ anchors.horizontalCenter: undefined
+ anchors.verticalCenter: undefined
+ }
+ PropertyChanges {
+ target: root
+ opacity: 0.6
+ border.width: 3
+ }
+ }
+ ]
+}
diff --git a/examples/qml/editingmodel/doc/editingmodel.rst b/examples/qml/editingmodel/doc/editingmodel.rst
new file mode 100644
index 000000000..d76bebc22
--- /dev/null
+++ b/examples/qml/editingmodel/doc/editingmodel.rst
@@ -0,0 +1,14 @@
+QAbstractListModel in QML
+=========================
+
+This example shows how to add, remove and move items inside a QML
+ListView, but showing and editing the data via roles using a
+QAbstractListModel from Python.
+
+You can add new elements and reset the view using the two top buttons,
+remove elements by 'middle click' the element, and move the elements
+with a 'left click' plus dragging the item around.
+
+.. image:: qabstractlistmodelqml.png
+ :width: 400
+ :alt: QAbstractListModel/ListView Screenshot
diff --git a/examples/qml/editingmodel/doc/qabstractlistmodelqml.png b/examples/qml/editingmodel/doc/qabstractlistmodelqml.png
new file mode 100644
index 000000000..6e181fba1
--- /dev/null
+++ b/examples/qml/editingmodel/doc/qabstractlistmodelqml.png
Binary files differ
diff --git a/examples/qml/editingmodel/main.py b/examples/qml/editingmodel/main.py
new file mode 100644
index 000000000..00b3ae2b1
--- /dev/null
+++ b/examples/qml/editingmodel/main.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+from pathlib import Path
+
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlApplicationEngine
+
+from model import BaseModel
+
+if __name__ == "__main__":
+ app = QGuiApplication(sys.argv)
+ engine = QQmlApplicationEngine()
+ qml_file = Path(__file__).parent / "main.qml"
+ engine.load(QUrl.fromLocalFile(qml_file))
+
+ if not engine.rootObjects():
+ sys.exit(-1)
+ sys.exit(app.exec())
diff --git a/examples/qml/editingmodel/main.pyproject b/examples/qml/editingmodel/main.pyproject
new file mode 100644
index 000000000..71272a973
--- /dev/null
+++ b/examples/qml/editingmodel/main.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["model.py","main.qml","main.py","MovingRectangle.qml"]
+}
diff --git a/examples/qml/editingmodel/main.qml b/examples/qml/editingmodel/main.qml
new file mode 100644
index 000000000..2318ae8b3
--- /dev/null
+++ b/examples/qml/editingmodel/main.qml
@@ -0,0 +1,106 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Window
+import BaseModel
+
+Window {
+ title: "Moving Rectangle"
+ width: 800
+ height: 480
+ visible: true
+ id: mainWindow
+
+ Column {
+ spacing: 20
+ anchors.fill: parent
+ id: mainColumn
+ Text {
+ padding: 20
+ font.pointSize: 10
+ width: 600
+ wrapMode: Text.Wrap
+ text: "This example shows how to add, remove and move items inside a QML ListView.\n
+It shows and edits data via roles using QAbstractListModel on the Python side.\n
+Use the 'Middle click' on top of a rectangle to remove an item.\n
+'Left click' and drag to move the items."
+ }
+
+ Button {
+ anchors {
+ left: mainColumn.left
+ right: mainColumn.right
+ margins: 30
+ }
+ text: "Reset view"
+ onClicked: lv.model.reset()
+ }
+
+ Button {
+ anchors {
+ left: mainColumn.left
+ right: mainColumn.right
+ margins: 30
+ }
+ text: "Add element"
+ onClicked: lv.model.append()
+ }
+
+ ListView {
+ id: lv
+ anchors {
+ left: mainColumn.left
+ right: mainColumn.right
+ margins: 30
+ }
+
+ height: 200
+ model: BaseModel {}
+ orientation: ListView.Horizontal
+ displaced: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ easing.type: Easing.OutQuad
+ }
+ }
+ delegate: DropArea {
+ id: droparea
+ width: ratio * lv.width
+ height: lv.height
+
+ onEntered: function (drag) {
+ let dragindex = drag.source.modelIndex
+ if (index === dragindex)
+ return
+ lv.model.move(dragindex, index)
+ }
+
+ MovingRectangle {
+ modelIndex: index
+ dragParent: lv
+ sizeParent: droparea
+ }
+ }
+
+ MouseArea {
+ id: lvMousearea
+ anchors.fill: lv
+ z: -1
+ }
+ Rectangle {
+ id: lvBackground
+ anchors.fill: lv
+ anchors.margins: -border.width
+ color: "white"
+ border.color: "black"
+ border.width: 5
+ z: -1
+ }
+ Component.onCompleted: {
+ lv.model.reset()
+ }
+ }
+ }
+}
diff --git a/examples/qml/editingmodel/model.py b/examples/qml/editingmodel/model.py
new file mode 100644
index 000000000..591497872
--- /dev/null
+++ b/examples/qml/editingmodel/model.py
@@ -0,0 +1,157 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+
+from PySide6.QtCore import (QAbstractListModel, QByteArray, QModelIndex, Qt,
+ Slot)
+from PySide6.QtGui import QColor
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "BaseModel"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class BaseModel(QAbstractListModel):
+
+ RatioRole = Qt.UserRole + 1
+
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.db = []
+
+ def rowCount(self, parent=QModelIndex()):
+ return len(self.db)
+
+ def roleNames(self):
+ default = super().roleNames()
+ default[self.RatioRole] = QByteArray(b"ratio")
+ default[Qt.BackgroundRole] = QByteArray(b"backgroundColor")
+ return default
+
+ def data(self, index, role: int):
+ if not self.db:
+ ret = None
+ elif not index.isValid():
+ ret = None
+ elif role == Qt.DisplayRole:
+ ret = self.db[index.row()]["text"]
+ elif role == Qt.BackgroundRole:
+ ret = self.db[index.row()]["bgColor"]
+ elif role == self.RatioRole:
+ ret = self.db[index.row()]["ratio"]
+ else:
+ ret = None
+ return ret
+
+ def setData(self, index, value, role):
+ if not index.isValid():
+ return False
+ if role == Qt.EditRole:
+ self.db[index.row()]["text"] = value
+ return True
+
+ @Slot(result=bool)
+ def append(self):
+ """Slot to append a row at the end"""
+ return self.insertRow(self.rowCount())
+
+ def insertRow(self, row):
+ """Insert a single row at row"""
+ return self.insertRows(row, 0)
+
+ def insertRows(self, row: int, count, index=QModelIndex()):
+ """Insert n rows (n = 1 + count) at row"""
+
+ self.beginInsertRows(QModelIndex(), row, row + count)
+
+ # start database work
+ if len(self.db):
+ newid = max(x["id"] for x in self.db) + 1
+ else:
+ newid = 1
+ for i in range(count + 1): # at least one row
+ self.db.insert(
+ row, {"id": newid, "text": "new", "bgColor": QColor("purple"), "ratio": 0.2}
+ )
+ # end database work
+ self.endInsertRows()
+ return True
+
+ @Slot(int, int, result=bool)
+ def move(self, source: int, target: int):
+ """Slot to move a single row from source to target"""
+ return self.moveRow(QModelIndex(), source, QModelIndex(), target)
+
+ def moveRow(self, sourceParent, sourceRow, dstParent, dstChild):
+ """Move a single row"""
+ return self.moveRows(sourceParent, sourceRow, 0, dstParent, dstChild)
+
+ def moveRows(self, sourceParent, sourceRow, count, dstParent, dstChild):
+ """Move n rows (n=1+ count) from sourceRow to dstChild"""
+
+ if sourceRow == dstChild:
+ return False
+
+ elif sourceRow > dstChild:
+ end = dstChild
+
+ else:
+ end = dstChild + 1
+
+ self.beginMoveRows(QModelIndex(), sourceRow, sourceRow + count, QModelIndex(), end)
+
+ # start database work
+ pops = self.db[sourceRow : sourceRow + count + 1]
+ if sourceRow > dstChild:
+ self.db = (
+ self.db[:dstChild]
+ + pops
+ + self.db[dstChild:sourceRow]
+ + self.db[sourceRow + count + 1 :]
+ )
+ else:
+ start = self.db[:sourceRow]
+ middle = self.db[dstChild : dstChild + 1]
+ endlist = self.db[dstChild + count + 1 :]
+ self.db = start + middle + pops + endlist
+ # end database work
+
+ self.endMoveRows()
+ return True
+
+ @Slot(int, result=bool)
+ def remove(self, row: int):
+ """Slot to remove one row"""
+ return self.removeRow(row)
+
+ def removeRow(self, row, parent=QModelIndex()):
+ """Remove one row at index row"""
+ return self.removeRows(row, 0, parent)
+
+ def removeRows(self, row: int, count: int, parent=QModelIndex()):
+ """Remove n rows (n=1+count) starting at row"""
+ self.beginRemoveRows(QModelIndex(), row, row + count)
+
+ # start database work
+ self.db = self.db[:row] + self.db[row + count + 1 :]
+ # end database work
+
+ self.endRemoveRows()
+ return True
+
+ @Slot(result=bool)
+ def reset(self):
+ self.beginResetModel()
+ self.resetInternalData() # should work without calling it ?
+ self.endResetModel()
+ return True
+
+ def resetInternalData(self):
+ self.db = [
+ {"id": 3, "bgColor": QColor("red"), "ratio": 0.15, "text": "first"},
+ {"id": 1, "bgColor": QColor("blue"), "ratio": 0.1, "text": "second"},
+ {"id": 2, "bgColor": QColor("green"), "ratio": 0.2, "text": "third"},
+ ]
diff --git a/examples/qml/referenceexamples/adding/adding.pyproject b/examples/qml/referenceexamples/adding/adding.pyproject
new file mode 100644
index 000000000..46df4b253
--- /dev/null
+++ b/examples/qml/referenceexamples/adding/adding.pyproject
@@ -0,0 +1,5 @@
+{
+ "files": ["example.qml",
+ "main.py",
+ "person.py"]
+}
diff --git a/examples/qml/referenceexamples/adding/doc/adding.rst b/examples/qml/referenceexamples/adding/doc/adding.rst
new file mode 100644
index 000000000..55f6105b7
--- /dev/null
+++ b/examples/qml/referenceexamples/adding/doc/adding.rst
@@ -0,0 +1,67 @@
+.. _qml-adding-types-example:
+
+Extending QML - Adding Types Example
+====================================
+
+The Adding Types Example shows how to add a new object type, ``Person``, to QML.
+The ``Person`` type can be used from QML like this:
+
+.. code-block:: javascript
+
+ import examples.adding.people
+
+ Person {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+
+Declare the Person Class
+------------------------
+
+All QML types map to C++ types. Here we declare a basic C++ Person class
+with the two properties we want accessible on the QML type - name and shoeSize.
+Although in this example we use the same name for the C++ class as the QML
+type, the C++ class can be named differently, or appear in a namespace.
+
+The Person class implementation is quite basic. The property accessors simply
+return members of the object instance.
+
+.. code-block:: python
+
+ from PySide6.QtCore import QObject, Property
+ from PySide6.QtQml import QmlElement
+
+ # To be used on the @QmlElement decorator
+ # (QML_IMPORT_MINOR_VERSION is optional)
+ QML_IMPORT_NAME = "examples.adding.people"
+ QML_IMPORT_MAJOR_VERSION = 1
+
+
+ @QmlElement
+ class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
+Running the Example
+-------------------
+
+The main.py file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
diff --git a/examples/qml/referenceexamples/adding/example.qml b/examples/qml/referenceexamples/adding/example.qml
new file mode 100644
index 000000000..42d47dea9
--- /dev/null
+++ b/examples/qml/referenceexamples/adding/example.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.adding.people
+
+Person {
+ name: "Bob Jones"
+ shoe_size: 12
+}
diff --git a/examples/qml/referenceexamples/adding/main.py b/examples/qml/referenceexamples/adding/main.py
new file mode 100644
index 000000000..f10b77bc1
--- /dev/null
+++ b/examples/qml/referenceexamples/adding/main.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/adding example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Person
+
+
+if __name__ == '__main__':
+ app = QCoreApplication(sys.argv)
+
+ qml_file = Path(__file__).parent / "example.qml"
+ url = QUrl.fromLocalFile(qml_file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+
+ person = component.create()
+ if person:
+ print(f"The person's name is {person.name}")
+ print(f"They wear a {person.shoe_size} sized shoe")
+ else:
+ print(component.errors())
+ del engine
+ sys.exit(0)
diff --git a/examples/qml/referenceexamples/adding/person.py b/examples/qml/referenceexamples/adding/person.py
new file mode 100644
index 000000000..0c2b5b124
--- /dev/null
+++ b/examples/qml/referenceexamples/adding/person.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.adding.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
diff --git a/examples/qml/referenceexamples/attached/attached.pyproject b/examples/qml/referenceexamples/attached/attached.pyproject
new file mode 100644
index 000000000..3c01c40c2
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/attached.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/attached/birthdayparty.py b/examples/qml/referenceexamples/attached/birthdayparty.py
new file mode 100644
index 000000000..d83236e26
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/birthdayparty.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QDate, QObject, ClassInfo, Property
+from PySide6.QtQml import QmlAnonymous, QmlAttached, QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.default.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class BirthdayPartyAttached(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._rsvp = QDate()
+
+ @Property(QDate)
+ def rsvp(self):
+ return self._rsvp
+
+ @rsvp.setter
+ def rsvp(self, d):
+ self._rsvp = d
+
+
+@QmlElement
+@ClassInfo(DefaultProperty="guests")
+@QmlAttached(BirthdayPartyAttached)
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ @staticmethod
+ def qmlAttachedProperties(self, o):
+ return BirthdayPartyAttached(o)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/attached/doc/attached.rst b/examples/qml/referenceexamples/attached/doc/attached.rst
new file mode 100644
index 000000000..95fb5c43c
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/doc/attached.rst
@@ -0,0 +1,12 @@
+.. _qml-attached-properties-example:
+
+Extending QML - Attached Properties Example
+===========================================
+
+This example builds on the :ref:`qml-default-property-example`,
+:ref:`qml-inheritance-and-coercion-example`,
+:ref:`qml-object-and-list-property-types-example`
+and the :ref:`qml-adding-types-example`.
+
+The Attached Properties Example example shows how to inject
+properties to child objects.
diff --git a/examples/qml/referenceexamples/attached/example.qml b/examples/qml/referenceexamples/attached/example.qml
new file mode 100644
index 000000000..f038b3ece
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/example.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.default.people
+
+BirthdayParty {
+ Boy {
+ name: "Robert Campbell"
+ BirthdayParty.rsvp: "2009-07-01"
+ }
+
+ Boy {
+ name: "Leo Hodges"
+ shoe_size: 10
+ BirthdayParty.rsvp: "2009-07-06"
+ }
+
+ host: Boy {
+ name: "Jack Smith"
+ shoe_size: 8
+ }
+}
diff --git a/examples/qml/referenceexamples/attached/main.py b/examples/qml/referenceexamples/attached/main.py
new file mode 100644
index 000000000..d7483559f
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/main.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/attached example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine, qmlAttachedPropertiesObject
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+
+
+app = QCoreApplication(sys.argv)
+qml_file = Path(__file__).parent / "example.qml"
+url = QUrl.fromLocalFile(qml_file)
+engine = QQmlEngine()
+component = QQmlComponent(engine, url)
+party = component.create()
+if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+host = party.host
+print(f"{host.name} is having a birthday!")
+if isinstance(host, Boy):
+ print("He is inviting:")
+else:
+ print("She is inviting:")
+for g in range(party.guestCount()):
+ guest = party.guest(g)
+ name = guest.name
+
+ rsvp_date = None
+ attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False)
+ if attached:
+ rsvp_date = attached.rsvp.toString()
+ if rsvp_date:
+ print(f" {name} RSVP date: {rsvp_date}")
+ else:
+ print(f" {name} RSVP date: Hasn't RSVP'd")
+
+del engine
+sys.exit(0)
diff --git a/examples/qml/referenceexamples/attached/person.py b/examples/qml/referenceexamples/attached/person.py
new file mode 100644
index 000000000..7164bd645
--- /dev/null
+++ b/examples/qml/referenceexamples/attached/person.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlAnonymous, QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.default.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/binding/binding.pyproject b/examples/qml/referenceexamples/binding/binding.pyproject
new file mode 100644
index 000000000..a782d5c8a
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/binding.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "happybirthdaysong.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/binding/birthdayparty.py b/examples/qml/referenceexamples/binding/birthdayparty.py
new file mode 100644
index 000000000..78f0314b4
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/birthdayparty.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QDate, QObject, ClassInfo, Property, QTime, Signal
+from PySide6.QtQml import QmlAnonymous, QmlAttached, QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.binding.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class BirthdayPartyAttached(QObject):
+
+ rsvp_changed = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._rsvp = QDate()
+
+ @Property(QDate, notify=rsvp_changed)
+ def rsvp(self):
+ return self._rsvp
+
+ @rsvp.setter
+ def rsvp(self, d):
+ if self._rsvp != d:
+ self._rsvp = d
+ self.rsvp_changed.emit()
+
+
+@QmlElement
+@ClassInfo(DefaultProperty="guests")
+@QmlAttached(BirthdayPartyAttached)
+class BirthdayParty(QObject):
+
+ partyStarted = Signal(QTime)
+ host_changed = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ def startParty(self):
+ self.partyStarted.emit(QTime.currentTime())
+
+ @Property(Person, notify=host_changed)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ if self._host != h:
+ self._host = h
+ self.host_changed.emit()
+
+ @Property(str)
+ def announcement(self):
+ return ""
+
+ @announcement.setter
+ def announcement(self, a):
+ print(a)
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ @staticmethod
+ def qmlAttachedProperties(self, o):
+ return BirthdayPartyAttached(o)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/binding/doc/binding.rst b/examples/qml/referenceexamples/binding/doc/binding.rst
new file mode 100644
index 000000000..5c0ed21be
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/doc/binding.rst
@@ -0,0 +1,17 @@
+.. _qml-binding-example:
+
+Extending QML - Binding Example
+===============================
+
+This example builds on the :ref:`qml-adding-types-example`,
+the :ref:`qml-attached-properties-example`,
+the :ref:`qml-default-property-example`,
+the :ref:`qml-inheritance-and-coercion-example`
+the :ref:`qml-object-and-list-property-types-example`
+and the :ref:`qml-valuesource-example`.
+
+Running the Example
+-------------------
+
+The ``main.py`` file in the example includes a simple shell application that
+loads and runs the QML snippet shown below.
diff --git a/examples/qml/referenceexamples/binding/example.qml b/examples/qml/referenceexamples/binding/example.qml
new file mode 100644
index 000000000..ca0958810
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/example.qml
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.binding.people
+
+BirthdayParty {
+ id: theParty
+
+ HappyBirthdaySong on announcement { name: theParty.host.name }
+
+ onPartyStarted: (time) => { console.log("This party started rockin' at " + time); }
+
+ host: Boy {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+
+ Boy {
+ name: "Leo Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ }
+ Boy {
+ name: "Jack Smith"
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ }
+}
diff --git a/examples/qml/referenceexamples/binding/happybirthdaysong.py b/examples/qml/referenceexamples/binding/happybirthdaysong.py
new file mode 100644
index 000000000..cfe34eb82
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/happybirthdaysong.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, QTimer, Property, Slot
+from PySide6.QtQml import QmlElement, QPyQmlPropertyValueSource
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.binding.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class HappyBirthdaySong(QPyQmlPropertyValueSource):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.m_target = None
+ self.m_name = ""
+ self.m_line = -1
+ self.m_lyrics = []
+
+ self.m_timer = QTimer(self)
+ self.m_timer.timeout.connect(self.advance)
+ self.m_timer.start(1000)
+
+ def setTarget(self, property):
+ self.m_target = property
+
+ @Property(str)
+ def name(self):
+ return self.m_name
+
+ @name.setter
+ def name(self, n):
+ self.m_name = n
+ self.m_lyrics = ["Happy birthday to you,",
+ "Happy birthday to you,",
+ f"Happy birthday dear {self.m_name},",
+ "Happy birthday to you!",
+ ""]
+
+ @Slot()
+ def advance(self):
+ self.m_line = (self.m_line + 1) % len(self.m_lyrics)
+ self.m_target.write(self.m_lyrics[self.m_line])
diff --git a/examples/qml/referenceexamples/binding/main.py b/examples/qml/referenceexamples/binding/main.py
new file mode 100644
index 000000000..dcbd547ad
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/main.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/binding example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine, qmlAttachedPropertiesObject
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+from happybirthdaysong import HappyBirthdaySong
+
+
+if __name__ == "__main__":
+ app = QCoreApplication(sys.argv)
+ qml_file = Path(__file__).parent / "example.qml"
+ url = QUrl.fromLocalFile(qml_file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ party = component.create()
+ if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+ host = party.host
+ print(f"{host.name} is having a birthday!")
+ if isinstance(host, Boy):
+ print("He is inviting:")
+ else:
+ print("She is inviting:")
+ for g in range(party.guestCount()):
+ guest = party.guest(g)
+ name = guest.name
+
+ rsvp_date = None
+ attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False)
+ if attached:
+ rsvp_date = attached.rsvp.toString()
+ if rsvp_date:
+ print(f" {name} RSVP date: {rsvp_date}")
+ else:
+ print(f" {name} RSVP date: Hasn't RSVP'd")
+
+ party.startParty()
+
+ r = app.exec()
+
+ del engine
+ sys.exit(r)
diff --git a/examples/qml/referenceexamples/binding/person.py b/examples/qml/referenceexamples/binding/person.py
new file mode 100644
index 000000000..9e7d799e1
--- /dev/null
+++ b/examples/qml/referenceexamples/binding/person.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property, Signal
+from PySide6.QtQml import QmlAnonymous, QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.binding.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class Person(QObject):
+ name_changed = Signal()
+ shoe_size_changed = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str, notify=name_changed)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ if self._name != n:
+ self._name = n
+ self.name_changed.emit()
+
+ @Property(int, notify=shoe_size_changed)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ if self._shoe_size != s:
+ self._shoe_size = s
+ self.shoe_size_changed.emit()
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/coercion/birthdayparty.py b/examples/qml/referenceexamples/coercion/birthdayparty.py
new file mode 100644
index 000000000..f6ad1ac35
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/birthdayparty.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.coercion.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/coercion/coercion.pyproject b/examples/qml/referenceexamples/coercion/coercion.pyproject
new file mode 100644
index 000000000..3c01c40c2
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/coercion.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/coercion/doc/coercion.rst b/examples/qml/referenceexamples/coercion/doc/coercion.rst
new file mode 100644
index 000000000..2ccdaeb4f
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/doc/coercion.rst
@@ -0,0 +1,35 @@
+.. _qml-inheritance-and-coercion-example:
+
+Extending QML - Inheritance and Coercion Example
+================================================
+
+This example builds on the :ref:`qml-adding-types-example` and the
+:ref:`qml-object-and-list-property-types-example` .
+
+The Inheritance and Coercion Example shows how to use base classes to assign
+types of more than one type to a property. It specializes the Person type
+developed in the previous examples into two types - a ``Boy`` and a ``Girl``.
+
+Declare Boy and Girl
+--------------------
+
+The Person class remains unaltered in this example and the Boy and Girl C++
+classes are trivial extensions of it. The types and their QML name are
+registered with the QML engine.
+
+As an example, the inheritance used here is a little contrived, but in real
+applications it is likely that the two extensions would add additional
+properties or modify the Person classes behavior.
+
+Running the Example
+-------------------
+
+The BirthdayParty type has not changed since the previous example. The
+celebrant and guests property still use the People type.
+
+However, as all three types, Person, Boy and Girl, have been registered with the
+QML system, on assignment QML automatically (and type-safely) converts the Boy
+and Girl objects into a Person.
+
+The main.py file in the example includes a simple shell application that
+loads and runs the QML snippet shown below.
diff --git a/examples/qml/referenceexamples/coercion/example.qml b/examples/qml/referenceexamples/coercion/example.qml
new file mode 100644
index 000000000..c47678483
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/example.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.coercion.people
+
+BirthdayParty {
+ host: Boy {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+ guests: [
+ Boy { name: "Leo Hodges" },
+ Boy { name: "Jack Smith" },
+ Girl { name: "Anne Brown" }
+ ]
+}
diff --git a/examples/qml/referenceexamples/coercion/main.py b/examples/qml/referenceexamples/coercion/main.py
new file mode 100644
index 000000000..9f49bc1da
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/main.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/coercion example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+
+
+app = QCoreApplication(sys.argv)
+qml_file = Path(__file__).parent / "example.qml"
+url = QUrl.fromLocalFile(qml_file)
+engine = QQmlEngine()
+component = QQmlComponent(engine, url)
+party = component.create()
+if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+host = party.host
+print(f"{host.name} is having a birthday!")
+if isinstance(host, Boy):
+ print("He is inviting:")
+else:
+ print("She is inviting:")
+for g in range(party.guestCount()):
+ name = party.guest(g).name
+ print(f" {name}")
+del engine
+sys.exit(0)
diff --git a/examples/qml/referenceexamples/coercion/person.py b/examples/qml/referenceexamples/coercion/person.py
new file mode 100644
index 000000000..69056014c
--- /dev/null
+++ b/examples/qml/referenceexamples/coercion/person.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement, QmlUncreatable
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.coercion.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlUncreatable("Person is an abstract base class.")
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/default/birthdayparty.py b/examples/qml/referenceexamples/default/birthdayparty.py
new file mode 100644
index 000000000..3c13ca6cf
--- /dev/null
+++ b/examples/qml/referenceexamples/default/birthdayparty.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, ClassInfo, Property
+from PySide6.QtQml import QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.default.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@ClassInfo(DefaultProperty="guests")
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/default/default.pyproject b/examples/qml/referenceexamples/default/default.pyproject
new file mode 100644
index 000000000..3c01c40c2
--- /dev/null
+++ b/examples/qml/referenceexamples/default/default.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/default/doc/default.rst b/examples/qml/referenceexamples/default/doc/default.rst
new file mode 100644
index 000000000..1b28519a7
--- /dev/null
+++ b/examples/qml/referenceexamples/default/doc/default.rst
@@ -0,0 +1,30 @@
+.. _qml-default-property-example:
+
+Extending QML - Default Property Example
+========================================
+
+This example builds on the :ref:`qml-adding-types-example`,
+the :ref:`qml-object-and-list-property-types-example` and
+the :ref:`qml-inheritance-and-coercion-example`.
+
+The Default Property Example is a minor modification of the
+:ref:`qml-inheritance-and-coercion-example` that simplifies the
+specification of a BirthdayParty through the use of a default property.
+
+Declaring the BirthdayParty Class
+---------------------------------
+
+The only difference between this example and the last, is the addition of a
+``DefaultProperty`` class info annotation.
+
+The default property specifies the property to assign to whenever an explicit
+property is not specified, in the case of the BirthdayParty type the guest
+property. It is purely a syntactic simplification, the behavior is identical
+to specifying the property by name, but it can add a more natural feel in many
+situations. The default property must be either an object or list property.
+
+Running the Example
+-------------------
+
+The main.py file in the example includes a simple shell application that
+loads and runs the QML snippet shown below.
diff --git a/examples/qml/referenceexamples/default/example.qml b/examples/qml/referenceexamples/default/example.qml
new file mode 100644
index 000000000..435be7860
--- /dev/null
+++ b/examples/qml/referenceexamples/default/example.qml
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.default.people
+
+BirthdayParty {
+ host: Boy {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+
+ Boy { name: "Leo Hodges" }
+ Boy { name: "Jack Smith" }
+ Girl { name: "Anne Brown" }
+}
diff --git a/examples/qml/referenceexamples/default/main.py b/examples/qml/referenceexamples/default/main.py
new file mode 100644
index 000000000..a4ce2f08a
--- /dev/null
+++ b/examples/qml/referenceexamples/default/main.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/default example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+
+
+app = QCoreApplication(sys.argv)
+qml_file = Path(__file__).parent / "example.qml"
+url = QUrl.fromLocalFile(qml_file)
+engine = QQmlEngine()
+component = QQmlComponent(engine, url)
+party = component.create()
+if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+host = party.host
+print(f"{host.name} is having a birthday!")
+if isinstance(host, Boy):
+ print("He is inviting:")
+else:
+ print("She is inviting:")
+for g in range(party.guestCount()):
+ name = party.guest(g).name
+ print(f" {name}")
+del engine
+sys.exit(0)
diff --git a/examples/qml/referenceexamples/default/person.py b/examples/qml/referenceexamples/default/person.py
new file mode 100644
index 000000000..7164bd645
--- /dev/null
+++ b/examples/qml/referenceexamples/default/person.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlAnonymous, QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.default.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/extended/doc/extended.rst b/examples/qml/referenceexamples/extended/doc/extended.rst
new file mode 100644
index 000000000..745960535
--- /dev/null
+++ b/examples/qml/referenceexamples/extended/doc/extended.rst
@@ -0,0 +1,41 @@
+.. _qml-extension-objects-example:
+
+Extending QML - Extension Objects Example
+=========================================
+
+This example builds on the the :ref:`qml-adding-types-example`.
+
+Shows how to use QmlExtended decorator to provide an extension object to a
+QLineEdit without modifying or subclassing it.
+
+Firstly, the LineEditExtension class is registered with the QML system as an
+extension of QLineEdit. We declare a foreign type to do this as we cannot
+modify Qt's internal QLineEdit class.
+
+.. code-block:: python
+
+ @QmlNamedElement("QLineEdit")
+ @QmlExtended(LineEditExtension)
+ @QmlForeign(QLineEdit)
+ class LineEditForeign(QObject):
+
+
+Note the usage of ``QmlNamedElement()`` instead of ``QmlElement()``.
+``QmlElement()`` uses the name of the containing type by default,
+``LineEditExtension`` in this case. As the class being an extension class is
+an implementation detail, we choose the more natural name ``QLineEdit``
+instead.
+
+The QML engine then instantiates a QLineEdit.
+
+In QML, a property is set on the line edit that only exists in the
+``LineEditExtension`` class:
+
+.. code-block:: javascript
+
+ QLineEdit {
+ left_margin: 20
+ }
+
+The extension type performs calls on the ``QLineEdit`` that otherwise will not
+be accessible to the QML engine.
diff --git a/examples/qml/referenceexamples/extended/example.qml b/examples/qml/referenceexamples/extended/example.qml
new file mode 100644
index 000000000..e4af3bec5
--- /dev/null
+++ b/examples/qml/referenceexamples/extended/example.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.extend 1.0
+
+QLineEdit {
+ left_margin: 20
+}
diff --git a/examples/qml/referenceexamples/extended/extended.pyproject b/examples/qml/referenceexamples/extended/extended.pyproject
new file mode 100644
index 000000000..127a3a76a
--- /dev/null
+++ b/examples/qml/referenceexamples/extended/extended.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/extended/main.py b/examples/qml/referenceexamples/extended/main.py
new file mode 100644
index 000000000..6ee386401
--- /dev/null
+++ b/examples/qml/referenceexamples/extended/main.py
@@ -0,0 +1,95 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/extended example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QObject, QUrl, Property
+from PySide6.QtWidgets import QApplication, QLineEdit
+from PySide6.QtQml import (QQmlComponent, QQmlEngine, QmlForeign, QmlExtended,
+ QmlNamedElement)
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.extend"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+class LineEditExtension(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._line_edit = parent
+
+ @Property(int)
+ def left_margin(self):
+ return self._line_edit.textMargins().left()
+
+ @left_margin.setter
+ def left_margin(self, m):
+ margins = self._line_edit.textMargins()
+ margins.setLeft(m)
+ self._line_edit.setTextMargins(margins)
+
+ @Property(int)
+ def right_margin(self):
+ return self._line_edit.textMargins().right()
+
+ @right_margin.setter
+ def right_margin(self, m):
+ margins = self._line_edit.textMargins()
+ margins.setRight(m)
+ self._line_edit.setTextMargins(margins)
+
+ @Property(int)
+ def top_margin(self):
+ return self._line_edit.textMargins().top()
+
+ @top_margin.setter
+ def top_margin(self, m):
+ margins = self._line_edit.textMargins()
+ margins.setTop(m)
+ self._line_edit.setTextMargins(margins)
+
+ @Property(int)
+ def bottom_margin(self):
+ return self._line_edit.textMargins().bottom()
+
+ @bottom_margin.setter
+ def bottom_margin(self, m):
+ margins = self._line_edit.textMargins()
+ margins.setBottom(m)
+ self._line_edit.setTextMargins(margins)
+
+
+@QmlNamedElement("QLineEdit")
+@QmlExtended(LineEditExtension)
+@QmlForeign(QLineEdit)
+class LineEditForeign(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ qml_file = Path(__file__).parent / "example.qml"
+ url = QUrl.fromLocalFile(qml_file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ widget = component.create()
+ if not widget:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+
+ widget.show()
+ r = app.exec()
+ # Deleting the engine before it goes out of scope is required to make sure
+ # all child QML instances are destroyed in the correct order.
+ del engine
+ sys.exit(r)
diff --git a/examples/qml/referenceexamples/grouped/birthdayparty.py b/examples/qml/referenceexamples/grouped/birthdayparty.py
new file mode 100644
index 000000000..9f414441e
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/birthdayparty.py
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, ClassInfo, Property
+from PySide6.QtQml import QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.grouped.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@ClassInfo(DefaultProperty="guests")
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/grouped/doc/grouped.rst b/examples/qml/referenceexamples/grouped/doc/grouped.rst
new file mode 100644
index 000000000..691c1d393
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/doc/grouped.rst
@@ -0,0 +1,17 @@
+.. _qml-grouped-example:
+
+Extending QML - Grouped Properties Example
+==========================================
+
+Grouped Properties.
+
+This example builds on the the :ref:`qml-default-property-example`,
+the :ref:`qml-inheritance-and-coercion-example`
+the :ref:`qml-object-and-list-property-types-example`
+and the :ref:`qml-adding-types-example`.
+
+Running the Example
+-------------------
+
+The ``main.py`` file in the example includes a simple shell application that
+loads and runs the QML snippet shown below.
diff --git a/examples/qml/referenceexamples/grouped/example.qml b/examples/qml/referenceexamples/grouped/example.qml
new file mode 100644
index 000000000..d0db4f193
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/example.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+import examples.grouped.people
+
+BirthdayParty {
+ host: Boy {
+ name: "Bob Jones"
+ shoe { size: 12; color: "white"; brand: "Bikey"; price: 90.0 }
+ }
+
+ Boy {
+ name: "Leo Hodges"
+ shoe { size: 10; color: "black"; brand: "Thebok"; price: 59.95 }
+ }
+ Boy { name: "Jack Smith"
+ shoe {
+ size: 8
+ color: "blue"
+ brand: "Luma"
+ price: 19.95
+ }
+ }
+ Girl {
+ name: "Anne Brown"
+ shoe.size: 7
+ shoe.color: "red"
+ shoe.brand: "Job Macobs"
+ shoe.price: 699.99
+ }
+}
diff --git a/examples/qml/referenceexamples/grouped/grouped.pyproject b/examples/qml/referenceexamples/grouped/grouped.pyproject
new file mode 100644
index 000000000..3c01c40c2
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/grouped.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/grouped/main.py b/examples/qml/referenceexamples/grouped/main.py
new file mode 100644
index 000000000..f1edb8b94
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/main.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/default example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+
+
+if __name__ == '__main__':
+ app = QCoreApplication(sys.argv)
+ qml_file = Path(__file__).parent / "example.qml"
+ url = QUrl.fromLocalFile(qml_file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+ party = component.create()
+ if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+ host = party.host
+ print(f"{host.name} is having a birthday!")
+ if isinstance(host, Boy):
+ print("He is inviting:")
+ else:
+ print("She is inviting:")
+ best_shoe = None
+ for g in range(party.guestCount()):
+ guest = party.guest(g)
+ name = guest.name
+ print(f" {name}")
+ if not best_shoe or best_shoe.shoe.price < guest.shoe.price:
+ best_shoe = guest;
+ if best_shoe:
+ print(f"{best_shoe.name} is wearing the best shoes!");
+ del engine
+ sys.exit(0)
diff --git a/examples/qml/referenceexamples/grouped/person.py b/examples/qml/referenceexamples/grouped/person.py
new file mode 100644
index 000000000..a1edf077e
--- /dev/null
+++ b/examples/qml/referenceexamples/grouped/person.py
@@ -0,0 +1,85 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtGui import QColor
+from PySide6.QtQml import QmlAnonymous, QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.grouped.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class ShoeDescription(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._brand = ''
+ self._size = 0
+ self._price = 0
+ self._color = QColor()
+
+ @Property(str)
+ def brand(self):
+ return self._brand
+
+ @brand.setter
+ def brand(self, b):
+ self._brand = b
+
+ @Property(int)
+ def size(self):
+ return self._size
+
+ @size.setter
+ def size(self, s):
+ self._size = s
+
+ @Property(float)
+ def price(self):
+ return self._price
+
+ @price.setter
+ def price(self, p):
+ self._price = p
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, c):
+ self._color = c
+
+
+@QmlAnonymous
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe = ShoeDescription()
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(ShoeDescription)
+ def shoe(self):
+ return self._shoe
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/methods/birthdayparty.py b/examples/qml/referenceexamples/methods/birthdayparty.py
new file mode 100644
index 000000000..41425a2b1
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/birthdayparty.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property, Slot
+from PySide6.QtQml import QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.methods.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ @Slot(str)
+ def invite(self, name):
+ guest = Person(self)
+ guest.name = name
+ self.appendGuest(guest)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/methods/doc/methods.rst b/examples/qml/referenceexamples/methods/doc/methods.rst
new file mode 100644
index 000000000..bda2ede5a
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/doc/methods.rst
@@ -0,0 +1,15 @@
+.. _qml-methods-example:
+
+Extending QML - Methods Example
+===============================
+
+This example builds on the :ref:`qml-adding-types-example`,
+the :ref:`qml-object-and-list-property-types-example` and
+the :ref:`qml-inheritance-and-coercion-example`.
+
+The Methods Example has an additional method in the ``BirthdayParty`` class:
+``invite()``. ``invite()`` is decorated with ``@Slot`` so that it can be
+called from QML.
+
+In ``example.qml``, the ``invite()`` method is called
+in the ``QtQml.Component.completed()`` signal handler.
diff --git a/examples/qml/referenceexamples/methods/example.qml b/examples/qml/referenceexamples/methods/example.qml
new file mode 100644
index 000000000..c48e952fd
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/example.qml
@@ -0,0 +1,19 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import examples.methods.people
+
+BirthdayParty {
+ host: Person {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+ guests: [
+ Person { name: "Leo Hodges" },
+ Person { name: "Jack Smith" },
+ Person { name: "Anne Brown" }
+ ]
+
+ Component.onCompleted: invite("William Green")
+}
diff --git a/examples/qml/referenceexamples/methods/main.py b/examples/qml/referenceexamples/methods/main.py
new file mode 100644
index 000000000..31748ff2b
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/main.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/methods example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Person
+from birthdayparty import BirthdayParty
+
+
+app = QCoreApplication(sys.argv)
+qml_file = Path(__file__).parent / "example.qml"
+url = QUrl.fromLocalFile(qml_file)
+engine = QQmlEngine()
+component = QQmlComponent(engine, url)
+party = component.create()
+if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+host = party.host
+print(f"{host.name} is having a birthday!\nThey are inviting:")
+for g in range(party.guestCount()):
+ name = party.guest(g).name
+ print(f" {name}")
+del engine
+sys.exit(0)
diff --git a/examples/qml/referenceexamples/methods/methods.pyproject b/examples/qml/referenceexamples/methods/methods.pyproject
new file mode 100644
index 000000000..3c01c40c2
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/methods.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/referenceexamples/methods/person.py b/examples/qml/referenceexamples/methods/person.py
new file mode 100644
index 000000000..b5e0bd899
--- /dev/null
+++ b/examples/qml/referenceexamples/methods/person.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.methods.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
diff --git a/examples/qml/referenceexamples/properties/birthdayparty.py b/examples/qml/referenceexamples/properties/birthdayparty.py
new file mode 100644
index 000000000..1a115101b
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/birthdayparty.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.properties.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/properties/doc/properties.rst b/examples/qml/referenceexamples/properties/doc/properties.rst
new file mode 100644
index 000000000..909434c3c
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/doc/properties.rst
@@ -0,0 +1,89 @@
+.. _qml-object-and-list-property-types-example:
+
+Extending QML - Object and List Property Types Example
+======================================================
+
+Exporting C++ Properties.
+
+This example builds on :ref:`qml-adding-types-example`.
+
+The Object and List Property Types example shows how to add object and list
+properties in QML. This example adds a BirthdayParty type that specifies a
+birthday party, consisting of a celebrant and a list of guests. People are
+specified using the People QML type built in the previous example.
+
+import examples.properties.people
+
+.. code-block:: javascript
+
+ BirthdayParty {
+ host: Person {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+ guests: [
+ Person { name: "Leo Hodges" },
+ Person { name: "Jack Smith" },
+ Person { name: "Anne Brown" }
+ ]
+ }
+
+Declare the BirthdayParty
+-------------------------
+
+The BirthdayParty class is declared like this:
+
+.. code-block:: python
+
+ from person import Person
+
+
+ # To be used on the @QmlElement decorator
+ # (QML_IMPORT_MINOR_VERSION is optional)
+ QML_IMPORT_NAME = "examples.properties.people"
+ QML_IMPORT_MAJOR_VERSION = 1
+
+
+ @QmlElement
+ class BirthdayParty(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ guests = ListProperty(Person, appendGuest)
+
+The class contains a member to store the celebrant object, and also a
+list member storing the Person instances.
+
+In QML, the type of a list properties - and the guests property is a list of
+people - are all of type ListProperty. ListProperty is simple value
+type that contains a set of functions. QML calls these functions
+whenever it needs to read from, write to or otherwise interact with
+the list. In addition to concrete lists like the people list used in this
+example, the use of QQmlListProperty allows for "virtual lists" and other advanced
+scenarios.
+
+Running the Example
+-------------------
+
+The main.py file in the example includes a simple shell application that
+loads and runs the QML snippet shown at the beginning of this page.
diff --git a/examples/qml/referenceexamples/properties/example.qml b/examples/qml/referenceexamples/properties/example.qml
new file mode 100644
index 000000000..1486a0f92
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/example.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.properties.people
+
+BirthdayParty {
+ host: Person {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+ guests: [
+ Person { name: "Leo Hodges" },
+ Person { name: "Jack Smith" },
+ Person { name: "Anne Brown" }
+ ]
+}
diff --git a/examples/qml/referenceexamples/properties/main.py b/examples/qml/referenceexamples/properties/main.py
new file mode 100644
index 000000000..a980b25aa
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/main.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/properties example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Person
+from birthdayparty import BirthdayParty
+
+
+if __name__ == '__main__':
+ app = QCoreApplication(sys.argv)
+
+ qml_file = Path(__file__).parent / "example.qml"
+ url = QUrl.fromLocalFile(qml_file)
+ engine = QQmlEngine()
+ component = QQmlComponent(engine, url)
+
+ party = component.create()
+ if party:
+ print(f"{party.host} is having a birthday!\nThey are inviting:")
+ for g in range(party.guestCount()):
+ name = party.guest(g).name
+ print(f" {name}")
+ else:
+ print(component.errors())
+
+ del engine
+ sys.exit(0)
diff --git a/examples/qml/referenceexamples/properties/person.py b/examples/qml/referenceexamples/properties/person.py
new file mode 100644
index 000000000..4cc54260a
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/person.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.properties.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
diff --git a/examples/qml/referenceexamples/properties/properties.pyproject b/examples/qml/referenceexamples/properties/properties.pyproject
new file mode 100644
index 000000000..0f5958fc3
--- /dev/null
+++ b/examples/qml/referenceexamples/properties/properties.pyproject
@@ -0,0 +1,6 @@
+{
+ "files": ["example.qml",
+ "main.py",
+ "person.py",
+ "birthdayparty.py"]
+}
diff --git a/examples/qml/referenceexamples/valuesource/birthdayparty.py b/examples/qml/referenceexamples/valuesource/birthdayparty.py
new file mode 100644
index 000000000..3bc75e819
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/birthdayparty.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QDate, QObject, ClassInfo, Property, QTime, Signal
+from PySide6.QtQml import QmlAnonymous, QmlAttached, QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.valuesource.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class BirthdayPartyAttached(QObject):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._rsvp = QDate()
+
+ @Property(QDate)
+ def rsvp(self):
+ return self._rsvp
+
+ @rsvp.setter
+ def rsvp(self, d):
+ self._rsvp = d
+
+
+@QmlElement
+@ClassInfo(DefaultProperty="guests")
+@QmlAttached(BirthdayPartyAttached)
+class BirthdayParty(QObject):
+
+ partyStarted = Signal(QTime)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ def startParty(self):
+ self.partyStarted.emit(QTime.currentTime())
+
+ @Property(Person)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ self._host = h
+
+ @Property(str)
+ def announcement(self):
+ return ""
+
+ @announcement.setter
+ def announcement(self, a):
+ print(a)
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+
+ @staticmethod
+ def qmlAttachedProperties(self, o):
+ return BirthdayPartyAttached(o)
+
+ guests = ListProperty(Person, appendGuest)
diff --git a/examples/qml/referenceexamples/valuesource/doc/valuesource.rst b/examples/qml/referenceexamples/valuesource/doc/valuesource.rst
new file mode 100644
index 000000000..81fbc827f
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/doc/valuesource.rst
@@ -0,0 +1,20 @@
+.. _qml-valuesource-example:
+
+Extending QML - Value Source Example
+====================================
+
+This example builds on the :ref:`qml-adding-types-example`,
+the :ref:`qml-attached-properties-example`,
+the :ref:`qml-default-property-example`,
+the :ref:`qml-inheritance-and-coercion-example` and
+the :ref:`qml-object-and-list-property-types-example`.
+
+It demonstrates implementing a
+`property value source <https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html#property-value-sources>`_
+in Python.
+
+Running the Example
+-------------------
+
+The main.py file in the example includes a simple shell application that
+loads and runs the QML snippet shown below.
diff --git a/examples/qml/referenceexamples/valuesource/example.qml b/examples/qml/referenceexamples/valuesource/example.qml
new file mode 100644
index 000000000..cb9683f3a
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/example.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import examples.valuesource.people
+
+BirthdayParty {
+ HappyBirthdaySong on announcement { name: "Bob Jones" }
+
+ onPartyStarted: (time) => { console.log("This party started rockin' at " + time); }
+
+ host: Boy {
+ name: "Bob Jones"
+ shoe_size: 12
+ }
+
+ Boy {
+ name: "Leo Hodges"
+ BirthdayParty.rsvp: "2009-07-06"
+ }
+ Boy {
+ name: "Jack Smith"
+ }
+ Girl {
+ name: "Anne Brown"
+ BirthdayParty.rsvp: "2009-07-01"
+ }
+}
diff --git a/examples/qml/referenceexamples/valuesource/happybirthdaysong.py b/examples/qml/referenceexamples/valuesource/happybirthdaysong.py
new file mode 100644
index 000000000..cffddd39e
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/happybirthdaysong.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, QTimer, Property, Slot
+from PySide6.QtQml import QmlElement, QPyQmlPropertyValueSource
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.valuesource.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class HappyBirthdaySong(QPyQmlPropertyValueSource):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.m_target = None
+ self.m_name = ""
+ self.m_line = -1
+ self.m_lyrics = []
+
+ self.m_timer = QTimer(self)
+ self.m_timer.timeout.connect(self.advance)
+ self.m_timer.start(1000)
+
+ def setTarget(self, property):
+ self.m_target = property
+
+ @Property(str)
+ def name(self):
+ return self.m_name
+
+ @name.setter
+ def name(self, n):
+ self.m_name = n
+ self.m_lyrics = ["Happy birthday to you,",
+ "Happy birthday to you,",
+ f"Happy birthday dear {self.m_name},",
+ "Happy birthday to you!",
+ ""]
+
+ @Slot()
+ def advance(self):
+ self.m_line = (self.m_line + 1) % len(self.m_lyrics)
+ self.m_target.write(self.m_lyrics[self.m_line])
diff --git a/examples/qml/referenceexamples/valuesource/main.py b/examples/qml/referenceexamples/valuesource/main.py
new file mode 100644
index 000000000..c3ded4be9
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/main.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/examples/qml/referenceexamples/valuesource example from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication, QUrl
+from PySide6.QtQml import QQmlComponent, QQmlEngine, qmlAttachedPropertiesObject
+
+from person import Boy, Girl
+from birthdayparty import BirthdayParty
+from happybirthdaysong import HappyBirthdaySong
+
+
+app = QCoreApplication(sys.argv)
+qml_file = Path(__file__).parent / "example.qml"
+url = QUrl.fromLocalFile(qml_file)
+engine = QQmlEngine()
+component = QQmlComponent(engine, url)
+party = component.create()
+if not party:
+ print(component.errors())
+ del engine
+ sys.exit(-1)
+host = party.host
+print(f"{host.name} is having a birthday!")
+if isinstance(host, Boy):
+ print("He is inviting:")
+else:
+ print("She is inviting:")
+for g in range(party.guestCount()):
+ guest = party.guest(g)
+ name = guest.name
+
+ rsvp_date = None
+ attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False)
+ if attached:
+ rsvp_date = attached.rsvp.toString()
+ if rsvp_date:
+ print(f" {name} RSVP date: {rsvp_date}")
+ else:
+ print(f" {name} RSVP date: Hasn't RSVP'd")
+
+party.startParty()
+
+r = app.exec()
+
+del engine
+sys.exit(r)
diff --git a/examples/qml/referenceexamples/valuesource/person.py b/examples/qml/referenceexamples/valuesource/person.py
new file mode 100644
index 000000000..5cd04e38a
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/person.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import QObject, Property
+from PySide6.QtQml import QmlAnonymous, QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.valuesource.people"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlAnonymous
+class Person(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._name = ''
+ self._shoe_size = 0
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, n):
+ self._name = n
+
+ @Property(int)
+ def shoe_size(self):
+ return self._shoe_size
+
+ @shoe_size.setter
+ def shoe_size(self, s):
+ self._shoe_size = s
+
+
+@QmlElement
+class Boy(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+@QmlElement
+class Girl(Person):
+ def __init__(self, parent=None):
+ super().__init__(parent)
diff --git a/examples/qml/referenceexamples/valuesource/valuesource.pyproject b/examples/qml/referenceexamples/valuesource/valuesource.pyproject
new file mode 100644
index 000000000..a782d5c8a
--- /dev/null
+++ b/examples/qml/referenceexamples/valuesource/valuesource.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "birthdayparty.py", "happybirthdaysong.py", "person.py", "example.qml"]
+}
diff --git a/examples/qml/signals/pytoqml1/main.py b/examples/qml/signals/pytoqml1/main.py
new file mode 100644
index 000000000..5bc27a521
--- /dev/null
+++ b/examples/qml/signals/pytoqml1/main.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QTimer, QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ timer = QTimer()
+ timer.start(2000)
+
+ view = QQuickView()
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ root = view.rootObject()
+
+ timer.timeout.connect(root.updateRotater)
+
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/pytoqml1/pytoqml1.pyproject b/examples/qml/signals/pytoqml1/pytoqml1.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/pytoqml1/pytoqml1.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/pytoqml1/view.qml b/examples/qml/signals/pytoqml1/view.qml
new file mode 100644
index 000000000..af2d966be
--- /dev/null
+++ b/examples/qml/signals/pytoqml1/view.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Rectangle {
+ id: page
+
+ function updateRotater() {
+ rotater.angle = rotater.angle + 45
+ }
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Rectangle {
+ id: rotater
+ property real angle : 0
+ x: 240
+ width: 100; height: 10
+ color: "black"
+ y: 95
+
+ transform: Rotation {
+ origin.x: 10; origin.y: 5
+ angle: rotater.angle
+ Behavior on angle {
+ SpringAnimation {
+ spring: 1.4
+ damping: .05
+ }
+ }
+ }
+ }
+
+}
diff --git a/examples/qml/signals/pytoqml2/main.py b/examples/qml/signals/pytoqml2/main.py
new file mode 100644
index 000000000..3a3650aba
--- /dev/null
+++ b/examples/qml/signals/pytoqml2/main.py
@@ -0,0 +1,54 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QObject, QTimer, QUrl, Signal, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.signals.pytoqml2"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class RotateValue(QObject):
+ valueChanged = Signal(int, arguments=['val'])
+
+ def __init__(self):
+ super().__init__()
+ self.r = 0
+
+ @Slot()
+ def increment(self):
+ self.r = self.r + 10
+ self.valueChanged.emit(self.r)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ rotatevalue = RotateValue()
+ timer = QTimer()
+ timer.start(2000)
+ view.setInitialProperties({"rotatevalue": rotatevalue})
+
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+
+ timer.timeout.connect(rotatevalue.increment)
+
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make
+ # sure all child QML instances are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/pytoqml2/pytoqml2.pyproject b/examples/qml/signals/pytoqml2/pytoqml2.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/pytoqml2/pytoqml2.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/pytoqml2/view.qml b/examples/qml/signals/pytoqml2/view.qml
new file mode 100644
index 000000000..2e9128f53
--- /dev/null
+++ b/examples/qml/signals/pytoqml2/view.qml
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQml
+
+import examples.signals.pytoqml2 1.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+ required property RotateValue rotatevalue
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 30
+ font.pointSize: 24; font.bold: true
+ }
+
+ Connections {
+ target: rotatevalue
+ function onValueChanged(val) {
+ helloText.rotation = val
+ }
+ }
+}
diff --git a/examples/qml/signals/qmltopy1/main.py b/examples/qml/signals/qmltopy1/main.py
new file mode 100644
index 000000000..83966903c
--- /dev/null
+++ b/examples/qml/signals/qmltopy1/main.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QObject, QUrl, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.signals.qmltopy1"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Console(QObject):
+ """Output stuff on the console."""
+
+ @Slot(str)
+ @Slot('double')
+ def output(self, s):
+ print(s)
+
+ @Slot(str)
+ def outputStr(self, s):
+ print(s)
+
+ @Slot('double')
+ def outputFloat(self, x):
+ print(x)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/qmltopy1/qmltopy1.pyproject b/examples/qml/signals/qmltopy1/qmltopy1.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/qmltopy1/qmltopy1.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/qmltopy1/view.qml b/examples/qml/signals/qmltopy1/view.qml
new file mode 100644
index 000000000..b10e2e77d
--- /dev/null
+++ b/examples/qml/signals/qmltopy1/view.qml
@@ -0,0 +1,54 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+
+import QtQuick
+
+import examples.signals.qmltopy1 1.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Console {
+ id: pyConsole
+ }
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 30
+ font.pointSize: 24; font.bold: true
+ }
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ // once the "console" context has been declared,
+ // slots can be called like functions
+ pyConsole.outputFloat(123)
+ pyConsole.outputStr("foobar")
+ pyConsole.output(helloText.x)
+ pyConsole.output(helloText.text)
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/qml/signals/qmltopy2/main.py b/examples/qml/signals/qmltopy2/main.py
new file mode 100644
index 000000000..bc2e8d3ed
--- /dev/null
+++ b/examples/qml/signals/qmltopy2/main.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QObject, QUrl, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "examples.signals.qmltopy2"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class RotateValue(QObject):
+ def __init__(self):
+ super().__init__()
+ self.r = 0
+
+ # If a slot returns a value, the return value type must be explicitly
+ # defined in the decorator.
+ @Slot(result=int)
+ def val(self):
+ self.r = self.r + 10
+ return self.r
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/qmltopy2/qmltopy2.pyproject b/examples/qml/signals/qmltopy2/qmltopy2.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/qmltopy2/qmltopy2.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/qmltopy2/view.qml b/examples/qml/signals/qmltopy2/view.qml
new file mode 100644
index 000000000..4bbda574c
--- /dev/null
+++ b/examples/qml/signals/qmltopy2/view.qml
@@ -0,0 +1,49 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+import examples.signals.qmltopy2 1.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ RotateValue {
+ id: rotatevalue
+ }
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 30
+ font.pointSize: 24; font.bold: true
+ }
+
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ helloText.rotation = rotatevalue.val()
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/qml/signals/qmltopy3/main.py b/examples/qml/signals/qmltopy3/main.py
new file mode 100644
index 000000000..6a5554842
--- /dev/null
+++ b/examples/qml/signals/qmltopy3/main.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+
+
+def sayThis(s):
+ print(s)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+
+ root = view.rootObject()
+ root.textRotationChanged.connect(sayThis)
+ root.buttonClicked.connect(lambda: sayThis("clicked button (QML top-level signal)"))
+
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/qmltopy3/qmltopy3.pyproject b/examples/qml/signals/qmltopy3/qmltopy3.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/qmltopy3/qmltopy3.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/qmltopy3/view.qml b/examples/qml/signals/qmltopy3/view.qml
new file mode 100644
index 000000000..3e8a0f564
--- /dev/null
+++ b/examples/qml/signals/qmltopy3/view.qml
@@ -0,0 +1,66 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Rectangle {
+ id: page
+
+ signal buttonClicked
+ signal textRotationChanged(double rot)
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ y: 30
+ x: page.width/2-width/2
+ font.pointSize: 24; font.bold: true
+ onRotationChanged: textRotationChanged(rotation)
+
+ states: State {
+ name: "down"; when: buttonMouseArea.pressed === true
+ PropertyChanges {
+ target: helloText;
+ rotation: 180;
+ y: 100;
+ }
+ }
+
+ transitions: Transition {
+ from: ""; to: "down"; reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y,rotation"
+ duration: 500
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ buttonClicked()
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/qml/signals/qmltopy4/main.py b/examples/qml/signals/qmltopy4/main.py
new file mode 100644
index 000000000..8a56073d1
--- /dev/null
+++ b/examples/qml/signals/qmltopy4/main.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QObject, QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+
+
+def sayThis(s):
+ print(s)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+
+ root = view.rootObject()
+ button = root.findChild(QObject, "buttonMouseArea")
+ button.clicked.connect(lambda: sayThis("clicked button (signal directly connected)"))
+
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/signals/qmltopy4/qmltopy4.pyproject b/examples/qml/signals/qmltopy4/qmltopy4.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/signals/qmltopy4/qmltopy4.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/signals/qmltopy4/view.qml b/examples/qml/signals/qmltopy4/view.qml
new file mode 100644
index 000000000..771b14c47
--- /dev/null
+++ b/examples/qml/signals/qmltopy4/view.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ anchors.verticalCenter: page.verticalCenter
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/qml/textproperties/doc/textproperties.png b/examples/qml/textproperties/doc/textproperties.png
new file mode 100644
index 000000000..b14bb73d7
--- /dev/null
+++ b/examples/qml/textproperties/doc/textproperties.png
Binary files differ
diff --git a/examples/qml/textproperties/doc/textproperties.rst b/examples/qml/textproperties/doc/textproperties.rst
new file mode 100644
index 000000000..81829dfdc
--- /dev/null
+++ b/examples/qml/textproperties/doc/textproperties.rst
@@ -0,0 +1,9 @@
+Text Properties Example
+=======================
+
+A Python application that demonstrates how to load a qml file
+using Material design, to change the look of text.
+
+.. image:: textproperties.png
+ :width: 400
+ :alt: Text Properties Screenshot
diff --git a/examples/qml/textproperties/main.py b/examples/qml/textproperties/main.py
new file mode 100644
index 000000000..4e6afc9ff
--- /dev/null
+++ b/examples/qml/textproperties/main.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+from pathlib import Path
+
+from PySide6.QtCore import QObject, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlApplicationEngine, QmlElement
+from PySide6.QtQuickControls2 import QQuickStyle
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "io.qt.textproperties"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class Bridge(QObject):
+
+ @Slot(str, result=str)
+ def getColor(self, s):
+ if s.lower() == "red":
+ return "#ef9a9a"
+ elif s.lower() == "green":
+ return "#a5d6a7"
+ elif s.lower() == "blue":
+ return "#90caf9"
+ else:
+ return "white"
+
+ @Slot(float, result=int)
+ def getSize(self, s):
+ size = int(s * 34)
+ if size <= 0:
+ return 1
+ else:
+ return size
+
+ @Slot(str, result=bool)
+ def getItalic(self, s):
+ if s.lower() == "italic":
+ return True
+ else:
+ return False
+
+ @Slot(str, result=bool)
+ def getBold(self, s):
+ if s.lower() == "bold":
+ return True
+ else:
+ return False
+
+ @Slot(str, result=bool)
+ def getUnderline(self, s):
+ if s.lower() == "underline":
+ return True
+ else:
+ return False
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ QQuickStyle.setStyle("Material")
+ engine = QQmlApplicationEngine()
+
+ # Get the path of the current directory, and then add the name
+ # of the QML file, to load it.
+ qml_file = Path(__file__).parent / 'view.qml'
+ engine.load(qml_file)
+
+ if not engine.rootObjects():
+ sys.exit(-1)
+
+ sys.exit(app.exec())
diff --git a/examples/qml/textproperties/textproperties.pyproject b/examples/qml/textproperties/textproperties.pyproject
new file mode 100644
index 000000000..e6f087cce
--- /dev/null
+++ b/examples/qml/textproperties/textproperties.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "view.qml"]
+}
diff --git a/examples/qml/textproperties/view.qml b/examples/qml/textproperties/view.qml
new file mode 100644
index 000000000..c722eb4eb
--- /dev/null
+++ b/examples/qml/textproperties/view.qml
@@ -0,0 +1,160 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQuick.Window
+import QtQuick.Controls.Material
+
+import io.qt.textproperties
+
+ApplicationWindow {
+ id: page
+ width: 800
+ height: 400
+ visible: true
+ Material.theme: Material.Dark
+ Material.accent: Material.Red
+
+ Bridge {
+ id: bridge
+ }
+
+ GridLayout {
+ id: grid
+ columns: 2
+ rows: 3
+
+ ColumnLayout {
+ spacing: 2
+ Layout.columnSpan: 1
+ Layout.preferredWidth: 400
+
+ Text {
+ id: leftlabel
+ Layout.alignment: Qt.AlignHCenter
+ color: "white"
+ font.pointSize: 16
+ text: "Qt for Python"
+ Layout.preferredHeight: 100
+ Material.accent: Material.Green
+ }
+
+ RadioButton {
+ id: italic
+ Layout.alignment: Qt.AlignLeft
+ text: "Italic"
+ onToggled: {
+ leftlabel.font.italic = bridge.getItalic(italic.text)
+ leftlabel.font.bold = bridge.getBold(italic.text)
+ leftlabel.font.underline = bridge.getUnderline(italic.text)
+
+ }
+ }
+ RadioButton {
+ id: bold
+ Layout.alignment: Qt.AlignLeft
+ text: "Bold"
+ onToggled: {
+ leftlabel.font.italic = bridge.getItalic(bold.text)
+ leftlabel.font.bold = bridge.getBold(bold.text)
+ leftlabel.font.underline = bridge.getUnderline(bold.text)
+ }
+ }
+ RadioButton {
+ id: underline
+ Layout.alignment: Qt.AlignLeft
+ text: "Underline"
+ onToggled: {
+ leftlabel.font.italic = bridge.getItalic(underline.text)
+ leftlabel.font.bold = bridge.getBold(underline.text)
+ leftlabel.font.underline = bridge.getUnderline(underline.text)
+ }
+ }
+ RadioButton {
+ id: noneradio
+ Layout.alignment: Qt.AlignLeft
+ text: "None"
+ checked: true
+ onToggled: {
+ leftlabel.font.italic = bridge.getItalic(noneradio.text)
+ leftlabel.font.bold = bridge.getBold(noneradio.text)
+ leftlabel.font.underline = bridge.getUnderline(noneradio.text)
+ }
+ }
+ }
+
+ ColumnLayout {
+ id: rightcolumn
+ spacing: 2
+ Layout.columnSpan: 1
+ Layout.preferredWidth: 400
+ Layout.preferredHeight: 400
+ Layout.fillWidth: true
+
+ RowLayout {
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
+
+
+ Button {
+ id: red
+ text: "Red"
+ highlighted: true
+ Material.accent: Material.Red
+ onClicked: {
+ leftlabel.color = bridge.getColor(red.text)
+ }
+ }
+ Button {
+ id: green
+ text: "Green"
+ highlighted: true
+ Material.accent: Material.Green
+ onClicked: {
+ leftlabel.color = bridge.getColor(green.text)
+ }
+ }
+ Button {
+ id: blue
+ text: "Blue"
+ highlighted: true
+ Material.accent: Material.Blue
+ onClicked: {
+ leftlabel.color = bridge.getColor(blue.text)
+ }
+ }
+ Button {
+ id: nonebutton
+ text: "None"
+ highlighted: true
+ Material.accent: Material.BlueGrey
+ onClicked: {
+ leftlabel.color = bridge.getColor(nonebutton.text)
+ }
+ }
+ }
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
+ Text {
+ id: rightlabel
+ color: "white"
+ Layout.alignment: Qt.AlignLeft
+ text: "Font size"
+ Material.accent: Material.White
+ }
+ Slider {
+ width: rightcolumn.width*0.6
+ Layout.alignment: Qt.AlignRight
+ id: slider
+ value: 0.5
+ onValueChanged: {
+ leftlabel.font.pointSize = bridge.getSize(value)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/qml/tutorials/extending/chapter1-basics/app.qml b/examples/qml/tutorials/extending/chapter1-basics/app.qml
new file mode 100644
index 000000000..415183596
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter1-basics/app.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: aPieChart
+ anchors.centerIn: parent
+ width: 100; height: 100
+ name: "A simple pie chart"
+ color: "red"
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: aPieChart.name
+ }
+}
+//![0]
diff --git a/examples/qml/tutorials/extending/chapter1-basics/basics.py b/examples/qml/tutorials/extending/chapter1-basics/basics.py
new file mode 100644
index 000000000..f76183705
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter1-basics/basics.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter1-basics example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, Signal, QUrl
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieChart (QQuickPaintedItem):
+
+ nameChanged = Signal()
+
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._color = QColor()
+
+ def paint(self, painter):
+ pen = QPen(self.color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16)
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ self._color = value
+
+ @Property(str, notify=nameChanged)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pyproject b/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pyproject
new file mode 100644
index 000000000..869556bb8
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["basics.py", "app.qml"]
+}
diff --git a/examples/qml/tutorials/extending/chapter2-methods/app.qml b/examples/qml/tutorials/extending/chapter2-methods/app.qml
new file mode 100644
index 000000000..d330f3b64
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter2-methods/app.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: aPieChart
+ anchors.centerIn: parent
+ width: 100; height: 100
+ color: "red"
+
+ onChartCleared: console.log("The chart has been cleared")
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: aPieChart.clearChart()
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: "Click anywhere to clear the chart"
+ }
+}
+//![0]
diff --git a/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pyproject b/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pyproject
new file mode 100644
index 000000000..cdf33be7f
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["methods.py", "app.qml"]
+}
diff --git a/examples/qml/tutorials/extending/chapter2-methods/methods.py b/examples/qml/tutorials/extending/chapter2-methods/methods.py
new file mode 100644
index 000000000..f8241db72
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter2-methods/methods.py
@@ -0,0 +1,75 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter2-methods example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, Signal, Slot, Qt, QUrl
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieChart(QQuickPaintedItem):
+
+ chartCleared = Signal()
+ nameChanged = Signal()
+
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._color = QColor()
+
+ def paint(self, painter):
+ pen = QPen(self.color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16)
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ self._color = value
+
+ @Property(str, notify=nameChanged)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ @Slot() # This should be something like @Invokable
+ def clearChart(self):
+ self.color = Qt.transparent
+ self.update()
+ self.chartCleared.emit()
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/app.qml b/examples/qml/tutorials/extending/chapter3-bindings/app.qml
new file mode 100644
index 000000000..ee24a428a
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter3-bindings/app.qml
@@ -0,0 +1,41 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 20
+
+ PieChart {
+ id: chartA
+ width: 100; height: 100
+ color: "red"
+ }
+
+ PieChart {
+ id: chartB
+ width: 100; height: 100
+ color: chartA.color
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: { chartA.color = "blue" }
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: "Click anywhere to change the chart color"
+ }
+}
+//![0]
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/bindings.py b/examples/qml/tutorials/extending/chapter3-bindings/bindings.py
new file mode 100644
index 000000000..e50f08397
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter3-bindings/bindings.py
@@ -0,0 +1,79 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter3-bindings example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, Signal, Slot, QUrl, Qt
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieChart (QQuickPaintedItem):
+
+ chartCleared = Signal()
+ nameChanged = Signal()
+ colorChanged = Signal()
+
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._color = QColor()
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16)
+
+ @Property(QColor, notify=colorChanged)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ if value != self._color:
+ self._color = value
+ self.update()
+ self.colorChanged.emit()
+
+ @Property(str, notify=nameChanged)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ @Slot() # This should be something like @Invokable
+ def clearChart(self):
+ self.color = Qt.transparent
+ self.update()
+ self.chartCleared.emit()
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pyproject b/examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pyproject
new file mode 100644
index 000000000..6e21f86f9
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["app.qml", "bindings.py"]
+}
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
new file mode 100644
index 000000000..954e6465c
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: chart
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ pieSlice: PieSlice {
+ anchors.fill: parent
+ color: "red"
+ }
+ }
+
+ Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color)
+}
+//![0]
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject
new file mode 100644
index 000000000..af1cfefb7
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["app.qml", "customPropertyTypes.py"]
+}
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/customPropertyTypes.py b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/customPropertyTypes.py
new file mode 100644
index 000000000..ee10f0894
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter4-customPropertyTypes/customPropertyTypes.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter4-customPropertyTypes example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, QUrl
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieSlice (QQuickPaintedItem):
+
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._color = QColor()
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ self._color = value
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16)
+
+
+@QmlElement
+class PieChart (QQuickItem):
+ def __init__(self, parent=None):
+ QQuickItem.__init__(self, parent)
+ self._name = None
+ self._pieSlice = None
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ @Property(PieSlice)
+ def pieSlice(self):
+ return self._pieSlice
+
+ @pieSlice.setter
+ def pieSlice(self, value):
+ self._pieSlice = value
+ self._pieSlice.setParentItem(self)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/app.qml b/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
new file mode 100644
index 000000000..edbf3e770
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ slices: [
+ PieSlice {
+ anchors.fill: parent
+ color: "red"
+ fromAngle: 0; angleSpan: 110
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "black"
+ fromAngle: 110; angleSpan: 50
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "blue"
+ fromAngle: 160; angleSpan: 100
+ }
+ ]
+ }
+}
+//![0]
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pyproject b/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pyproject
new file mode 100644
index 000000000..a3f89d575
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["app.qml", "listproperties.py"]
+}
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/listproperties.py b/examples/qml/tutorials/extending/chapter5-listproperties/listproperties.py
new file mode 100644
index 000000000..95a393fa3
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter5-listproperties/listproperties.py
@@ -0,0 +1,96 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the qml/tutorials/extending-qml/chapter5-listproperties example from Qt v5.x"""
+
+import os
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import Property, QUrl
+from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide6.QtQml import QmlElement, ListProperty
+from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class PieSlice (QQuickPaintedItem):
+ def __init__(self, parent=None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._color = QColor()
+ self._fromAngle = 0
+ self._angleSpan = 0
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, value):
+ self._color = value
+
+ @Property(int)
+ def fromAngle(self):
+ return self._angle
+
+ @fromAngle.setter
+ def fromAngle(self, value):
+ self._fromAngle = value
+
+ @Property(int)
+ def angleSpan(self):
+ return self._angleSpan
+
+ @angleSpan.setter
+ def angleSpan(self, value):
+ self._angleSpan = value
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen)
+ painter.setRenderHints(QPainter.Antialiasing, True)
+ painter.drawPie(self.boundingRect().adjusted(1, 1, -1, -1), self._fromAngle * 16, self._angleSpan * 16)
+
+
+@QmlElement
+class PieChart (QQuickItem):
+ def __init__(self, parent=None):
+ QQuickItem.__init__(self, parent)
+ self._name = u''
+ self._slices = []
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ self._name = value
+
+ def appendSlice(self, _slice):
+ _slice.setParentItem(self)
+ self._slices.append(_slice)
+
+ slices = ListProperty(PieSlice, appendSlice)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/Charts/piechart.py b/examples/qml/tutorials/extending/chapter6-plugins/Charts/piechart.py
new file mode 100644
index 000000000..b721a7130
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/Charts/piechart.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import Property
+from PySide6.QtQml import QmlElement, ListProperty
+from PySide6.QtQuick import QQuickItem
+
+from pieslice import PieSlice
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+@QmlElement
+class PieChart(QQuickItem):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._slices = []
+ self._name = ''
+
+ @Property(str)
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ def slice(self, n):
+ return self._slices[n]
+
+ def sliceCount(self):
+ return len(self._slices)
+
+ def append_and_setparent(self, slice):
+ self._slices.append(slice)
+ slice.setParentItem(self)
+
+ slices = ListProperty(PieSlice, append_and_setparent)
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/Charts/pieslice.py b/examples/qml/tutorials/extending/chapter6-plugins/Charts/pieslice.py
new file mode 100644
index 000000000..7945eff12
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/Charts/pieslice.py
@@ -0,0 +1,52 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtCore import Property, QRectF
+from PySide6.QtGui import QColor, QPainter, QPen
+from PySide6.QtQuick import QQuickPaintedItem
+from PySide6.QtQml import QmlElement
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Charts"
+QML_IMPORT_MAJOR_VERSION = 1
+
+@QmlElement
+class PieSlice(QQuickPaintedItem):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self._color = QColor()
+ self._from_angle = 0
+ self._angle_span = 0
+
+ @Property(QColor)
+ def color(self):
+ return self._color
+
+ @color.setter
+ def color(self, color):
+ self._color = QColor(color)
+
+ @Property(int)
+ def fromAngle(self):
+ return self._from_angle
+
+ @fromAngle.setter
+ def fromAngle(self, fromAngle):
+ self._from_angle = fromAngle
+
+ @Property(int)
+ def angleSpan(self):
+ return self._angle_span
+
+ @angleSpan.setter
+ def angleSpan(self, angleSpan):
+ self._angle_span = angleSpan
+
+ def paint(self, painter):
+ painter.setPen(QPen(self._color, 2))
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
+
+ rect = QRectF(0, 0, self.width(), self.height()).adjusted(1, 1, -1, -1)
+ painter.drawPie(rect, self._from_angle * 16, self._angle_span * 16)
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/Charts/plugins.png b/examples/qml/tutorials/extending/chapter6-plugins/Charts/plugins.png
new file mode 100644
index 000000000..8992e89c0
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/Charts/plugins.png
Binary files differ
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/app.qml b/examples/qml/tutorials/extending/chapter6-plugins/app.qml
new file mode 100644
index 000000000..70761619f
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/app.qml
@@ -0,0 +1,32 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick 2.0
+import Charts 1.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ slices: [
+ PieSlice {
+ anchors.fill: parent
+ color: "red"
+ fromAngle: 0; angleSpan: 110
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "black"
+ fromAngle: 110; angleSpan: 50
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "blue"
+ fromAngle: 160; angleSpan: 100
+ }
+ ]
+ }
+}
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pyproject b/examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pyproject
new file mode 100644
index 000000000..cc684401f
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["app.qml", "Charts/piechart.py", "Charts/pieslice.py"]
+}
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/doc/chapter6-plugins.rst b/examples/qml/tutorials/extending/chapter6-plugins/doc/chapter6-plugins.rst
new file mode 100644
index 000000000..10aba1e8f
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/doc/chapter6-plugins.rst
@@ -0,0 +1,21 @@
+.. _qml-chapter6-plugins-example:
+
+Extending QML - Plugins Example
+===============================
+
+This example refers to the Python version of using a QML plugin in Python. The idea of plugins in
+Python is non-existent because Python modules are dynamically loaded anyway. We use this idea and
+our QML type registration decorators - QmlELement/QmlNamedElement - to register the QML modules as
+they are imported. The pyside6-qml tool does this for you by simply pointing to the .qml file.
+
+.. image:: plugins.png
+ :width: 400
+ :alt: Plugins Example
+
+
+Running the Example
+-------------------
+
+.. code-block:: shell
+
+ pyside6-pyqml examples/declarative/extending/chapter6-plugins/app.qml -I examples/declarative/extending/chapter6-plugins/Charts
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/doc/plugins.png b/examples/qml/tutorials/extending/chapter6-plugins/doc/plugins.png
new file mode 100644
index 000000000..8992e89c0
--- /dev/null
+++ b/examples/qml/tutorials/extending/chapter6-plugins/doc/plugins.png
Binary files differ
diff --git a/examples/qml/usingmodel/doc/usingmodel.png b/examples/qml/usingmodel/doc/usingmodel.png
new file mode 100644
index 000000000..b4240951b
--- /dev/null
+++ b/examples/qml/usingmodel/doc/usingmodel.png
Binary files differ
diff --git a/examples/qml/usingmodel/doc/usingmodel.rst b/examples/qml/usingmodel/doc/usingmodel.rst
new file mode 100644
index 000000000..11b476d09
--- /dev/null
+++ b/examples/qml/usingmodel/doc/usingmodel.rst
@@ -0,0 +1,9 @@
+Using Model Example
+===================
+
+A Python application that demonstrates how to use a :ref:`QAbstractListModel`
+with QML.
+
+.. image:: usingmodel.png
+ :width: 400
+ :alt: Using Model Screenshot
diff --git a/examples/qml/usingmodel/usingmodel.py b/examples/qml/usingmodel/usingmodel.py
new file mode 100644
index 000000000..6f8ea5a21
--- /dev/null
+++ b/examples/qml/usingmodel/usingmodel.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+import sys
+from PySide6.QtCore import QAbstractListModel, Qt, QUrl, QByteArray
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQuick import QQuickView
+from PySide6.QtQml import qmlRegisterSingletonType
+
+
+class PersonModel (QAbstractListModel):
+ MyRole = Qt.UserRole + 1
+
+ def __init__(self, parent=None):
+ QAbstractListModel.__init__(self, parent)
+ self._data = []
+
+ def roleNames(self):
+ roles = {
+ PersonModel.MyRole: QByteArray(b'modelData'),
+ Qt.DisplayRole: QByteArray(b'display')
+ }
+ return roles
+
+ def rowCount(self, index):
+ return len(self._data)
+
+ def data(self, index, role):
+ d = self._data[index.row()]
+
+ if role == Qt.DisplayRole:
+ return d['name']
+ elif role == Qt.DecorationRole:
+ return Qt.black
+ elif role == PersonModel.MyRole:
+ return d['myrole']
+ return None
+
+ def populate(self, data=None):
+ for item in data:
+ self._data.append(item)
+
+
+def model_callback(engine):
+ my_model = PersonModel()
+ data = [{'name': 'Qt', 'myrole': 'role1'},
+ {'name': 'PySide', 'myrole': 'role2'}]
+ my_model.populate(data)
+ return my_model
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+
+ qmlRegisterSingletonType(PersonModel, "PersonModel", 1, 0, "MyModel", model_callback)
+ qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
+ view.setSource(QUrl.fromLocalFile(qml_file))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+
+ r = app.exec()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(r)
diff --git a/examples/qml/usingmodel/usingmodel.pyproject b/examples/qml/usingmodel/usingmodel.pyproject
new file mode 100644
index 000000000..600cdb409
--- /dev/null
+++ b/examples/qml/usingmodel/usingmodel.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["view.qml", "usingmodel.py"]
+}
diff --git a/examples/qml/usingmodel/view.qml b/examples/qml/usingmodel/view.qml
new file mode 100644
index 000000000..c5aa7e0fc
--- /dev/null
+++ b/examples/qml/usingmodel/view.qml
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import PersonModel
+
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: MyModel
+ delegate: Component {
+ Rectangle {
+ height: 25
+ width: 100
+ Text {
+ function displayText() {
+ var result = ""
+ if (typeof display !== "undefined")
+ result = display + ": "
+ result += modelData
+ return result
+ }
+
+ text: displayText()
+ }
+ }
+ }
+}