aboutsummaryrefslogtreecommitdiffstats
path: root/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion')
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/Main.qml16
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/qmldir3
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/advanced2-Inheritance-and-coercion.pyproject4
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/birthdayparty.py46
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/doc/advanced2-Inheritance-and-coercion.rst62
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/main.py38
-rw-r--r--examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/person.py52
7 files changed, 221 insertions, 0 deletions
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/Main.qml b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/Main.qml
new file mode 100644
index 000000000..b2b7ace93
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/Main.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import 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/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/qmldir b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/qmldir
new file mode 100644
index 000000000..a2bd9515a
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/People/qmldir
@@ -0,0 +1,3 @@
+module People
+typeinfo coercion.qmltypes
+Main 1.0 Main.qml
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/advanced2-Inheritance-and-coercion.pyproject b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/advanced2-Inheritance-and-coercion.pyproject
new file mode 100644
index 000000000..09942ebcc
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/advanced2-Inheritance-and-coercion.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["main.py", "birthdayparty.py", "person.py",
+ "People/Main.qml", "People/qmldir"]
+}
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/birthdayparty.py b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/birthdayparty.py
new file mode 100644
index 000000000..764815175
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/birthdayparty.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2023 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 QmlElement, ListProperty
+
+from person import Person
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "People"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class BirthdayParty(QObject):
+ host_changed = Signal()
+ guests_changed = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._host = None
+ self._guests = []
+
+ @Property(Person, notify=host_changed, final=True)
+ def host(self):
+ return self._host
+
+ @host.setter
+ def host(self, h):
+ if self._host != h:
+ self._host = h
+ self.host_changed.emit()
+
+ def guest(self, n):
+ return self._guests[n]
+
+ def guestCount(self):
+ return len(self._guests)
+
+ def appendGuest(self, guest):
+ self._guests.append(guest)
+ self.guests_changed.emit()
+
+ guests = ListProperty(Person, appendGuest, notify=guests_changed, final=True)
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/doc/advanced2-Inheritance-and-coercion.rst b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/doc/advanced2-Inheritance-and-coercion.rst
new file mode 100644
index 000000000..16c0dbc9a
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/doc/advanced2-Inheritance-and-coercion.rst
@@ -0,0 +1,62 @@
+.. _qml-advanced2-inheritance-and-coercion:
+
+Extending QML (advanced) - Inheritance and Coercion
+===================================================
+
+This is the second of a series of 6 examples forming a tutorial using the
+example of a birthday party to demonstrate some of the advanced features of
+QML.
+
+Right now, each attendant is being modelled as a person. This is a bit too
+generic and it would be nice to be able to know more about the attendees. By
+specializing them as boys and girls, we can already get a better idea of who's
+coming.
+
+To do this, the ``Boy`` and ``Girl`` classes are introduced, both inheriting from
+``Person``.
+
+.. literalinclude:: person.py
+ :lineno-start: 43
+ :lines: 43-46
+
+.. literalinclude:: person.py
+ :lineno-start: 49
+ :lines: 49-52
+
+The ``Person`` class remains unaltered and the ``Boy`` and ``Girl`` classes are
+trivial extensions of it. The types and their QML name are registered with the
+QML engine with ``@QmlElement``.
+
+Notice that the ``host`` and ``guests`` properties in ``BirthdayParty`` still
+take instances of ``Person``.
+
+.. literalinclude:: birthdayparty.py
+ :lineno-start: 26
+ :lines: 26-26
+
+.. literalinclude:: birthdayparty.py
+ :lineno-start: 46
+ :lines: 46-46
+
+The implementation of the ``Person`` class itself has not been changed.
+However, as the ``Person`` class was repurposed as a common base for ``Boy``
+and ``Girl``, ``Person`` should no longer be instantiable from QML directly. An
+explicit ``Boy`` or ``Girl`` should be instantiated instead.
+
+.. literalinclude:: person.py
+ :lineno-start: 13
+ :lines: 13-15
+
+While we want to disallow instantiating ``Person`` from within QML, it still
+needs to be registered with the QML engine so that it can be used as a property
+type and other types can be coerced to it. This is what the ``@QmlUncreatable``
+macro does. 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``.
+
+With these changes in place, we can now specify the birthday party with the
+extra information about the attendees as follows.
+
+.. literalinclude:: People/Main.qml
+ :lineno-start: 6
+ :lines: 6-16
diff --git a/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/main.py b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/main.py
new file mode 100644
index 000000000..cc77e2b40
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/main.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the
+ qml/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion example
+ from Qt v6.x"""
+
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QCoreApplication
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+
+from person import Boy, Girl # noqa: F401
+from birthdayparty import BirthdayParty # noqa: F401
+
+
+app = QCoreApplication(sys.argv)
+engine = QQmlEngine()
+engine.addImportPath(Path(__file__).parent)
+component = QQmlComponent(engine)
+component.loadFromModule("People", "Main")
+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/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/person.py b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/person.py
new file mode 100644
index 000000000..57e73e6f5
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml-advanced/advanced2-Inheritance-and-coercion/person.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 QObject, Property, Signal
+from PySide6.QtQml import QmlElement, QmlUncreatable
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "People"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlUncreatable("Person is an abstract base class.")
+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, final=True)
+ 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, final=True)
+ 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)