aboutsummaryrefslogtreecommitdiffstats
path: root/examples/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'examples/declarative')
-rw-r--r--examples/declarative/editingmodel/MovingRectangle.qml115
-rw-r--r--examples/declarative/editingmodel/doc/editingmodel.rst14
-rw-r--r--examples/declarative/editingmodel/doc/qabstractlistmodelqml.pngbin0 -> 45810 bytes
-rw-r--r--examples/declarative/editingmodel/main.py59
-rw-r--r--examples/declarative/editingmodel/main.pyproject3
-rw-r--r--examples/declarative/editingmodel/main.qml143
-rw-r--r--examples/declarative/editingmodel/model.py187
-rw-r--r--examples/declarative/openglunderqml/doc/openglunderqml.rst21
-rw-r--r--examples/declarative/openglunderqml/doc/squircle.pngbin0 -> 37963 bytes
-rw-r--r--examples/declarative/openglunderqml/main.py66
-rw-r--r--examples/declarative/openglunderqml/main.qml86
-rw-r--r--examples/declarative/openglunderqml/openglunderqml.pyproject3
-rw-r--r--examples/declarative/openglunderqml/squircle.py107
-rw-r--r--examples/declarative/openglunderqml/squirclerenderer.py141
-rw-r--r--examples/declarative/stringlistmodel/doc/stringlistmodel.pngbin79 -> 1978 bytes
-rw-r--r--examples/declarative/textproperties/doc/textproperties.rst2
16 files changed, 946 insertions, 1 deletions
diff --git a/examples/declarative/editingmodel/MovingRectangle.qml b/examples/declarative/editingmodel/MovingRectangle.qml
new file mode 100644
index 000000000..0d835af1c
--- /dev/null
+++ b/examples/declarative/editingmodel/MovingRectangle.qml
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+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/declarative/editingmodel/doc/editingmodel.rst b/examples/declarative/editingmodel/doc/editingmodel.rst
new file mode 100644
index 000000000..d76bebc22
--- /dev/null
+++ b/examples/declarative/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/declarative/editingmodel/doc/qabstractlistmodelqml.png b/examples/declarative/editingmodel/doc/qabstractlistmodelqml.png
new file mode 100644
index 000000000..6e181fba1
--- /dev/null
+++ b/examples/declarative/editingmodel/doc/qabstractlistmodelqml.png
Binary files differ
diff --git a/examples/declarative/editingmodel/main.py b/examples/declarative/editingmodel/main.py
new file mode 100644
index 000000000..6aee0d224
--- /dev/null
+++ b/examples/declarative/editingmodel/main.py
@@ -0,0 +1,59 @@
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import sys
+from pathlib import Path
+
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType
+
+from model import BaseModel
+
+if __name__ == "__main__":
+ app = QGuiApplication(sys.argv)
+ qmlRegisterType(BaseModel, "BaseModel", 1, 0, "BaseModel")
+ 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/declarative/editingmodel/main.pyproject b/examples/declarative/editingmodel/main.pyproject
new file mode 100644
index 000000000..71272a973
--- /dev/null
+++ b/examples/declarative/editingmodel/main.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["model.py","main.qml","main.py","MovingRectangle.qml"]
+}
diff --git a/examples/declarative/editingmodel/main.qml b/examples/declarative/editingmodel/main.qml
new file mode 100644
index 000000000..8624be6cf
--- /dev/null
+++ b/examples/declarative/editingmodel/main.qml
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+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/declarative/editingmodel/model.py b/examples/declarative/editingmodel/model.py
new file mode 100644
index 000000000..99736e714
--- /dev/null
+++ b/examples/declarative/editingmodel/model.py
@@ -0,0 +1,187 @@
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+
+from PySide6.QtCore import (QAbstractListModel, QByteArray, QModelIndex, Qt,
+ Slot)
+from PySide6.QtGui import QColor
+
+
+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/declarative/openglunderqml/doc/openglunderqml.rst b/examples/declarative/openglunderqml/doc/openglunderqml.rst
new file mode 100644
index 000000000..6a89a99d9
--- /dev/null
+++ b/examples/declarative/openglunderqml/doc/openglunderqml.rst
@@ -0,0 +1,21 @@
+OpenGL under QML Squircle
+=========================
+
+The OpenGL under QML example shows how an application can make use of the
+QQuickWindow::beforeRendering() signal to draw custom OpenGL content under a Qt
+Quick scene. This signal is emitted at the start of every frame, before the
+scene graph starts its rendering, thus any OpenGL draw calls that are made as
+a response to this signal, will stack under the Qt Quick items.
+
+As an alternative, applications that wish to render OpenGL content on top of
+the Qt Quick scene, can do so by connecting to the
+QQuickWindow::afterRendering() signal.
+
+In this example, we will also see how it is possible to have values that are
+exposed to QML which affect the OpenGL rendering. We animate the threshold
+value using a NumberAnimation in the QML file and this value is used by the
+OpenGL shader program that draws the squircles.
+
+.. image:: squircle.png
+ :width: 400
+ :alt: Squircle Screenshot
diff --git a/examples/declarative/openglunderqml/doc/squircle.png b/examples/declarative/openglunderqml/doc/squircle.png
new file mode 100644
index 000000000..c099a6b7e
--- /dev/null
+++ b/examples/declarative/openglunderqml/doc/squircle.png
Binary files differ
diff --git a/examples/declarative/openglunderqml/main.py b/examples/declarative/openglunderqml/main.py
new file mode 100644
index 000000000..26e059f93
--- /dev/null
+++ b/examples/declarative/openglunderqml/main.py
@@ -0,0 +1,66 @@
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import sys
+from pathlib import Path
+
+from PySide6.QtCore import QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQuick import QQuickView, QQuickWindow, QSGRendererInterface
+
+from squircle import Squircle
+
+if __name__ == "__main__":
+ app = QGuiApplication(sys.argv)
+
+ QQuickWindow.setGraphicsApi(QSGRendererInterface.OpenGLRhi)
+ qmlRegisterType(Squircle, "OpenGLUnderQML", 1, 0, "Squircle")
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qml_file = Path(__file__).parent / "main.qml"
+ view.setSource(QUrl.fromLocalFile(qml_file))
+
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+
+ sys.exit(app.exec())
diff --git a/examples/declarative/openglunderqml/main.qml b/examples/declarative/openglunderqml/main.qml
new file mode 100644
index 000000000..7edcf523b
--- /dev/null
+++ b/examples/declarative/openglunderqml/main.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import OpenGLUnderQML
+
+Item {
+
+ width: 320
+ height: 480
+
+ Squircle {
+ SequentialAnimation on t {
+ NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
+ NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
+ loops: Animation.Infinite
+ running: true
+ }
+ }
+ Rectangle {
+ color: Qt.rgba(1, 1, 1, 0.7)
+ radius: 10
+ border.width: 1
+ border.color: "white"
+ anchors.fill: label
+ anchors.margins: -10
+ }
+
+ Text {
+ id: label
+ color: "black"
+ wrapMode: Text.WordWrap
+ text: "The background here is a squircle rendered with raw OpenGL using the 'beforeRender()' signal in QQuickWindow. This text label and its border is rendered using QML"
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+ }
+}
diff --git a/examples/declarative/openglunderqml/openglunderqml.pyproject b/examples/declarative/openglunderqml/openglunderqml.pyproject
new file mode 100644
index 000000000..e7cfbc570
--- /dev/null
+++ b/examples/declarative/openglunderqml/openglunderqml.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": [ "main.py", "main.qml", "squircle.py", "squirclerenderer.py"]
+}
diff --git a/examples/declarative/openglunderqml/squircle.py b/examples/declarative/openglunderqml/squircle.py
new file mode 100644
index 000000000..8d2cbca84
--- /dev/null
+++ b/examples/declarative/openglunderqml/squircle.py
@@ -0,0 +1,107 @@
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from PySide6.QtCore import Property, QRunnable, Qt, Signal, Slot
+from PySide6.QtQuick import QQuickItem, QQuickWindow
+
+from squirclerenderer import SquircleRenderer
+
+
+class CleanupJob(QRunnable):
+ def __init__(self, renderer):
+ super().__init__()
+ self._renderer = renderer
+
+ def run(self):
+ del self._renderer
+
+
+class Squircle(QQuickItem):
+
+ tChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._t = 0.0
+ self._renderer = None
+ self.windowChanged.connect(self.handleWindowChanged)
+
+ def t(self):
+ return self._t
+
+ def setT(self, value):
+ if self._t == value:
+ return
+ self._t = value
+ self.tChanged.emit()
+ if self.window():
+ self.window().update()
+
+ @Slot(QQuickWindow)
+ def handleWindowChanged(self, win):
+ if win:
+ win.beforeSynchronizing.connect(self.sync, type=Qt.DirectConnection)
+ win.sceneGraphInvalidated.connect(self.cleanup, type=Qt.DirectConnection)
+ win.setColor(Qt.black)
+ self.sync()
+
+ def cleanup(self):
+ del self._renderer
+ self._renderer = None
+
+ @Slot()
+ def sync(self):
+ if not self._renderer:
+ self._renderer = SquircleRenderer()
+ self.window().beforeRendering.connect(self._renderer.init, Qt.DirectConnection)
+ self.window().beforeRenderPassRecording.connect(
+ self._renderer.paint, Qt.DirectConnection
+ )
+ self._renderer.setViewportSize(self.window().size() * self.window().devicePixelRatio())
+ self._renderer.setT(self._t)
+ self._renderer.setWindow(self.window())
+
+ def releaseResources(self):
+ self.window().scheduleRenderJob(
+ CleanupJob(self._renderer), QQuickWindow.BeforeSynchronizingStage
+ )
+ self._renderer = None
+
+ t = Property(float, t, setT, notify=tChanged)
diff --git a/examples/declarative/openglunderqml/squirclerenderer.py b/examples/declarative/openglunderqml/squirclerenderer.py
new file mode 100644
index 000000000..12cd93bb8
--- /dev/null
+++ b/examples/declarative/openglunderqml/squirclerenderer.py
@@ -0,0 +1,141 @@
+#############################################################################
+##
+## Copyright (C) 2021 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from textwrap import dedent
+
+import numpy as np
+from OpenGL.GL import (GL_ARRAY_BUFFER, GL_BLEND, GL_DEPTH_TEST, GL_FLOAT,
+ GL_ONE, GL_SRC_ALPHA, GL_TRIANGLE_STRIP)
+from PySide6.QtCore import QSize, Slot
+from PySide6.QtGui import QOpenGLFunctions
+from PySide6.QtOpenGL import (QOpenGLShader, QOpenGLShaderProgram,
+ QOpenGLVersionProfile)
+from PySide6.QtQuick import QQuickWindow, QSGRendererInterface
+
+VERTEX_SHADER = dedent(
+ """\
+ attribute highp vec4 vertices;
+ varying highp vec2 coords;
+ void main() {
+ gl_Position = vertices;
+ coords = vertices.xy;
+ }
+ """
+)
+FRAGMENT_SHADER = dedent(
+ """\
+ uniform lowp float t;
+ varying highp vec2 coords;
+ void main() {
+ lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));
+ i = smoothstep(t - 0.8, t + 0.8, i);
+ i = floor(i * 20.) / 20.;
+ gl_FragColor = vec4(coords * .5 + .5, i, i);
+ }
+ """
+)
+
+
+class SquircleRenderer(QOpenGLFunctions):
+ def __init__(self):
+ QOpenGLFunctions.__init__(self)
+ self._viewport_size = QSize()
+ self._t = 0.0
+ self._program = None
+ self._window = QQuickWindow()
+ self.profile = QOpenGLVersionProfile()
+ self.gl = None
+
+ def setT(self, t):
+ self._t = t
+
+ def setViewportSize(self, size):
+ self._viewport_size = size
+
+ def setWindow(self, window):
+ self._window = window
+
+ @Slot()
+ def init(self):
+ if not self._program:
+ rif = self._window.rendererInterface()
+ assert (
+ rif.graphicsApi() == QSGRendererInterface.OpenGL
+ or rif.graphicsApi() == QSGRendererInterface.OpenGLRhy
+ )
+ self.initializeOpenGLFunctions()
+ self._program = QOpenGLShaderProgram()
+ self._program.addCacheableShaderFromSourceCode(QOpenGLShader.Vertex, VERTEX_SHADER)
+ self._program.addCacheableShaderFromSourceCode(QOpenGLShader.Fragment, FRAGMENT_SHADER)
+ self._program.bindAttributeLocation("vertices", 0)
+ self._program.link()
+
+ @Slot()
+ def paint(self):
+ # Play nice with the RHI. Not strictly needed when the scenegraph uses
+ # OpenGL directly.
+ self._window.beginExternalCommands()
+
+ self._program.bind()
+
+ self._program.enableAttributeArray(0)
+
+ values = np.array([-1, -1, 1, -1, -1, 1, 1, 1], dtype="single")
+
+ # This example relies on (deprecated) client-side pointers for the vertex
+ # input. Therefore, we have to make sure no vertex buffer is bound.
+ self.glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+ self._program.setAttributeArray(0, GL_FLOAT, values, 2)
+ self._program.setUniformValue1f("t", self._t)
+
+ self.glViewport(0, 0, self._viewport_size.width(), self._viewport_size.height())
+
+ self.glDisable(GL_DEPTH_TEST)
+
+ self.glEnable(GL_BLEND)
+ self.glBlendFunc(GL_SRC_ALPHA, GL_ONE)
+
+ self.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
+
+ self._program.disableAttributeArray(0)
+ self._program.release()
+
+ self._window.endExternalCommands()
diff --git a/examples/declarative/stringlistmodel/doc/stringlistmodel.png b/examples/declarative/stringlistmodel/doc/stringlistmodel.png
index 6058c5930..eeb9b518a 100644
--- a/examples/declarative/stringlistmodel/doc/stringlistmodel.png
+++ b/examples/declarative/stringlistmodel/doc/stringlistmodel.png
Binary files differ
diff --git a/examples/declarative/textproperties/doc/textproperties.rst b/examples/declarative/textproperties/doc/textproperties.rst
index a67e35f0f..81829dfdc 100644
--- a/examples/declarative/textproperties/doc/textproperties.rst
+++ b/examples/declarative/textproperties/doc/textproperties.rst
@@ -4,6 +4,6 @@ Text Properties Example
A Python application that demonstrates how to load a qml file
using Material design, to change the look of text.
-.. image:: scrolling.png
+.. image:: textproperties.png
:width: 400
:alt: Text Properties Screenshot