aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--coin/instructions/common_environment.yaml43
-rw-r--r--coin/instructions_utils.py6
-rw-r--r--coin/module_config.yaml3
-rw-r--r--doc/changelogs/changes-6.10.081
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml6
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml3
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml70
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml54
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml60
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml231
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml2
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml45
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml57
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg3
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/heart.pngbin2664 -> 2318 bytes
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg4
-rw-r--r--examples/bluetooth/heartrate_game/bluetoothbaseclass.py31
-rw-r--r--examples/bluetooth/heartrate_game/devicefinder.py17
-rw-r--r--examples/bluetooth/heartrate_game/devicehandler.py22
-rw-r--r--examples/bluetooth/heartrate_game/deviceinfo.py2
-rw-r--r--examples/bluetooth/heartrate_game/doc/heartrate_game.rst3
-rw-r--r--examples/bluetooth/heartrate_game/heartrate_global.py1
-rw-r--r--examples/bluetooth/heartrate_game/main.py1
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/Charts/App.qml (renamed from examples/qml/tutorials/extending-qml/chapter1-basics/app.qml)8
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/Charts/qmldir4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/basics.py7
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pyproject2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/Charts/App.qml (renamed from examples/qml/tutorials/extending-qml/chapter2-methods/app.qml)8
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/Charts/qmldir4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pyproject2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/methods.py7
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/App.qml (renamed from examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml)8
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/qmldir4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py7
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/App.qml (renamed from examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/qmldir4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/customPropertyTypes.py7
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/App.qml39
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/qmldir4
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml32
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pyproject2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/listproperties.py7
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/App.qml (renamed from examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml)29
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/Charts/plugins.pngbin5014 -> 0 bytes
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst2
-rw-r--r--examples/quick/customitems/painteditem/doc/painteditem.png (renamed from examples/quick/painteditem/doc/painteditem.png)bin3768 -> 3768 bytes
-rw-r--r--examples/quick/customitems/painteditem/doc/painteditem.rst (renamed from examples/quick/painteditem/doc/painteditem.rst)0
-rw-r--r--examples/quick/customitems/painteditem/main.qml (renamed from examples/quick/painteditem/main.qml)0
-rw-r--r--examples/quick/customitems/painteditem/painteditem.py (renamed from examples/quick/painteditem/painteditem.py)0
-rw-r--r--examples/quick/customitems/painteditem/painteditem.pyproject (renamed from examples/quick/painteditem/painteditem.pyproject)0
-rw-r--r--examples/quick/models/objectlistmodel/view.qml16
-rw-r--r--examples/quick/rendercontrol/rendercontrol_opengl/demo.qml8
-rw-r--r--examples/quick/scenegraph/openglunderqml/main.qml2
-rw-r--r--examples/quick/scenegraph/scenegraph_customgeometry/main.qml4
-rw-r--r--examples/quick/window/Splash.qml19
-rw-r--r--examples/quick/window/rc_window.py554
-rw-r--r--examples/quick/window/window.qml46
-rw-r--r--examples/quick/window/window.qrc2
-rw-r--r--examples/quick3d/intro/main.qml8
-rw-r--r--sources/pyside6/doc/_tags/android.rst2
-rw-r--r--sources/pyside6/doc/developer/add_port_example.rst6
-rw-r--r--sources/pyside6/doc/developer/pythonversions.md8
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp14
-rw-r--r--sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py7
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp23
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h6
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.cpp15
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.h4
-rw-r--r--sources/shiboken6/ApiExtractor/classdocumentation.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp4
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.cpp14
-rw-r--r--sources/shiboken6/ApiExtractor/parser/codemodel.h7
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp7
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_container.cpp5
-rw-r--r--sources/shiboken6/libshiboken/sbkbindingutils.cpp1
-rw-r--r--sources/shiboken6/libshiboken/sbkmodule.cpp2
-rw-r--r--tools/sync_examples.py199
82 files changed, 1280 insertions, 655 deletions
diff --git a/coin/instructions/common_environment.yaml b/coin/instructions/common_environment.yaml
index 949eecad3..3ee04a444 100644
--- a/coin/instructions/common_environment.yaml
+++ b/coin/instructions/common_environment.yaml
@@ -328,6 +328,49 @@ instructions:
condition: property
property: host.osVersion
not_in_values: [RHEL_8_6, RHEL_8_8, RHEL_8_10]
+
+ - type: ExecuteCommand
+ command: "pyenv install 3.13.7"
+ maxTimeInSeconds: 14400
+ maxTimeBetweenOutput: 1200
+ ignoreExitCode: true
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: host.osVersion
+ equals_value: MacOS_15
+ - condition: property
+ property: host.arch
+ equals_value: ARM64
+ userMessageOnFailure: >
+ Failed to install python 3.13
+ - type: PrependToEnvironmentVariable
+ variableName: PATH
+ variableValue: "/Users/qt/.pyenv/versions/3.13.7/bin:"
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: host.osVersion
+ equals_value: MacOS_15
+ - condition: property
+ property: host.arch
+ equals_value: ARM64
+ - type: EnvironmentVariable
+ variableName: interpreter
+ variableValue: "python3.13"
+ enable_if:
+ condition: and
+ conditions:
+ - condition: property
+ property: host.osVersion
+ equals_value: MacOS_15
+ - condition: property
+ property: host.arch
+ equals_value: ARM64
+
+
# ToDo: can be removed after 3.11 is available on qt5#3.8 on macOS
# start of ToDo
- type: ExecuteCommand
diff --git a/coin/instructions_utils.py b/coin/instructions_utils.py
index 52c8211e0..0337a0a4c 100644
--- a/coin/instructions_utils.py
+++ b/coin/instructions_utils.py
@@ -148,8 +148,12 @@ def setup_virtualenv(python, exe, env, pip, log, ci):
# Within Ubuntu 24.04 one can't install anything with pip to outside of
# virtual env. Trust that we already have proper virtualenv installed.
if os.environ.get("HOST_OSVERSION_COIN") != "ubuntu_24_04":
+ virtualenv_version = "20.7.2"
+ # 20.7.2 is too old for 3.13
+ if sys.version_info[1] > 12:
+ virtualenv_version = "20.32.0"
run_instruction(
- [str(python), "-m", "pip", "install", "--user", "virtualenv==20.7.2"],
+ [str(python), "-m", "pip", "install", "--user", "virtualenv==" + virtualenv_version],
"Failed to pin virtualenv",
)
# installing to user base might not be in PATH by default.
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index 471c84035..b9a74523b 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -31,6 +31,9 @@ accept_configuration:
- condition: property
property: target.osVersion
not_equals_value: VxWorks
+ - condition: property
+ property: host.osVersion
+ not_equals_value: Windows_11_22H2
- condition: and
conditions:
- condition: property
diff --git a/doc/changelogs/changes-6.10.0 b/doc/changelogs/changes-6.10.0
new file mode 100644
index 000000000..b3e8ea056
--- /dev/null
+++ b/doc/changelogs/changes-6.10.0
@@ -0,0 +1,81 @@
+Qt for Python 6.10.0 is a minor release.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qtforpython/
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+* **************************************************************************
+* PySide6 *
+****************************************************************************
+
+ - [PYSIDE-1735] @QEnum, @QFlag and QMetaEnum now support unsigned 64 bit
+ values for QML usage (with the exception of Qt Widgets
+ Designer), following the support added to Qt.
+ - [PYSIDE-2840] It is now possible to use @QEnum/@QFlag-decorated
+ enumerations as properties of custom widgets in Qt Widgets
+ Designer.
+ - [PYSIDE-2916] The invocation of functions overridden in Python
+ has been optimized for speed.
+ - [PYSIDE-3012] type hints: The annotations of QPropertyAnimation
+ have been fixed.
+ - [PYSIDE-3084] Enumerations are now stored as such instead of an opaque
+ PyObjectWrapper in functions returning QVariant.
+ - [PYSIDE-3137] A warning occurring when doing the first signal connection
+ from a thread has been fixed.
+ - [PYSIDE-3143] A bug causing events to be wrongly converted to
+ QStandardItem has been fixed. Also, a leak of QStandardItem
+ instances returned from QStandardItemModel functions
+ has been fixed.
+ - [PYSIDE-3146] Deployment: Values generated into pysidedeploy.spec are
+ now sorted.
+ - [PYSIDE-3147] Initial adaptations for the upcoming Python version 3.14
+ have been done.
+ - [PYSIDE-3164] type hints: Enum values have been added to the stubs for
+ improved type checking.
+ - [PYSIDE-3178] type hints: The return types of
+ QPoint(F)/QSize(F).toTuple have been fixed.
+ - [QTBUG-110428] The QtExampleIcons module has been removed due to
+ the removal of the underlying library in Qt.
+
+ ***************************************************************************
+* Shiboken6 *
+****************************************************************************
+
+ - Template specializations like "std::optional<int>" can now be specified
+ as primitive types with converter code.
+ - [PYSIDE-2221] Multi-phase Python extension module initialization is now
+ used for the non-deployed case.
+ - [PYSIDE-3011] It is now possible to inject code into the the wrapper
+ class declaration, which can be used to import base class
+ members via the "using" keyword.
+ - [PYSIDE-3105] The support for cross compiling (using the correct target
+ for clang-based parsing) has been improved. Various options
+ have been added to shiboken to be able to specify target
+ platform and compiler.
+ - [PYSIDE-2854] libshiboken: The internal map instances has been changed
+ to be a multimap to improve support for co-located objects.
+ - [PYSIDE-3107] An automatic conversion from T to std::optional<T>
+ has been added (in case std::optional is specified in
+ the type system).
+ - [PYSIDE-3138] A CMake package "Shiboken6Tools" has been introduced to make
+ integrating Shiboken with CMake easier. This significantly
+ reduces the amount of CMake code required by users,
+ replacing the previous method of calling the executable
+ directly with a Python script (`pyside_config.py`).
+ - [PYSIDE-3171] libshiboken's replacement functions providing functions
+ missing from the limited API or appearing in future Python
+ versions have been moved from sbkpython.h (providing a
+ sanitized Python.h) to separate headers sbkpep.h and
+ sbkpepbuffer.h (providing buffer API). This should not
+ affect binding code as the generator includes the new
+ headers, but may require adaption in client code using
+ libshiboken/libpyside directly.
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
index 3687b1331..16b4d32b3 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
@@ -52,7 +52,7 @@ Item {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
- font.pixelSize: GameSettings.mediumFontSize
+ font.pixelSize: GameSettings.smallFontSize
color: GameSettings.textColor
text: root.permissionError
? qsTr("Bluetooth permissions are not granted. Please grant the permissions in the system settings.")
@@ -70,8 +70,8 @@ Item {
Text {
anchors.centerIn: parent
color: GameSettings.textColor
- font.pixelSize: GameSettings.bigFontSize
- text: qsTr("Quit")
+ font.pixelSize: GameSettings.microFontSize
+ text: qsTr("QUIT")
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml b/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
index caebc307e..80fdaa8cd 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
@@ -6,7 +6,6 @@ import QtQuick
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
- width: parent.width * 0.85
+ width: parent.width
height: parent.height * 0.05
- radius: height*0.5
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
index ca8ef2923..ed5fb63d7 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
@@ -16,43 +16,39 @@ GamePage {
errorMessage: deviceFinder.error
infoMessage: deviceFinder.info
+ iconType: deviceFinder.icon
+
+ Text {
+ id: viewCaption
+ anchors {
+ top: parent.top
+ topMargin: GameSettings.fieldMargin + connectPage.messageHeight
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width - GameSettings.fieldMargin * 2
+ height: GameSettings.fieldHeight
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.smallFontSize
+ text: qsTr("Found Devices")
+ }
Rectangle {
id: viewContainer
- anchors.top: parent.top
+ anchors.top: viewCaption.bottom
// only BlueZ platform has address type selection
anchors.bottom: connectPage.connectionHandler.requiresAddressType ? addressTypeButton.top
: searchButton.top
- anchors.topMargin: GameSettings.fieldMargin + connectPage.messageHeight
anchors.bottomMargin: GameSettings.fieldMargin
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - GameSettings.fieldMargin * 2
color: GameSettings.viewColor
radius: GameSettings.buttonRadius
- Text {
- id: title
- width: parent.width
- height: GameSettings.fieldHeight
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- color: GameSettings.textColor
- font.pixelSize: GameSettings.mediumFontSize
- text: qsTr("FOUND DEVICES")
-
- BottomLine {
- height: 1
- width: parent.width
- color: "#898989"
- }
- }
-
ListView {
id: devices
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.top: title.bottom
+ anchors.fill: parent
model: connectPage.deviceFinder.devices
clip: true
@@ -76,22 +72,22 @@ GamePage {
Text {
id: device
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
text: box.modelData.deviceName
anchors.top: parent.top
- anchors.topMargin: parent.height * 0.1
- anchors.leftMargin: parent.height * 0.1
+ anchors.topMargin: parent.height * 0.15
+ anchors.leftMargin: parent.height * 0.15
anchors.left: parent.left
color: GameSettings.textColor
}
Text {
id: deviceAddress
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
text: box.modelData.deviceAddress
anchors.bottom: parent.bottom
- anchors.bottomMargin: parent.height * 0.1
- anchors.rightMargin: parent.height * 0.1
+ anchors.bottomMargin: parent.height * 0.15
+ anchors.rightMargin: parent.height * 0.15
anchors.right: parent.right
color: Qt.darker(GameSettings.textColor)
}
@@ -114,19 +110,19 @@ GamePage {
State {
name: "public"
PropertyChanges {
- addressTypeText.text: qsTr("Public Address")
+ addressTypeText.text: qsTr("PUBLIC ADDRESS")
}
PropertyChanges {
- connectPage.deviceHandler.addressType: DeviceHandler.PUBLIC_ADDRESS
+ connectPage.deviceHandler.addressType: DeviceHandler.PublicAddress
}
},
State {
name: "random"
PropertyChanges {
- addressTypeText.text: qsTr("Random Address")
+ addressTypeText.text: qsTr("RANDOM ADDRESS")
}
PropertyChanges {
- connectPage.deviceHandler.addressType: DeviceHandler.RANDOM_ADDRESS
+ connectPage.deviceHandler.addressType: DeviceHandler.RandomAddress
}
}
]
@@ -134,8 +130,8 @@ GamePage {
Text {
id: addressTypeText
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
- color: GameSettings.textColor
+ font.pixelSize: GameSettings.microFontSize
+ color: GameSettings.textDarkColor
}
}
@@ -151,9 +147,9 @@ GamePage {
Text {
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
+ font.pixelSize: GameSettings.microFontSize
text: qsTr("START SEARCH")
- color: searchButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ color: GameSettings.textDarkColor
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml b/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
index 249f94186..2d592cfdb 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
@@ -11,25 +11,65 @@ Item {
property real messageHeight: msg.height
property bool hasError: errorMessage != ""
property bool hasInfo: infoMessage != ""
+ property int iconType: BluetoothBaseClass.IconNone
+
+ function iconTypeToName(icon: int) : string {
+ switch (icon) {
+ case BluetoothBaseClass.IconNone: return ""
+ case BluetoothBaseClass.IconBluetooth: return "images/bluetooth.svg"
+ case BluetoothBaseClass.IconError: return "images/alert.svg"
+ case BluetoothBaseClass.IconProgress: return "images/progress.svg"
+ case BluetoothBaseClass.IconSearch: return "images/search.svg"
+ }
+ }
Rectangle {
id: msg
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ topMargin: GameSettings.fieldMargin * 0.5
+ leftMargin: GameSettings.fieldMargin
+ rightMargin: GameSettings.fieldMargin
+ }
height: GameSettings.fieldHeight
- color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor
+ radius: GameSettings.buttonRadius
+ color: page.hasError ? GameSettings.errorColor : "transparent"
visible: page.hasError || page.hasInfo
+ border {
+ width: 1
+ color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor
+ }
+
+ Image {
+ id: icon
+ readonly property int imgSize: GameSettings.fieldHeight * 0.5
+ anchors {
+ left: parent.left
+ leftMargin: GameSettings.fieldMargin * 0.5
+ verticalCenter: parent.verticalCenter
+ }
+ visible: source.toString() !== ""
+ source: page.iconTypeToName(page.iconType)
+ sourceSize.width: imgSize
+ sourceSize.height: imgSize
+ fillMode: Image.PreserveAspectFit
+ }
Text {
id: error
- anchors.fill: parent
+ anchors {
+ fill: parent
+ leftMargin: GameSettings.fieldMargin + icon.width
+ rightMargin: GameSettings.fieldMargin + icon.width
+ }
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
minimumPixelSize: 5
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
fontSizeMode: Text.Fit
- color: GameSettings.textColor
+ color: page.hasError ? GameSettings.textColor : GameSettings.infoColor
text: page.hasError ? page.errorMessage : page.infoMessage
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml b/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
index 0fe854609..4032787ce 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
@@ -4,35 +4,49 @@
pragma Singleton
import QtQuick
-Item {
+QtObject {
property int wHeight
property int wWidth
// Colors
- readonly property color backgroundColor: "#2d3037"
- readonly property color buttonColor: "#202227"
- readonly property color buttonPressedColor: "#6ccaf2"
- readonly property color disabledButtonColor: "#555555"
- readonly property color viewColor: "#202227"
- readonly property color delegate1Color: Qt.darker(viewColor, 1.2)
- readonly property color delegate2Color: Qt.lighter(viewColor, 1.2)
+ readonly property color lightGreenColor: "#80ebb6"
+ readonly property color backgroundColor: "#2c3038"
+ readonly property color buttonColor: "#2cde85"
+ readonly property color buttonPressedColor: lightGreenColor
+ readonly property color disabledButtonColor: "#808080"
+ readonly property color viewColor: "#262626"
+ readonly property color delegate1Color: "#262626"
+ readonly property color delegate2Color: "#404040"
readonly property color textColor: "#ffffff"
- readonly property color textDarkColor: "#232323"
- readonly property color disabledTextColor: "#777777"
- readonly property color sliderColor: "#6ccaf2"
+ readonly property color textDarkColor: "#0d0d0d"
+ readonly property color textInfoColor: lightGreenColor
+ readonly property color sliderColor: "#00414a"
+ readonly property color sliderBorderColor: lightGreenColor
+ readonly property color sliderTextColor: lightGreenColor
readonly property color errorColor: "#ba3f62"
- readonly property color infoColor: "#3fba62"
+ readonly property color infoColor: lightGreenColor
+ readonly property color titleColor: "#202227"
+ readonly property color selectedTitleColor: "#19545c"
+ readonly property color hoverTitleColor: Qt.rgba(selectedTitleColor.r,
+ selectedTitleColor.g,
+ selectedTitleColor.b,
+ 0.25)
+ readonly property color bottomLineColor: "#e6e6e6"
+ readonly property color heartRateColor: "#f80067"
+
+ // All the fonts are given for the window of certain size.
+ // Resizing the window changes all the fonts accordingly
+ readonly property int defaultSize: 500
+ readonly property real fontScaleFactor: Math.min(wWidth, wHeight) / defaultSize
// Font sizes
- property real microFontSize: hugeFontSize * 0.2
- property real tinyFontSize: hugeFontSize * 0.4
- property real smallTinyFontSize: hugeFontSize * 0.5
- property real smallFontSize: hugeFontSize * 0.6
- property real mediumFontSize: hugeFontSize * 0.7
- property real bigFontSize: hugeFontSize * 0.8
- property real largeFontSize: hugeFontSize * 0.9
- property real hugeFontSize: (wWidth + wHeight) * 0.03
- property real giganticFontSize: (wWidth + wHeight) * 0.04
+ readonly property real microFontSize: 16 * fontScaleFactor
+ readonly property real tinyFontSize: 20 * fontScaleFactor
+ readonly property real smallFontSize: 24 * fontScaleFactor
+ readonly property real mediumFontSize: 32 * fontScaleFactor
+ readonly property real bigFontSize: 36 * fontScaleFactor
+ readonly property real largeFontSize: 54 * fontScaleFactor
+ readonly property real hugeFontSize: 128 * fontScaleFactor
// Some other values
property real fieldHeight: wHeight * 0.08
@@ -41,10 +55,6 @@ Item {
property real buttonRadius: buttonHeight * 0.1
// Some help functions
- function widthForHeight(h, ss) {
- return h / ss.height * ss.width
- }
-
function heightForWidth(w, ss) {
return w / ss.width * ss.height
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
index 48e84e762..04ebeb09a 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
@@ -11,10 +11,15 @@ GamePage {
errorMessage: deviceHandler.error
infoMessage: deviceHandler.info
+ iconType: deviceHandler.icon
property real __timeCounter: 0
property real __maxTimeCount: 60
- property string relaxText: qsTr("Relax!\nWhen you are ready, press Start. You have %1s time to increase heartrate so much as possible.\nGood luck!").arg(__maxTimeCount)
+
+ readonly property string relaxText: qsTr("Relax!")
+ readonly property string startText: qsTr("When you are ready,\npress Start.")
+ readonly property string instructionText: qsTr("You have %1s time to increase heart\nrate as much as possible.").arg(__maxTimeCount)
+ readonly property string goodLuckText: qsTr("Good luck!")
signal showStatsPage
@@ -55,6 +60,10 @@ GamePage {
Rectangle {
id: circle
+
+ readonly property bool hintVisible: !measurePage.deviceHandler.measuring
+ readonly property real innerSpacing: Math.min(width * 0.05, 25)
+
anchors.horizontalCenter: parent.horizontalCenter
width: Math.min(measurePage.width, measurePage.height - GameSettings.fieldHeight * 4)
- 2 * GameSettings.fieldMargin
@@ -63,30 +72,127 @@ GamePage {
color: GameSettings.viewColor
Text {
- id: hintText
- anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height * 0.1
+ id: relaxTextBox
+ anchors {
+ bottom: startTextBox.top
+ bottomMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.6
+ height: parent.height * 0.1
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
- width: parent.width * 0.8
- height: parent.height * 0.6
- wrapMode: Text.WordWrap
text: measurePage.relaxText
- visible: !measurePage.deviceHandler.measuring
+ visible: circle.hintVisible
color: GameSettings.textColor
fontSizeMode: Text.Fit
- minimumPixelSize: 10
- font.pixelSize: GameSettings.mediumFontSize
+ font.pixelSize: GameSettings.smallFontSize
+ font.bold: true
}
Text {
- id: text
- anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height * 0.15
- font.pixelSize: parent.width * 0.45
+ id: startTextBox
+ anchors {
+ bottom: heart.top
+ bottomMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.8
+ height: parent.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.startText
+ visible: circle.hintVisible
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.tinyFontSize
+ }
+
+ Text {
+ id: measureTextBox
+ anchors {
+ bottom: heart.top
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.7
+ height: parent.height * 0.35
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
text: measurePage.deviceHandler.hr
visible: measurePage.deviceHandler.measuring
+ color: GameSettings.heartRateColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.hugeFontSize
+ font.bold: true
+ }
+
+ Image {
+ id: heart
+ anchors.centerIn: circle
+ width: parent.width * 0.2
+ height: width
+ fillMode: Image.PreserveAspectFit
+ source: "images/heart.png"
+ smooth: true
+ antialiasing: true
+
+ SequentialAnimation {
+ id: heartAnim
+ running: measurePage.deviceHandler.measuring
+ loops: Animation.Infinite
+ alwaysRunToEnd: true
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.4
+ duration: 500
+ easing.type: Easing.InQuad
+ }
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.0
+ duration: 500
+ easing.type: Easing.OutQuad
+ }
+ }
+ }
+
+ Text {
+ id: instructionTextBox
+ anchors {
+ top: heart.bottom
+ topMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.8
+ height: parent.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.instructionText
+ visible: circle.hintVisible
color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.tinyFontSize
+ }
+
+ Text {
+ id: goodLuckBox
+ anchors {
+ top: instructionTextBox.bottom
+ topMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.6
+ height: parent.height * 0.1
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.goodLuckText
+ visible: circle.hintVisible
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.smallFontSize
+ font.bold: true
}
Item {
@@ -101,14 +207,22 @@ GamePage {
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
+ width: parent.width * 0.35
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
text: measurePage.deviceHandler.minHR
color: GameSettings.textColor
- font.pixelSize: GameSettings.hugeFontSize
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.largeFontSize
Text {
anchors.left: parent.left
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize * 0.8
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.mediumFontSize
color: parent.color
text: "MIN"
}
@@ -117,51 +231,27 @@ GamePage {
Text {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * 0.35
text: measurePage.deviceHandler.maxHR
color: GameSettings.textColor
- font.pixelSize: GameSettings.hugeFontSize
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.largeFontSize
Text {
anchors.right: parent.right
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize * 0.8
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.mediumFontSize
color: parent.color
text: "MAX"
}
}
}
-
- Image {
- id: heart
- anchors.horizontalCenter: minMaxContainer.horizontalCenter
- anchors.verticalCenter: minMaxContainer.bottom
- width: parent.width * 0.2
- height: width
- source: "images/heart.png"
- smooth: true
- antialiasing: true
-
- SequentialAnimation {
- id: heartAnim
- running: measurePage.deviceHandler.alive
- loops: Animation.Infinite
- alwaysRunToEnd: true
- PropertyAnimation {
- target: heart
- property: "scale"
- to: 1.2
- duration: 500
- easing.type: Easing.InQuad
- }
- PropertyAnimation {
- target: heart
- property: "scale"
- to: 1.0
- duration: 500
- easing.type: Easing.OutQuad
- }
- }
- }
}
Rectangle {
@@ -171,21 +261,43 @@ GamePage {
width: circle.width
height: GameSettings.fieldHeight
radius: GameSettings.buttonRadius
+ border {
+ width: 1
+ color: GameSettings.sliderBorderColor
+ }
Rectangle {
- height: parent.height
+ anchors {
+ top: parent.top
+ topMargin: parent.border.width
+ left: parent.left
+ leftMargin: parent.border.width
+ }
+ height: parent.height - 2 * parent.border.width
+ width: Math.min(1.0, measurePage.__timeCounter / measurePage.__maxTimeCount)
+ * (parent.width - 2 * parent.border.width)
radius: parent.radius
color: GameSettings.sliderColor
- width: Math.min(
- 1.0,
- measurePage.__timeCounter / measurePage.__maxTimeCount) * parent.width
+ }
+
+ Image {
+ readonly property int imgSize: GameSettings.fieldHeight * 0.5
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: parent.left
+ leftMargin: GameSettings.fieldMargin * 0.5
+ }
+ source: "images/clock.svg"
+ sourceSize.width: imgSize
+ sourceSize.height: imgSize
+ fillMode: Image.PreserveAspectFit
}
Text {
anchors.centerIn: parent
- color: "gray"
+ color: GameSettings.sliderTextColor
text: (measurePage.__maxTimeCount - measurePage.__timeCounter).toFixed(0) + " s"
- font.pixelSize: GameSettings.bigFontSize
+ font.pixelSize: GameSettings.smallFontSize
}
}
}
@@ -197,16 +309,17 @@ GamePage {
anchors.bottomMargin: GameSettings.fieldMargin
width: circle.width
height: GameSettings.fieldHeight
- enabled: !measurePage.deviceHandler.measuring
+ enabled: measurePage.deviceHandler.alive && !measurePage.deviceHandler.measuring
+ && measurePage.errorMessage === ""
radius: GameSettings.buttonRadius
onClicked: measurePage.start()
Text {
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
+ font.pixelSize: GameSettings.microFontSize
text: qsTr("START")
- color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ color: GameSettings.textDarkColor
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml b/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
index 2f9ac1b3f..918319d78 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
@@ -23,7 +23,7 @@ Item {
Timer {
id: splashTimer
interval: 1000
- onTriggered: splashIsReady = true
+ onTriggered: root.splashIsReady = true
}
Component.onCompleted: splashTimer.start()
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
index 22cdd5365..87487c944 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
@@ -13,20 +13,45 @@ GamePage {
anchors.centerIn: parent
width: parent.width
- Text {
+ Rectangle {
+ id: resultRect
anchors.horizontalCenter: parent.horizontalCenter
- font.pixelSize: GameSettings.hugeFontSize
- color: GameSettings.textColor
- text: qsTr("RESULT")
- }
+ width: height
+ height: statsPage.height / 2 - GameSettings.fieldHeight
+ radius: height / 2
+ color: GameSettings.viewColor
- Text {
- anchors.horizontalCenter: parent.horizontalCenter
- font.pixelSize: GameSettings.giganticFontSize * 3
- color: GameSettings.textColor
- text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0)
+ Column {
+ anchors.centerIn: parent
+
+ Text {
+ id: resultCaption
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: resultRect.width * 0.8
+ height: resultRect.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.bigFontSize
+ color: GameSettings.textColor
+ text: qsTr("RESULT")
+ }
+
+ Text {
+ id: resultValue
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: resultRect.width * 0.8
+ height: resultRect.height * 0.4
+ horizontalAlignment: Text.AlignHCenter
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.hugeFontSize
+ font.bold: true
+ color: GameSettings.heartRateColor
+ text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0)
+ }
+ }
}
+
Item {
height: GameSettings.fieldHeight
width: 1
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml b/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
index 016a44358..ccec76089 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
@@ -13,42 +13,51 @@ Rectangle {
signal titleClicked(int index)
height: GameSettings.fieldHeight
- color: GameSettings.viewColor
+ color: GameSettings.titleColor
+
+ Rectangle {
+ anchors.bottom: parent.bottom
+ width: parent.width / 3
+ height: parent.height
+ x: titleBar.currentIndex * width
+ color: GameSettings.selectedTitleColor
+
+ BottomLine {
+ color: GameSettings.bottomLineColor
+ }
+
+ Behavior on x {
+ NumberAnimation {
+ duration: 200
+ }
+ }
+ }
Repeater {
model: 3
- Text {
+ Rectangle {
id: caption
required property int index
+ property bool hoveredOrPressed: mouseArea.pressed || mouseArea.containsMouse
width: titleBar.width / 3
height: titleBar.height
x: index * width
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- text: titleBar.__titles[index]
- font.pixelSize: GameSettings.tinyFontSize
- color: titleBar.currentIndex === index ? GameSettings.textColor
- : GameSettings.disabledTextColor
-
+ color: (titleBar.currentIndex !== index) && hoveredOrPressed
+ ? GameSettings.hoverTitleColor : "transparent"
+ Text {
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: titleBar.__titles[caption.index]
+ font.pixelSize: GameSettings.microFontSize
+ color: GameSettings.textColor
+ }
MouseArea {
+ id: mouseArea
anchors.fill: parent
+ hoverEnabled: true
onClicked: titleBar.titleClicked(caption.index)
}
}
}
-
- Item {
- anchors.bottom: parent.bottom
- width: parent.width / 3
- height: parent.height
- x: titleBar.currentIndex * width
-
- BottomLine {}
-
- Behavior on x {
- NumberAnimation {
- duration: 200
- }
- }
- }
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg
new file mode 100644
index 000000000..c48c10e6b
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4ZM12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2Z" fill="white"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 13C11.4477 13 11 12.5523 11 12V8C11 7.44772 11.4477 7 12 7C12.5523 7 13 7.44772 13 8V12C13 12.5523 12.5523 13 12 13ZM12 15C12.5523 15 13 15.4477 13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15Z" fill="white"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg
new file mode 100644
index 000000000..6d01b28ff
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1869 2.24413C11.4926 2.11749 11.8445 2.18749 12.0785 2.42149L16.5785 6.92149C16.8981 7.24101 16.8981 7.75905 16.5785 8.07857L12.6571 12L16.5785 15.9215C16.8981 16.241 16.8981 16.7591 16.5785 17.0786L12.0785 21.5786C11.8445 21.8126 11.4926 21.8826 11.1869 21.7559C10.8812 21.6293 10.6818 21.331 10.6818 21V13.9753L7.57855 17.0786C7.25903 17.3981 6.74098 17.3981 6.42146 17.0786C6.10194 16.7591 6.10194 16.241 6.42146 15.9215L10.3429 12L6.42146 8.07857C6.10194 7.75905 6.10194 7.24101 6.42146 6.92149C6.74098 6.60197 7.25903 6.60197 7.57855 6.92149L10.6818 10.0248V3.00003C10.6818 2.66911 10.8812 2.37077 11.1869 2.24413ZM12.3182 13.9753L14.8429 16.5L12.3182 19.0248V13.9753ZM12.3182 10.0248V4.9753L14.8429 7.50003L12.3182 10.0248Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg
new file mode 100644
index 000000000..655996bab
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8 20H16V17C16 15.9 15.6083 14.9583 14.825 14.175C14.0417 13.3917 13.1 13 12 13C10.9 13 9.95833 13.3917 9.175 14.175C8.39167 14.9583 8 15.9 8 17V20ZM12 11C13.1 11 14.0417 10.6083 14.825 9.825C15.6083 9.04167 16 8.1 16 7V4H8V7C8 8.1 8.39167 9.04167 9.175 9.825C9.95833 10.6083 10.9 11 12 11ZM5 22C4.44772 22 4 21.5523 4 21C4 20.4477 4.44772 20 5 20H6V17C6 15.9833 6.2375 15.0292 6.7125 14.1375C7.1875 13.2458 7.85 12.5333 8.7 12C7.85 11.4667 7.1875 10.7542 6.7125 9.8625C6.2375 8.97083 6 8.01667 6 7V4H5C4.44772 4 4 3.55228 4 3C4 2.44772 4.44772 2 5 2H19C19.5523 2 20 2.44772 20 3C20 3.55228 19.5523 4 19 4H18V7C18 8.01667 17.7625 8.97083 17.2875 9.8625C16.8125 10.7542 16.15 11.4667 15.3 12C16.15 12.5333 16.8125 13.2458 17.2875 14.1375C17.7625 15.0292 18 15.9833 18 17V20H19C19.5523 20 20 20.4477 20 21C20 21.5523 19.5523 22 19 22H5Z" fill="#80EBB6"/>
+<path d="M17 22H7L7 18C7 15.2386 9.23858 13 12 13C14.7614 13 17 15.2386 17 18V22Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png b/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
index f2b3c0a3e..4ba0f822d 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
Binary files differ
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg
new file mode 100644
index 000000000..449fe5e73
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M19 11C19 11.5523 19.4477 12 20 12C20.5523 12 21 11.5523 21 11V10.8478C21 8.11075 19.7088 5.53404 17.5163 3.89561C17.0739 3.56501 16.4472 3.65565 16.1166 4.09805C15.786 4.54046 15.8767 5.1671 16.3191 5.4977C18.0064 6.75857 19 8.74149 19 10.8478V11ZM4 12C4.55228 12 5 11.5523 5 11V10.8478C5 8.74149 5.99363 6.75857 7.68091 5.4977C8.12331 5.1671 8.21395 4.54046 7.88335 4.09805C7.55275 3.65565 6.92611 3.56501 6.4837 3.89561C4.29117 5.53404 3 8.11075 3 10.8478V11C3 11.5523 3.44772 12 4 12ZM7.10555 19.5528C7.35253 19.0588 7.95321 18.8586 8.44719 19.1055C10.6837 20.2238 13.3162 20.2238 15.5528 19.1056C16.0467 18.8586 16.6474 19.0588 16.8944 19.5528C17.1414 20.0468 16.9412 20.6474 16.4472 20.8944C13.6476 22.2942 10.3523 22.2942 7.55276 20.8944C7.05878 20.6474 6.85856 20.0467 7.10555 19.5528Z" fill="#80EBB6"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13 5C13 5.55228 12.5523 6 12 6C11.4477 6 11 5.55228 11 5C11 4.44772 11.4477 4 12 4C12.5523 4 13 4.44772 13 5ZM15 5C15 6.65685 13.6569 8 12 8C10.3431 8 9 6.65685 9 5C9 3.34315 10.3431 2 12 2C13.6569 2 15 3.34315 15 5ZM5 17C5.55228 17 6 16.5523 6 16C6 15.4477 5.55228 15 5 15C4.44772 15 4 15.4477 4 16C4 16.5523 4.44772 17 5 17ZM5 19C6.65685 19 8 17.6569 8 16C8 14.3431 6.65685 13 5 13C3.34315 13 2 14.3431 2 16C2 17.6569 3.34315 19 5 19ZM19 17C19.5523 17 20 16.5523 20 16C20 15.4477 19.5523 15 19 15C18.4477 15 18 15.4477 18 16C18 16.5523 18.4477 17 19 17ZM19 19C20.6569 19 22 17.6569 22 16C22 14.3431 20.6569 13 19 13C17.3431 13 16 14.3431 16 16C16 17.6569 17.3431 19 19 19Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg
new file mode 100644
index 000000000..9af5fe4d7
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.2929 14.2929C14.6834 13.9024 15.3166 13.9024 15.7071 14.2929L21.7071 20.2929C22.0976 20.6834 22.0976 21.3166 21.7071 21.7071C21.3166 22.0976 20.6834 22.0976 20.2929 21.7071L14.2929 15.7071C13.9024 15.3166 13.9024 14.6834 14.2929 14.2929Z" fill="#80EBB6"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10 4C6.68629 4 4 6.68629 4 10C4 13.3137 6.68629 16 10 16C13.3137 16 16 13.3137 16 10C16 6.68629 13.3137 4 10 4ZM2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/bluetoothbaseclass.py b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
index 6278b0418..7f4c5a5b4 100644
--- a/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
+++ b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
@@ -2,18 +2,36 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
-from PySide6.QtCore import QObject, Property, Signal, Slot
+from enum import IntEnum
+from PySide6.QtQml import QmlElement, QmlUncreatable
+from PySide6.QtCore import QObject, Property, Signal, Slot, QEnum
+QML_IMPORT_NAME = "HeartRateGame"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlUncreatable("BluetoothBaseClass is not intended to be created directly")
class BluetoothBaseClass(QObject):
+ @QEnum
+ class IconType(IntEnum):
+ IconNone = 0
+ IconBluetooth = 1
+ IconError = 2
+ IconProgress = 3
+ IconSearch = 4
+
errorChanged = Signal()
infoChanged = Signal()
+ iconChanged = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.m_error = ""
self.m_info = ""
+ self.m_icon = BluetoothBaseClass.IconType.IconNone
@Property(str, notify=errorChanged)
def error(self):
@@ -35,7 +53,18 @@ class BluetoothBaseClass(QObject):
self.m_info = i
self.infoChanged.emit()
+ @Property(int, notify=iconChanged)
+ def icon(self):
+ return self.m_icon
+
+ @icon.setter
+ def icon(self, i):
+ if self.m_icon != i:
+ self.m_icon = i
+ self.iconChanged.emit()
+
@Slot()
def clearMessages(self):
self.info = ""
self.error = ""
+ self.icon = BluetoothBaseClass.IconType.IconNone
diff --git a/examples/bluetooth/heartrate_game/devicefinder.py b/examples/bluetooth/heartrate_game/devicefinder.py
index 5c00e7c94..932f2bb4c 100644
--- a/examples/bluetooth/heartrate_game/devicefinder.py
+++ b/examples/bluetooth/heartrate_game/devicefinder.py
@@ -5,7 +5,7 @@ import sys
from PySide6.QtBluetooth import (QBluetoothDeviceDiscoveryAgent,
QBluetoothDeviceInfo)
-from PySide6.QtQml import QmlElement
+from PySide6.QtQml import QmlElement, QmlUncreatable
from PySide6.QtCore import QTimer, Property, Signal, Slot, Qt
from bluetoothbaseclass import BluetoothBaseClass
@@ -22,6 +22,7 @@ QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
+@QmlUncreatable("This class is not intended to be created directly")
class DeviceFinder(BluetoothBaseClass):
scanningChanged = Signal()
@@ -57,6 +58,7 @@ class DeviceFinder(BluetoothBaseClass):
qApp.requestPermission(permission, self, self.startSearch) # noqa: F82 1
return
elif permission_status == Qt.PermissionStatus.Denied:
+ self.icon = BluetoothBaseClass.IconType.IconError
return
elif permission_status == Qt.PermissionStatus.Granted:
print("[HeartRateGame] Bluetooth Permission Granted")
@@ -75,6 +77,7 @@ class DeviceFinder(BluetoothBaseClass):
#! [devicediscovery-2]
self.scanningChanged.emit()
self.info = "Scanning for devices..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
#! [devicediscovery-3]
@Slot(QBluetoothDeviceInfo)
@@ -83,6 +86,7 @@ class DeviceFinder(BluetoothBaseClass):
if device.coreConfigurations() & QBluetoothDeviceInfo.LowEnergyCoreConfiguration:
self.m_devices.append(DeviceInfo(device))
self.info = "Low Energy device found. Scanning more..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
#! [devicediscovery-3]
self.devicesChanged.emit()
#! [devicediscovery-4]
@@ -97,6 +101,7 @@ class DeviceFinder(BluetoothBaseClass):
self.error = "Writing or reading from the device resulted in an error."
else:
self.error = "An unknown error has occurred."
+ self.icon = BluetoothBaseClass.IconType.IconError
@Slot()
def scanFinished(self):
@@ -107,12 +112,20 @@ class DeviceFinder(BluetoothBaseClass):
if self.m_devices:
self.info = "Scanning done."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
else:
self.error = "No Low Energy devices found."
+ self.icon = BluetoothBaseClass.IconType.IconError
self.scanningChanged.emit()
self.devicesChanged.emit()
+ @Slot()
+ def resetMessages(self):
+ self.error = ""
+ self.info = "Start search to find devices"
+ self.icon = BluetoothBaseClass.IconType.IconSearch
+
@Slot(str)
def connectToService(self, address):
self.m_deviceDiscoveryAgent.stop()
@@ -127,7 +140,7 @@ class DeviceFinder(BluetoothBaseClass):
if currentDevice:
self.m_deviceHandler.setDevice(currentDevice)
- self.clearMessages()
+ self.resetMessages()
@Property(bool, notify=scanningChanged)
def scanning(self):
diff --git a/examples/bluetooth/heartrate_game/devicehandler.py b/examples/bluetooth/heartrate_game/devicehandler.py
index 8599c0296..f10c052be 100644
--- a/examples/bluetooth/heartrate_game/devicehandler.py
+++ b/examples/bluetooth/heartrate_game/devicehandler.py
@@ -69,31 +69,37 @@ class DeviceHandler(BluetoothBaseClass):
self.m_demoTimer.start()
self.updateDemoHR()
- @Property(int)
def addressType(self):
if self.m_addressType == QLowEnergyController.RemoteAddressType.RandomAddress:
return DeviceHandler.AddressType.RANDOM_ADDRESS
return DeviceHandler.AddressType.PUBLIC_ADDRESS
- @addressType.setter
- def addressType(self, type):
+ @Slot(int)
+ def setAddressType(self, type):
if type == DeviceHandler.AddressType.PUBLIC_ADDRESS:
self.m_addressType = QLowEnergyController.RemoteAddressType.PublicAddress
elif type == DeviceHandler.AddressType.RANDOM_ADDRESS:
self.m_addressType = QLowEnergyController.RemoteAddressType.RandomAddress
+ @Slot()
+ def resetAddressType(self):
+ self.m_addressType = QLowEnergyController.RemoteAddressType.PublicAddress
+
@Slot(QLowEnergyController.Error)
def controllerErrorOccurred(self, device):
self.error = "Cannot connect to remote device."
+ self.icon = BluetoothBaseClass.IconType.IconError
@Slot()
def controllerConnected(self):
self.info = "Controller connected. Search services..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
self.m_control.discoverServices()
@Slot()
def controllerDisconnected(self):
self.error = "LowEnergy controller disconnected"
+ self.icon = BluetoothBaseClass.IconType.IconError
def setDevice(self, device):
self.clearMessages()
@@ -101,6 +107,7 @@ class DeviceHandler(BluetoothBaseClass):
if simulator():
self.info = "Demo device connected."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
return
# Disconnect and delete old connection
@@ -152,6 +159,7 @@ class DeviceHandler(BluetoothBaseClass):
def serviceDiscovered(self, gatt):
if gatt == QBluetoothUuid(QBluetoothUuid.ServiceClassUuid.HeartRate):
self.info = "Heart Rate service discovered. Waiting for service scan to be done..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
self.m_foundHeartRateService = True
#! [Filter HeartRate service 1]
@@ -159,6 +167,7 @@ class DeviceHandler(BluetoothBaseClass):
@Slot()
def serviceScanDone(self):
self.info = "Service scan done."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
# Delete old service if available
if self.m_service:
@@ -177,6 +186,8 @@ class DeviceHandler(BluetoothBaseClass):
self.m_service.discoverDetails()
else:
self.error = "Heart Rate Service not found."
+ self.icon = BluetoothBaseClass.IconType.IconError
+
#! [Filter HeartRate service 2]
# Service functions
@@ -185,8 +196,10 @@ class DeviceHandler(BluetoothBaseClass):
def serviceStateChanged(self, switch):
if switch == QLowEnergyService.RemoteServiceDiscovering:
self.info = "Discovering services..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
elif switch == QLowEnergyService.RemoteServiceDiscovered:
self.info = "Service discovered."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
hrChar = self.m_service.characteristic(
QBluetoothUuid(QBluetoothUuid.CharacteristicType.HeartRateMeasurement))
if hrChar.isValid():
@@ -197,6 +210,7 @@ class DeviceHandler(BluetoothBaseClass):
QByteArray.fromHex(b"0100"))
else:
self.error = "HR Data not found."
+ self.icon = BluetoothBaseClass.IconType.IconError
self.aliveChanged.emit()
#! [Find HRM characteristic]
@@ -308,3 +322,5 @@ class DeviceHandler(BluetoothBaseClass):
+ (0.2017 * 24)) / 4.184) * 60 * self.time / 3600
self.statsChanged.emit()
+
+ addressType = Property(int, addressType, setAddressType, freset=resetAddressType)
diff --git a/examples/bluetooth/heartrate_game/deviceinfo.py b/examples/bluetooth/heartrate_game/deviceinfo.py
index 136bbbacb..60cdb5aaf 100644
--- a/examples/bluetooth/heartrate_game/deviceinfo.py
+++ b/examples/bluetooth/heartrate_game/deviceinfo.py
@@ -27,7 +27,7 @@ class DeviceInfo(QObject):
@Property(str, notify=deviceChanged)
def deviceName(self):
if simulator():
- return "Demo device"
+ return "Demo BT device"
return self.m_device.name()
@Property(str, notify=deviceChanged)
diff --git a/examples/bluetooth/heartrate_game/doc/heartrate_game.rst b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
index 9d190d991..1704e32d8 100644
--- a/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
+++ b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
@@ -9,3 +9,6 @@ application covers the scanning for Bluetooth Low Energy devices,
connecting to a Heart Rate service on the device, writing
characteristics and descriptors, and receiving updates from the device
once the heart rate has changed.
+
+The command line option `--simulator` can be used to run the example against a
+demo server in case no Bluetooth hardware is available.
diff --git a/examples/bluetooth/heartrate_game/heartrate_global.py b/examples/bluetooth/heartrate_game/heartrate_global.py
index 384eb93a7..75a0b42b8 100644
--- a/examples/bluetooth/heartrate_game/heartrate_global.py
+++ b/examples/bluetooth/heartrate_game/heartrate_global.py
@@ -8,7 +8,6 @@ _simulator = False
def simulator():
- global _simulator
return _simulator
diff --git a/examples/bluetooth/heartrate_game/main.py b/examples/bluetooth/heartrate_game/main.py
index 00df7de6a..a70b9f349 100644
--- a/examples/bluetooth/heartrate_game/main.py
+++ b/examples/bluetooth/heartrate_game/main.py
@@ -15,6 +15,7 @@ from PySide6.QtCore import QCoreApplication, QLoggingCategory
from connectionhandler import ConnectionHandler
from devicefinder import DeviceFinder
from devicehandler import DeviceHandler
+from bluetoothbaseclass import BluetoothBaseClass # noqa: F401
from heartrate_global import set_simulator
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml b/examples/qml/tutorials/extending-qml/chapter1-basics/Charts/App.qml
index 6feef5633..523dc7128 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/Charts/App.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import Charts
@@ -16,11 +16,7 @@ Item {
}
Text {
- anchors {
- bottom: parent.bottom;
- horizontalCenter: parent.horizontalCenter;
- bottomMargin: 20
- }
+ anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: aPieChart.name
}
}
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/Charts/qmldir b/examples/qml/tutorials/extending-qml/chapter1-basics/Charts/qmldir
new file mode 100644
index 000000000..78602c6b4
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/Charts/qmldir
@@ -0,0 +1,4 @@
+module Charts
+typeinfo chapter1-basics.qmltypes
+depends QtQuick
+App 254.0 App.qml
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/basics.py b/examples/qml/tutorials/extending-qml/chapter1-basics/basics.py
index 322bef954..08fa91c14 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/basics.py
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/basics.py
@@ -4,11 +4,10 @@ from __future__ import annotations
"""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.QtCore import Property, Signal
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement
from PySide6.QtQuick import QQuickPaintedItem, QQuickView
@@ -57,8 +56,8 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
- qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
- view.setSource(QUrl.fromLocalFile(qml_file))
+ view.engine().addImportPath(Path(__file__).parent)
+ view.loadFromModule("Charts", "App")
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
diff --git a/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pyproject b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pyproject
index 869556bb8..2207b8344 100644
--- a/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pyproject
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["basics.py", "app.qml"]
+ "files": ["basics.py", "Charts/App.qml", "Charts/qmldir"]
}
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml b/examples/qml/tutorials/extending-qml/chapter2-methods/Charts/App.qml
index d9477e253..6190cbc50 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/Charts/App.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import Charts
@@ -22,11 +22,7 @@ Item {
}
Text {
- anchors {
- bottom: parent.bottom;
- horizontalCenter: parent.horizontalCenter;
- bottomMargin: 20
- }
+ anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: "Click anywhere to clear the chart"
}
}
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/Charts/qmldir b/examples/qml/tutorials/extending-qml/chapter2-methods/Charts/qmldir
new file mode 100644
index 000000000..dad537878
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/Charts/qmldir
@@ -0,0 +1,4 @@
+module Charts
+typeinfo chapter2-methods.qmltypes
+depends QtQuick
+App 254.0 App.qml
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pyproject b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pyproject
index cdf33be7f..b0942a27b 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pyproject
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["methods.py", "app.qml"]
+ "files": ["methods.py", "Charts/App.qml", "Charts/qmldir"]
}
diff --git a/examples/qml/tutorials/extending-qml/chapter2-methods/methods.py b/examples/qml/tutorials/extending-qml/chapter2-methods/methods.py
index 238225fd3..02f600d1b 100644
--- a/examples/qml/tutorials/extending-qml/chapter2-methods/methods.py
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/methods.py
@@ -4,11 +4,10 @@ from __future__ import annotations
"""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.QtCore import Property, Signal, Slot, Qt
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement
from PySide6.QtQuick import QQuickPaintedItem, QQuickView
@@ -64,8 +63,8 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
- qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
- view.setSource(QUrl.fromLocalFile(qml_file))
+ view.engine().addImportPath(Path(__file__).parent)
+ view.loadFromModule("Charts", "App")
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml b/examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/App.qml
index f1530516a..0e30ba69b 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/App.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import Charts
@@ -30,11 +30,7 @@ Item {
}
Text {
- anchors {
- bottom: parent.bottom;
- horizontalCenter: parent.horizontalCenter;
- bottomMargin: 20
- }
+ anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
text: "Click anywhere to change the chart color"
}
}
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/qmldir b/examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/qmldir
new file mode 100644
index 000000000..f2d39dd19
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/Charts/qmldir
@@ -0,0 +1,4 @@
+module Charts
+typeinfo chapter3-bindings.qmltypes
+depends QtQuick
+App 254.0 App.qml
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py b/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py
index ed332cba7..a3fa77ed9 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/bindings.py
@@ -4,11 +4,10 @@ from __future__ import annotations
"""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.QtCore import Property, Signal, Slot, Qt
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement
from PySide6.QtQuick import QQuickPaintedItem, QQuickView
@@ -68,8 +67,8 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
- qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
- view.setSource(QUrl.fromLocalFile(qml_file))
+ view.engine().addImportPath(Path(__file__).parent)
+ view.loadFromModule("Charts", "App")
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
diff --git a/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject
index 6e21f86f9..ebd65a027 100644
--- a/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["app.qml", "bindings.py"]
+ "files": ["bindings.py", "Charts/App.qml", "Charts/qmldir"]
}
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/App.qml
index a5c5ff9fa..eb0a3cdcf 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/App.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import Charts
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/qmldir b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/qmldir
new file mode 100644
index 000000000..7a7a4188b
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/Charts/qmldir
@@ -0,0 +1,4 @@
+module Charts
+typeinfo chapter4-customPropertyTypes.qmltypes
+depends QtQuick
+App 254.0 App.qml
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject
index af1cfefb7..076f3a825 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["app.qml", "customPropertyTypes.py"]
+ "files": ["customPropertyTypes.py", "Charts/App.qml", "Charts/qmldir"]
}
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/customPropertyTypes.py b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/customPropertyTypes.py
index bf24ec3c3..2d03b5cb2 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/customPropertyTypes.py
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/customPropertyTypes.py
@@ -5,11 +5,10 @@ from __future__ import annotations
"""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.QtCore import Property
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement
from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
@@ -72,8 +71,8 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
- qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
- view.setSource(QUrl.fromLocalFile(qml_file))
+ view.engine().addImportPath(Path(__file__).parent)
+ view.loadFromModule("Charts", "App")
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/App.qml b/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/App.qml
new file mode 100644
index 000000000..c0c3e8268
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/App.qml
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+pragma ComponentBehavior: Bound
+import Charts
+import QtQuick
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: chart
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ component Slice: PieSlice {
+ parent: chart
+ anchors.fill: parent
+ }
+
+ slices: [
+ Slice {
+ color: "red"
+ fromAngle: 0
+ angleSpan: 110
+ },
+ Slice {
+ color: "black"
+ fromAngle: 110
+ angleSpan: 50
+ },
+ Slice {
+ color: "blue"
+ fromAngle: 160
+ angleSpan: 100
+ }
+ ]
+ }
+}
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/qmldir b/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/qmldir
new file mode 100644
index 000000000..48ec24349
--- /dev/null
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/Charts/qmldir
@@ -0,0 +1,4 @@
+module Charts
+typeinfo chapter5-listproperties.qmltypes
+depends QtQuick
+App 254.0 App.qml
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml b/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
deleted file mode 100644
index ac99d5a40..000000000
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-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
- }
- ]
- }
-}
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pyproject b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pyproject
index a3f89d575..d726432f0 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pyproject
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pyproject
@@ -1,3 +1,3 @@
{
- "files": ["app.qml", "listproperties.py"]
+ "files": ["listproperties.py", "Charts/App.qml", "Charts/qmldir"]
}
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/listproperties.py b/examples/qml/tutorials/extending-qml/chapter5-listproperties/listproperties.py
index 67d7482ec..c2ea85ff4 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/listproperties.py
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/listproperties.py
@@ -4,11 +4,10 @@ from __future__ import annotations
"""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.QtCore import Property
from PySide6.QtGui import QGuiApplication, QPen, QPainter, QColor
from PySide6.QtQml import QmlElement, ListProperty
from PySide6.QtQuick import QQuickPaintedItem, QQuickView, QQuickItem
@@ -86,8 +85,8 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
- qml_file = os.fspath(Path(__file__).resolve().parent / 'app.qml')
- view.setSource(QUrl.fromLocalFile(qml_file))
+ view.engine().addImportPath(Path(__file__).parent)
+ view.loadFromModule("Charts", "App")
if view.status() == QQuickView.Status.Error:
sys.exit(-1)
view.show()
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml b/examples/qml/tutorials/extending-qml/chapter6-plugins/App.qml
index 1a4772e15..79a9ce9b3 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/App.qml
@@ -1,32 +1,39 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
+pragma ComponentBehavior: Bound
import QtQuick
-import Charts 1.0
+import Charts
Item {
width: 300; height: 200
PieChart {
+ id: chart
anchors.centerIn: parent
width: 100; height: 100
+ component Slice: PieSlice {
+ parent: chart
+ anchors.fill: parent
+ }
+
slices: [
- PieSlice {
- anchors.fill: parent
+ Slice {
color: "red"
- fromAngle: 0; angleSpan: 110
+ fromAngle: 0
+ angleSpan: 110
},
- PieSlice {
- anchors.fill: parent
+ Slice {
color: "black"
- fromAngle: 110; angleSpan: 50
+ fromAngle: 110
+ angleSpan: 50
},
- PieSlice {
- anchors.fill: parent
+ Slice {
color: "blue"
- fromAngle: 160; angleSpan: 100
+ fromAngle: 160
+ angleSpan: 100
}
]
}
}
+
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/Charts/plugins.png b/examples/qml/tutorials/extending-qml/chapter6-plugins/Charts/plugins.png
deleted file mode 100644
index 8992e89c0..000000000
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/Charts/plugins.png
+++ /dev/null
Binary files differ
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst b/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
index 2320a8fa1..3677a71f5 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/doc/chapter6-plugins.rst
@@ -21,4 +21,4 @@ Running the Example
.. code-block:: shell
- pyside6-qml examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml -I examples/qml/tutorials/extending-qml/chapter6-plugins/Charts
+ pyside6-qml examples/qml/tutorials/extending-qml/chapter6-plugins/App.qml -I examples/qml/tutorials/extending-qml/chapter6-plugins/Charts
diff --git a/examples/quick/painteditem/doc/painteditem.png b/examples/quick/customitems/painteditem/doc/painteditem.png
index 743cd11b5..743cd11b5 100644
--- a/examples/quick/painteditem/doc/painteditem.png
+++ b/examples/quick/customitems/painteditem/doc/painteditem.png
Binary files differ
diff --git a/examples/quick/painteditem/doc/painteditem.rst b/examples/quick/customitems/painteditem/doc/painteditem.rst
index 5c3e8935b..5c3e8935b 100644
--- a/examples/quick/painteditem/doc/painteditem.rst
+++ b/examples/quick/customitems/painteditem/doc/painteditem.rst
diff --git a/examples/quick/painteditem/main.qml b/examples/quick/customitems/painteditem/main.qml
index 44be89dc3..44be89dc3 100644
--- a/examples/quick/painteditem/main.qml
+++ b/examples/quick/customitems/painteditem/main.qml
diff --git a/examples/quick/painteditem/painteditem.py b/examples/quick/customitems/painteditem/painteditem.py
index 95390b6ee..95390b6ee 100644
--- a/examples/quick/painteditem/painteditem.py
+++ b/examples/quick/customitems/painteditem/painteditem.py
diff --git a/examples/quick/painteditem/painteditem.pyproject b/examples/quick/customitems/painteditem/painteditem.pyproject
index 0597c2a97..0597c2a97 100644
--- a/examples/quick/painteditem/painteditem.pyproject
+++ b/examples/quick/customitems/painteditem/painteditem.pyproject
diff --git a/examples/quick/models/objectlistmodel/view.qml b/examples/quick/models/objectlistmodel/view.qml
index b7cf68a9b..3cb072dd3 100644
--- a/examples/quick/models/objectlistmodel/view.qml
+++ b/examples/quick/models/objectlistmodel/view.qml
@@ -2,14 +2,20 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
+import QtQuick.Controls
ListView {
- width: 100; height: 100
+ id: listview
+ width: 200; height: 320
+ required model
+ ScrollBar.vertical: ScrollBar { }
delegate: Rectangle {
- color: model.modelData.color
- height: 25
- width: 100
- Text { text: model.modelData.name }
+ width: listview.width; height: 25
+
+ required color
+ required property string name
+
+ Text { text: parent.name }
}
}
diff --git a/examples/quick/rendercontrol/rendercontrol_opengl/demo.qml b/examples/quick/rendercontrol/rendercontrol_opengl/demo.qml
index 00f6a81e9..ca6ba7b2b 100644
--- a/examples/quick/rendercontrol/rendercontrol_opengl/demo.qml
+++ b/examples/quick/rendercontrol/rendercontrol_opengl/demo.qml
@@ -2,13 +2,14 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import QtQuick.Particles 2.0
+import QtQuick.Particles
Rectangle {
id: root
+ property bool keyDown: false
gradient: Gradient {
- GradientStop { position: 0; color: mouse.pressed ? "lightsteelblue" : "steelblue" }
+ GradientStop { position: 0; color: mouse.pressed ? "lightsteelblue" : (root.keyDown ? "blue" : "steelblue") }
GradientStop { position: 1; color: "black" }
}
@@ -158,4 +159,7 @@ Rectangle {
id: mouse
anchors.fill: parent
}
+
+ Keys.onPressed: keyDown = true
+ Keys.onReleased: keyDown = false
}
diff --git a/examples/quick/scenegraph/openglunderqml/main.qml b/examples/quick/scenegraph/openglunderqml/main.qml
index 73bfa3262..5d4e51f76 100644
--- a/examples/quick/scenegraph/openglunderqml/main.qml
+++ b/examples/quick/scenegraph/openglunderqml/main.qml
@@ -30,7 +30,7 @@ Item {
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"
+ text: qsTr("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
diff --git a/examples/quick/scenegraph/scenegraph_customgeometry/main.qml b/examples/quick/scenegraph/scenegraph_customgeometry/main.qml
index 88431a176..044302428 100644
--- a/examples/quick/scenegraph/scenegraph_customgeometry/main.qml
+++ b/examples/quick/scenegraph/scenegraph_customgeometry/main.qml
@@ -22,13 +22,13 @@ Item {
p2: Qt.point(t, 1 - t)
p3: Qt.point(1 - t, t)
}
-
Text {
anchors.bottom: line.bottom
+
x: 20
width: parent.width - 40
wrapMode: Text.WordWrap
- text: "This curve is a custom scene graph item, implemented using GL_LINE_STRIP"
+ text: qsTr("This curve is a custom scene graph item, implemented using line strips")
}
}
diff --git a/examples/quick/window/Splash.qml b/examples/quick/window/Splash.qml
index 0a7da219d..698942554 100644
--- a/examples/quick/window/Splash.qml
+++ b/examples/quick/window/Splash.qml
@@ -24,19 +24,20 @@ Window {
Image {
id: splashImage
source: Images.qtLogo
- MouseArea {
- anchors.fill: parent
- onClicked: Qt.quit()
+ TapHandler {
+ onTapped: splash.exit()
}
}
+
+ function exit() {
+ splash.visible = false
+ splash.timeout()
+ }
+
//! [timer]
Timer {
- interval: splash.timeoutInterval; running: true; repeat: false
- onTriggered: {
- splash.visible = false
- splash.timeout()
- }
+ interval: splash.timeoutInterval; running: splash.visible; repeat: false
+ onTriggered: splash.exit()
}
//! [timer]
- Component.onCompleted: visible = true
}
diff --git a/examples/quick/window/rc_window.py b/examples/quick/window/rc_window.py
index 30b1fbf0a..13dd34325 100644
--- a/examples/quick/window/rc_window.py
+++ b/examples/quick/window/rc_window.py
@@ -1,290 +1,290 @@
# Resource object code (Python 3)
# Created by: object code
-# Created by: The Resource Compiler for Qt version 6.5.0
+# Created by: The Resource Compiler for Qt version 6.10.0
# WARNING! All changes made in this file will be lost!
from PySide6 import QtCore
qt_resource_data = b"\
-\x00\x00\x05\x12\
+\x00\x00\x04\xe8\
/\
/ Copyright (C) \
2021 The Qt Comp\
-any Ltd.\x0d\x0a// SPD\
-X-License-Identi\
-fier: LicenseRef\
--Qt-Commercial O\
-R BSD-3-Clause\x0d\x0a\
-\x0d\x0aimport QtQuick\
-\x0d\x0aimport QtQuick\
-.Controls\x0d\x0a\x0d\x0aCol\
-umn {\x0d\x0a id: r\
-oot\x0d\x0a spacing\
-: 8\x0d\x0a\x0d\x0a Label\
- {\x0d\x0a text\
-: \x22Total number \
-of screens: \x22 + \
-screenInfo.count\
-\x0d\x0a font.b\
-old: true\x0d\x0a }\
-\x0d\x0a\x0d\x0a Flow {\x0d\x0a\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick\x0aim\
+port QtQuick.Con\
+trols\x0a\x0aColumn {\x0a\
+ id: root\x0a \
+ spacing: 8\x0a\x0a \
+ Label {\x0a \
+ text: \x22Total nu\
+mber of screens:\
+ \x22 + screenInfo.\
+count\x0a fo\
+nt.bold: true\x0a \
+ }\x0a\x0a Flow {\x0a\
spacing:\
- 12\x0d\x0a wid\
-th: parent.width\
-\x0d\x0a\x0d\x0a Repe\
-ater {\x0d\x0a \
- id: screenIn\
-fo\x0d\x0a \
-model: (Qt.appli\
+ 12\x0a widt\
+h: parent.width\x0a\
+\x0a Repeate\
+r {\x0a \
+id: screenInfo\x0a \
+ model\
+: (Qt.applicatio\
+n as Application\
+).screens\x0a \
+ Label {\x0a \
+ re\
+quired property \
+string name\x0a \
+ requ\
+ired property in\
+t virtualX\x0a \
+ requi\
+red property int\
+ virtualY\x0a \
+ requir\
+ed property var \
+modelData // avo\
+id shadowing Lab\
+el.width and hei\
+ght\x0a\x0a \
+ lineHeight:\
+ 1.5\x0a \
+ text: name \
++ \x22\x5cn\x22 + virtual\
+X + \x22, \x22 + virtu\
+alY + \x22 \x22 + mode\
+lData.width + \x22x\
+\x22 + modelData.he\
+ight\x0a \
+ }\x0a }\x0a \
+ }\x0a\x0a Componen\
+t.onCompleted: {\
+\x0a var scr\
+eens = (Qt.appli\
cation as Applic\
-ation).screens\x0d\x0a\
- Labe\
-l {\x0d\x0a \
- required pr\
-operty string na\
-me\x0d\x0a \
- required pro\
-perty int virtua\
-lX\x0d\x0a \
- required pro\
-perty int virtua\
-lY\x0d\x0a \
- required pro\
-perty var modelD\
-ata // avoid sha\
-dowing Label.wid\
-th and height\x0d\x0a\x0d\
-\x0a \
- lineHeight: 1.5\
-\x0d\x0a \
- text: name + \x22\
-\x5cn\x22 + virtualX +\
- \x22, \x22 + virtualY\
- + \x22 \x22 + modelDa\
-ta.width + \x22x\x22 +\
- modelData.heigh\
-t\x0d\x0a }\
-\x0d\x0a }\x0d\x0a \
- }\x0d\x0a\x0d\x0a Compon\
-ent.onCompleted:\
- {\x0d\x0a var \
-screens = (Qt.ap\
-plication as App\
-lication).screen\
-s;\x0d\x0a for \
-(var i = 0; i < \
-screens.length; \
-++i)\x0d\x0a \
- console.log(\x22s\
-creen \x22 + screen\
-s[i].name + \x22 ha\
-s geometry \x22 +\x0d\x0a\
- \
- screens[\
-i].virtualX + \x22,\
+ation).screens;\x0a\
+ for (var\
+ i = 0; i < scre\
+ens.length; ++i)\
+\x0a con\
+sole.log(\x22screen\
\x22 + screens[i].\
-virtualY + \x22 \x22 +\
-\x0d\x0a \
- screen\
-s[i].width + \x22x\x22\
- + screens[i].he\
-ight)\x0d\x0a }\x0d\x0a}\x0d\
-\x0a\
-\x00\x00\x04\x8a\
-\x00\
-\x00\x16\xa7x\xda\xcdXYo\xdbF\x10~7\xe0\xff\
-0a_\xec\x06\xba\x93\x17\x15Fa+H\x1d\xc0A\
-b\xcb\xa8\x03\x14}\xa0\xc9\x91\xb8\xf5\x8a+\xec.-\
-9\xae\xff{\x87\xc7\x92\x94\xb8$\xe5ZnJ\x08\x10\
-\xb9;;\xc77\x07g\xd8\xeb\xc1D,\x1f$\x9b\x07\
-\x1a\x8e&\xc70\xec\x0f\x07p\x1d \x5cj\xdaY,\
-\xdd\xf0\x01.\xb4\xdf=<\xe8\xf5`\xfa\xf5\xc3\xb7\xce\
-\x05\xf30T\xd8\xf9\xe4c\xa8\xd9\x8c\xa1\x1cC\xb6v\
-\x85\xb3\xce\xa5\xee\xd0\xb9\x05J\x8f\xb9\x1c\xbe\x5c\xc1\xd9\
-\xf4Cg\xd4\x99p7Rxxpx\xc0\x16K!\
-5\xf1\xbf\x8c\x98w\xb7\xfd\xdc\x9d\x88PK\xc1UL\
-z\xa9\xbf\xdc\xfe\x85\x9e\x86\xc7\xc3\x03\xa0\x8b\xf9c\x90\
-B\xe8\xf4i)\xc5\x12\xa5~\x00\x89$\xc9\xc7\x99\x1b\
-q=]\xba\x1e\x0b\xe7c\x18\xf4\xb7\xa8\xa6\x0fJ\xe3\
-\xe2\xab\xcbQk\x84e\xfa?\xdeZ~\x84\xa7X\xf0\
-\xc6\xc1{W\x82\x97ju\xc3B_\xac\xc6\x90\xfe\x1b\
-\xb5\xe2k\xc5|\x1d\x8c\x89\x8ew\xc9 \xce<\xa6o\
-\xe2%x\x9bh\xdc\xddT\x0f~\x86aq6\xc0\x18\
-\xfe\xcd\xc3\xe7\xc9\xda.\xa7\xe9\x94\x90).\xdd\xcc\xaa\
-\xee*\xd1\xaf\xa0\xd1Ls\xb2\xd5\xc9\xc0\xcd\xf4w\x0a\
-\x82\x89\xe0\xd1\x22,\x1bd\xf0&\xf6\x9b\x8bn\xe8\x05\
-B\xaa\xee\x8cq>&\x1c%\x85\x81\x9db\xe1\xca9\
-\x0b\xd5\xd8f\xc3\xe6\x09e\xbc\xd6J\xb9\xe9t\x0f9\
-\xbf)\x90O\x9c\x00=\x18A\xc7\xb0\xdc<}\xe1\xde\
-\x22''k\x5c\xeb\x12\x1c\x9a\xe2]!\xf9\xd8\x87\x14\
-\xb9\xb1\x13\xc7A\xf9\xe4o\x92\xf9\xdb\xf0\x18\x88\xe6\xb4\
-W\xdd\xf1\x12H\xc9\xfaQuow{K\xb1\x95B\
-\x9d\x1aY%:\x8b\xb4\x16\xa1ME\xa3\xa6\x0a\xc4*\
-\xa5\xb2\xd3\x94B8\xc7\xd5N\x99\xc2\x97\xe8\xaeQ\xe9\
-4\x9a\xba\xf7L\xb1[\x8e\xf0+8\xe7\xccG\x07\x08\
-\xe1i\xb0\x11f\xe5K\x84\x13\x8a\xf4;\xf4\xeb9\x9d\
-\xc0\x9b\x9a\xad*\xcb\xa7\xeaR\xaf\xf7\x06\xfeH\x1d\x8a\
-\xfe$@\xef\xeeV\xac\xff\xac\xd2%[gb]\x07\
-^\x16-7\x19\xa7\x1a{L\x16\x170w\xd3\xa5\x97\
-\xa2}Fr\xe3\xac'\xefz\xb1\xa6H\x81HE\x89\
-GX\x83\x1c\xe3\x8c\x12\xe4\xe4\xe4$\xcb\xf3\xae\xd1\xdc\
-\x06\xd2.\xae\xc8\x18n\xb3\xfbO\x9d\xf0j\xf0f\xde\
-\xfd\x18q\x0eSO\x22\x86\xcek\xf9!\x96\x91\x8a\xd8\
-\x93'\x0a\x86;\xf9\xa2\xbdF\xb8\x91\x16\xfb\xac\x11\xce\
-)1\x5c\xb8\x9ay\xce^\x0c\xce\xd9\xfd\x9eo\xeed\
-\xf9\xae\xd1U\xd8\xdf\x18]\x99q\x9fY\xc8\x16\xec{\
-mIxy\xc4\xe4\x12\xf6\x1409\xbf\x1f\x89\x9a\xbb\
-~m\xd4\x8c\x84}\xa1f\xf8\xb5\xa2\xb6\xf58\x8bB\
-O32\xa4\xe0z-\xa6Z\x92yG\xf7\xc76X\
-\xd5\x8ai/\x80\x9a]\xcfU\xb8]\x85\xc7v\x13%\
-\xeaH\x86\xe0\x98\xd2\xeb\xfc\xd2\xcc.\x8f\x8c\x16~\x8b\
-<\xe6\xdb\x18\x1a\xd0\xda\x18\xe6\xe1\xd0\xc2\xb0(v-\
-\x1cgD\xa8\xd2J\xde\xc2\xd2RNZx\xbby=\
-kaM-\x90\xdf\xaai\x90\x10\xd9XY\x02\xd7\x1c\
-\x8a\xc2\xbbP\xac*\xa7\x9e\xac\xad\xae\xbdc-\xc21\
-!\xab\x12e\xa9\xba\xd1\x14\x03S\xe0\xd0Dr\xd4\xd0\
-\xf8e\xb7I\xef\xc7B\xf3t\x0co\xed8\x001t\
-I@\xe0\xaa\x92N\x89\x94\xac\xdb\xb5$N}\xc6\x1e\
-7\x22rE\x93\xa4\x1b\xceI\xd1Gk\xb7^\x99\xa2\
-b\x10\xfee7n*\xe3\xa0Q\xa3I$c&Y\
-K\xf0\xf8\xffW\xf8\xd4d\xa0\x22m-|\xcb\xf4\xd9\
-\xad}\x9e.\xdc\xd70L\x8f\x86\xfd\xea\x90<|\xd7\
-\xaf\xcc\xbe\xceO\xc3\xc1\xfbw\xfd\xbeS\x9dx\xafI\
-\x90\x91@\xa55H\x8f$\x11\x96\xdc\x15'f\xdc\x9d\
-\xd3\xb4v\xa9\xb3\xca\x0a\x7f\x17\xf7\x1f\xf3\x8a\x92\xbe\xe6\
-\xceYy\xe6\xad\xf5\xd3k\x8c\xca\xb5ymXy$\
-\x04\xe5\xa7\xd0.\xb0\x94\xdc\xd34\xb9+\xdf\x02,~\
-\xff,\x22\x85\xa74r7\x09\xae\xb7\xb2\xe5\x95\x9b\xba\
-\xe4\x84\xdc\x88}o4\xc0f]\xea\x9bX\xa3\x88L\
-#%\x0bLioH\x0c\xb1\x16\xcb\x9c\x94\xee\xeb\x09\
-wwQ\xcb\x88\xdc4\x16P\x09\xc55\xd3Pz\x85\
-\xc5\xa5t.\xca+\xb5)>x\xdfo\x04\xbe\xae\xf1\
-\x9f\xc1\xd1s5=\xae+\xe8\xb0\xbf>>\xbe\x90+\
-|\x99\xa8g\xccH\xcf\x8e4\x8e\xb3\x22\xd0\xe2\x87\x1f\
-\x14g\xce\xb7\xfa\xa0\x18\xf5\x9f\x97\x8c\x5c(<\xaa\x7f\
-\x936\x96u\xb5\xe4\xae\x0aLa\x9f&Oe\xfcD\
-x\xcd\x16(\x22\x93\x1a\x1b\x9fUK\x9f}\xb4\x8c0\
-\x97C\xbf\x7f\x00\xe8k\x05\xe6\
-\x00\x00\x04$\
+name + \x22 has geo\
+metry \x22 +\x0a \
+ \
+ screens[i].vir\
+tualX + \x22, \x22 + s\
+creens[i].virtua\
+lY + \x22 \x22 +\x0a \
+ \
+ screens[i].wi\
+dth + \x22x\x22 + scre\
+ens[i].height)\x0a \
+ }\x0a}\x0a\
+\x00\x00\x05\x01\
+(\
+\xb5/\xfd`\xff\x16\xbd'\x00\x06p\x912`\x8d:\
+0\x0c\xc3\xc0\x161\x1c\x00\x98G\xc1\xb5\xb6\x93$\xda\
+IN\x11E,I\x22\xd5#\xdck\xe3\x5c\x9d/Y\
+\xc2BlU\xb2\xcdF\x1e\x12Xb\x833\xad\x1c\x83\
+\x00~\x00\x85\x00\x15\xc9\xe1\xec\x8b\xb7\xd4\x8d&Lf\
++\xd1\xec\xe70\xcf\xcb\xcc\x85\x18\xaetL\xb7\xf4\x94\
+1\xa7\xd8\xbb\xd3\xad`\xef\xeeN \xfb\x8f7@\x13\
+\xdf\x99\xa6*\x9d\xfet\x8b\xe2x\x9du\xbe\xb3O\x1d\
+\xbbz\x9a\xb8fNZ\x96\x8d\xa5\xc1\xc3\xb0\x15\x13+\
+]?\xca\x97\xe5;\x96\x10WlE\xb9C\xfd\x93!\
+\x84\x85\xeb\xe4\xd7\x11\x16\x8c\x06\x0a\xcfD\xc1\x8f\xd8\xd2\
+t\xd8\xe5\xd6~g9~6\xa3\xc1h\xb6bQ\xf6\
+\xa3\xa8i\x09sk/\x97\x1c\x8f\xa3\x059c\x01.\
+\x17\x11\x80M\x80\xcc\xf1ZZ\xd3\xa3\xa7m\xb5\x8da\
+s\xda*,KP\xd7\x1eQ_\xf9I\x1e\xab\xffg\
+\x0c\x9b'\x82M\x1fD\xb6\x91\x16N\x7f\x5c\x97\xe3\xbf\
+\x07\xff\x82\xacd\x90\x8b\xa8k\xd9\xcd^\xf6BJ~\
+\xb5\xaa\xb3E\xd4]?\x99J\xd9!\xaaR\x8fo\xba\
+ye\xd2\xad\xd6\xb6b\xf9\xfd$\x8a\xffY:l+\
+\xea\x1c\x8e\x9a\x15Xj`/\xbe_K\xecjJ\xfa\
+\xdb*>l\xd2\x06_\xf9\xd30\x98\x02\x83\x8c&\xa0\
+\x15h0\x9a\x8d\x08\xc8\xd6\x05\x10\x9aY\x19\x96\xa2\xe9\
+\xfeqE\xa5\xba\xb8p\xbam\x03[\x99M\xd9\x81m\
+[{I>9f\x16!l\x8e\xab\xa1\x0b\xa1\x91\xda\
+N\x9a=\xd3\x8a\xab{\x1b\xdf7\xa9VF\x14\xd1l\
+\xfa\x1e\xff\xec\xf4\xfe7\xb3\x90\x87\x83\xfc\xd1W\xcf\x96\
+\xb0h\xaf\xdf]\xfe\xd9B\xf3\xcf\x5c\x9b\xcc\xf4yV\
+\xca\xcca\x13\x12\x12\xb6\xf4-\x9b3\xe9F\x1c\xdfN\
+\x87\xb3\x19\xa8\x0b\x0fg\xd0\xf0pP\x93H\xe6|\xb5\
+'V'\xb1Z;\xfeV(\x5c]\xbe\x91\x92\x10\xcb\
+\xad\xa8\x7fe\xda(\xf4S;VA\xba\x11\xe5\x9f\x10\
+P:\x07\xce\x85Z\x99Rp\xcd\x9ce\xe9k\xc9I\
+\x86\x90)\x8f<b\xfd\x91\xee\x9ffBrR)p\
+F\x1f\xe40\xa74\xb4\xc9\x14\x1cP\x98\x9d\x084{\
+\xd9\x0a\xe5r8\x1d\xa5\xe2;\x89\x1dX\x03\x0d\x85\xa1\
+8\x90\x88&`\xd3)K8\x1d\x07s\x1f\xcf\x84\xa0\
+\xfc\x93\xdf\xf4\xb39\x0e!\xd4w\xb6\xaa\x22'C\xf1\
+\x03\x81 \xa8\x11\xa6\x19\x1a\x11\x19IR\x94\x0c\x07A\
+\x08\x820\x14uV\x9a\x07Rx$IC\x18\xc3 \
+\x14\x8d\x10)`\x06\x11D\x08\x99HH\x82\x0bd\x92\
+4\xd5\x01\xfd\x86\xe3\x00;U\xd9[%\xb0+\xa0H\
+Y\x22\xa8\xc45\x02LtZ\xa2\x1f\xf5yiy\xf2\
+1\xe7\xffg\xce\x8eR\xb6\x88\xc1\xb6\x88m\xaf\xd4)\
+\xd7\xa7\x00\xb5\x15Y,,MT\xd3\x84\xcc\xb2\xd8\xca\
+\xa0\xd5&S\x9b&\x97\x05\xed\x06\x92\xfc]\xe6-i\
+q\x1ckF\x85\xbc(\x08\xa3\x9c\xbd\x00\xb3~1Z\
+\xf8\xd0\xa6d\xb1\x8a\x8f\xd7{\x9b\x97/=\xf0F\xf8\
+\xb4L\xefw\xce\xcd\xd0\xdb\xe9\xc9\xc7\xa8\x08\xdd\x97\xb9\
+\xfc\x035B\xc9\xfa\xcdKA\x83\xd7)\x8e\xdf\xb0\xd4\
+\x04F\xe2\xe7\xca\xcf<v\xa5D\xa0\xbd\xc9x\x87E\
+R\xb3@\x8cTv\x10\x04+\xc8\xd8\xc35\x07r\x18\
+VCyf\xa6\x08q\x03\x10\x07<\xefF\xbd\xff\xf9\
+\xff\x84\x9d\xfb\xa7\x88\xff\x0c\x0d\xed\xed\xb4\xd8\xa2\xe22\
+\x10\xac\xd3PA\xe2\xf8\x17\x13;4\x9e\xfd1\x92\x11\
+\xb5\xf6\x228t\xd6\x8c&\x87\xaf\xd0\xc3\xc3\xba\xa6\xa1\
+\xb8\xb9N\xb9/\xf7\x05~\x22\xa5d,\xc1b\xd1#\
+%U\x05\xfe\xc3\x14T\xbc0\xc9\xe7\x80PZ\xea_\
+\xdd\x9eO@1\xf8\x10.\xf7\x8c\x1fe\xc0\xacHQ\
+<\xb6\x026\xee\xcb\x81] 4\x0e%\xbe,\x0f\x87\
+Jk\x91XN9\xb1\x14$\xa0\xad\xd8I\xc1Uy\
+S\xb4\xae\xd4F\xf7X3\x92\x9e!E\xca$\xe7x\
+\xaazGx\x0eG(\x8e\x0cmij\x0aL\xd3\xfd\
+\xc0\x0a\xe4\xf3BKz\xa02G\xf6\x10\xca\x04D\x1b\
+\xc9\x86\xe0\xa7^\xb5Dz@\xcd\x9c\xfa\xd3-\x97\x10\
+a5\xb1\xba\x97D\x86\xb1\x0f\xea\x0c\x95\xf4tU\x1f\
+\x93\xf7\xacR\x9c\xb6\x00\x83\xf4\xefK\xa5\xf8]\x97\x80\
+'\xa2\x04\x17\xeeu\xf43\x1f\x81\xe0C\xee\xf4\xf7\x85\
+7\xda17\x00\x1a\x14]\xdb\xb6\xad\x1c\x0d8\x12q\
+\x9c:\x0c1\x22\xf3\xd1\x09Vz\x916\x01h\xd9\x88\
+\x8b\xbf\xb5\xa3\xb84\xe2\xcd\xe7b\xf1\xac\xad\x9cR\x96\
+\xe3\x11\x97\x92\x93\xa3\xc1\x87\xf2:\xf2y\x0b\xb0\xca\xbd\
+\xdd \xc7t?D\xaf\x16-\x05a\xd2\xbd9 \xb3\
+\x9fRI\xaf\xbc\x99\x1cC\x0eK?\x9e\xdc\x86\xc3$\
+\xfe)\xab-\x01v\xbb\x1e\x8e\xdd\xfbm\x12\xc8\x1b\xf5\
+\xce\x1fym\xd8\x10\x0e\xe5\xd5w\xd1\x05m\x14`\xd5\
+\x0bAo)\xb0c,\x81'H\x81.xsAP\
+=&\xe5\xa0Z\xe0\x828\xa6\xdc\xde\xa0\xeb\x8e\xb1F\
+\xcb\xc0D6_,\x04\xa8y\xe0\xdf\x95\x9f\xfb\xe1\x97\
+\xa3I\xa6\x1f#k)\xf4\xaf\x03m\xd7\xc8AP\x12\
+]\x154_\xbd\x1cU\x0dcv\xb8\xbf\x1a\xc0\xa8\x02\
+\
+\x00\x00\x03\xd5\
/\
/ Copyright (C) \
2021 The Qt Comp\
-any Ltd.\x0d\x0a// SPD\
-X-License-Identi\
-fier: LicenseRef\
--Qt-Commercial O\
-R BSD-3-Clause\x0d\x0a\
-\x0d\x0aimport QtQuick\
-\x0d\x0aimport shared\x0d\
-\x0a\x0d\x0a//! [splash-p\
-roperties]\x0d\x0aWind\
-ow {\x0d\x0a id: sp\
-lash\x0d\x0a color:\
- \x22transparent\x22\x0d\x0a\
- title: \x22Spla\
-sh Window\x22\x0d\x0a \
-modality: Qt.App\
-licationModal\x0d\x0a \
- flags: Qt.Spl\
-ashScreen\x0d\x0a p\
-roperty int time\
-outInterval: 200\
-0\x0d\x0a signal ti\
-meout\x0d\x0a//! [spla\
-sh-properties]\x0d\x0a\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick\x0aim\
+port shared\x0a\x0a//!\
+ [splash-propert\
+ies]\x0aWindow {\x0a \
+ id: splash\x0a \
+ color: \x22transpa\
+rent\x22\x0a title:\
+ \x22Splash Window\x22\
+\x0a modality: Q\
+t.ApplicationMod\
+al\x0a flags: Qt\
+.SplashScreen\x0a \
+ property int t\
+imeoutInterval: \
+2000\x0a signal \
+timeout\x0a//! [spl\
+ash-properties]\x0a\
//! [screen-prop\
-erties]\x0d\x0a x: \
-(Screen.width - \
-splashImage.widt\
-h) / 2\x0d\x0a y: (\
-Screen.height - \
-splashImage.heig\
-ht) / 2\x0d\x0a//! [sc\
-reen-properties]\
-\x0d\x0a width: spl\
-ashImage.width\x0d\x0a\
- height: spla\
-shImage.height\x0d\x0a\
-\x0d\x0a Image {\x0d\x0a \
- id: splas\
-hImage\x0d\x0a \
-source: Images.q\
-tLogo\x0d\x0a M\
-ouseArea {\x0d\x0a \
- anchors.\
-fill: parent\x0d\x0a \
- onClic\
-ked: Qt.quit()\x0d\x0a\
- }\x0d\x0a }\
-\x0d\x0a //! [timer\
-]\x0d\x0a Timer {\x0d\x0a\
- interval\
-: splash.timeout\
-Interval; runnin\
-g: true; repeat:\
- false\x0d\x0a \
-onTriggered: {\x0d\x0a\
- spla\
-sh.visible = fal\
-se\x0d\x0a \
-splash.timeout()\
-\x0d\x0a }\x0d\x0a \
- }\x0d\x0a //! [tim\
-er]\x0d\x0a Compone\
-nt.onCompleted: \
-visible = true\x0d\x0a\
-}\x0d\x0a\
-\x00\x00\x03\x08\
-\x00\
-\x00\x0a\xb7x\xda\xadV\xdfo\xda0\x10~G\xe2\x7f\
-\xb8\xe5\x09\xb6\x91\x00\xeb\xa6)}\x986\xaam\x95\xd0\
-\xdaB\xa5uZ\xf7`\x92\x03\xac&v\xe48\x144\
-\xf5\x7f\x9f\x9d\x1f\x8d\x01\x0f\x82\xb6\x08\x89\xdc\xf9\xbb\xfb\
->\xdbg_<\x0fF<\xd9\x08\xbaXJ\xe8\x8c\xba\
-0\xec\x0f\x07p\xbbD\xb8\x91j$N\x08\xdb\xc0X\
-\x86n\xbb\xe5y0\xbd\xbe\xb8\xeb\x8di\x80,\xc5\xde\
-e\x88L\xd29E\xe1C\xe9\x9b\xe0\xbcw#{*\
-.F\x11P\x12\xc1\xd5\x04>M/zoz\xa3\x88\
-d)\xb6[\xed\x16\x8d\x13.\xa4\xca\x7f\x93\xd1\xe0a\
-\xd7vG\x9cI\xc1\xa3TC/%\xc6\xf0\xbb\xdd\x02\
-\xf5\xd0\xd0\x07\xc1\xb9,\xacG\x1a\xca\xa5\x0fg\xfd~\
-a/Q\xcf\xc0\x87D\xf0\x04\x85\xdc|\x114tU\
-\xe6\x88\x06T~\xcd\x07\xe1\x15\x0c\xde\xe9\xac\x1a?\xcf\
-X )g\xc0\x05U\xd3 \xfa\xfd\x96O\xa5\xa0l\
-\xd1\xe1\xdd\x8aT?\xe9#\x95\xc1\x12v\xbc\x01I\xf5\
-\x1a\xb9\xd7\x82\xc6Dl\xae\xea4~\x0d\xd2\x8f@\x99\
-\x09\x06NR\x00\x9dsK\x0e5\x7fA\xa8l\x90\xa4\
-D\xda\xb2\x8c\x09\x0b\xd3\x80$x<MTAmy\
-.\xd9J\xad \x86\xcdU\xd12\x02\x0e\xc9\xab\xd2\x9e\
- \xf39\xafU\xefS\xfdZ\x05d\xec\x81\xf1GV\
-\xa1\x9e\xaa\xdd\xd6\xd5`n\x9e\xae%\xb3R\x0c\xb5<\
-\xcab\x96\xfa04\x0a !\x81*\x0b\x1f\xde\xd7\xbe\
-\xb5_\xb9k\xdf\xc6\xf0\xd5^\xcf{\x01?\xd3@ \
-\xb2_\xb5wLf\x18\x99\x92\xf4#q\xadJ\xd8\x99\
-\xe6`\xb8w\x1cU\xb2\x85\xe12\x12\xa3\xb2\x9c{\xc7\
-w\xb6\x83\xe6\xea\xbc\xb83\x1e\xa9)I\x91\xa1u}\
-\x8asT\x1d\x9a\xc1\xf9\xf3q\x19\xc0\x93\x12\x98\xcbF\
-a\xaa.\xf5U\x92b\xc2\xb29\x09\xd4*\xa3p\xcc\
-\xcc\xdb\xb8R\xac\x89\x86\x0fV\xaf_oV\xbdM6\
-b\x1eb\xd4\x80Q\xc3\x0c\xaa\xdcl\xca\x91\xa2\xd0W\
-\x15\xcb\xe2Y\x93\xd9\x15\xf0o9\xba\xa6\xdc\xf26e\
-\x0ei\xac\xaeMu\x00\xd2\xe3\xb4\xf9\xe6\xe9\x12X\x1b\
-eQ\xec\xe3A\x8e\x84\xae\x95\x19j\x1e\xb99N\x93\
-\xc3/\x0a\xb4+\xf9ge\x86\x9daW\x13C\xc8e\
-\xea\xc51t\xb4\x82\x8e%\x00^\xc2\xf0\xad{\xd6\xb5\
-\x06R\x16,\xbb\x87\xd7#\xe2\x0b\x1a\xa8\xad8Qs\
-\x19v}\xaatK\xdc\xbf\xce \xc4\x95j\x85\xe5\x04\
-\x84\xbe\xdc\x8e\xcb/br\x15\x13\x1dar\x1f\xe2\x22\
-+B#2\x8b\x10VT\xc8\x8c\xe8\x15K\x1f$O\
-\x9aP\xe6\xc0\x8fU\x86\xef\xb6\xe2\xda\x05}mPl\
-\x5c-\xa2n\xab\x94\x9d.\xaa\x0c\xb8\xd3:^\x83!\
-\xa4\x1c\xf8q\x90\xdah\xe4\x07\xa8\xf4\x17\x84k\xeb\xf9\
-%\x951Tl|\xc7\xd0a\x0c\xea\xb1#\xa5P6\
-|\xf8?\xc2\x92\xbd\xef\x8c}}\xfb\x98Z\xa6\xbd\x1d\
-\xfdU\xfc\xa0\xaf\x0e\x8b\xc0@\x12\xb6\x88p+\xc3\xa4\
-\xf2\xee\xb6/\xd5;\xb9\xfa\x16t\x04\x86;=\xaal\
-<\xf6\x1bc\xd0\xdf\x06W\xbd)\x0f\xdakg\xeaO\
-\xfd\xfe\x00\x1e\x91\x1e\xa9\
+erties]\x0a x: (\
+Screen.width - s\
+plashImage.width\
+) / 2\x0a y: (Sc\
+reen.height - sp\
+lashImage.height\
+) / 2\x0a//! [scree\
+n-properties]\x0a \
+ width: splashI\
+mage.width\x0a h\
+eight: splashIma\
+ge.height\x0a\x0a I\
+mage {\x0a i\
+d: splashImage\x0a \
+ source: I\
+mages.qtLogo\x0a \
+ TapHandler \
+{\x0a on\
+Tapped: splash.e\
+xit()\x0a }\x0a\
+ }\x0a\x0a funct\
+ion exit() {\x0a \
+ splash.visi\
+ble = false\x0a \
+ splash.timeo\
+ut()\x0a }\x0a\x0a \
+//! [timer]\x0a \
+Timer {\x0a \
+interval: splash\
+.timeoutInterval\
+; running: splas\
+h.visible; repea\
+t: false\x0a \
+ onTriggered: sp\
+lash.exit()\x0a \
+}\x0a //! [timer\
+]\x0a}\x0a\
+\x00\x00\x03\x03\
+(\
+\xb5/\xfd`d\x09\xcd\x17\x00fbg\x1f\x00\xdb6\
+\x8e\x19\x94\xa4Zd_\xd9sQ1d\xb4\x22\x92\x81\
+P\xe2a+\xcaH\xcc\xa5\xff\xed?\x94`\x00\x5c\x00\
+^\x00\xddtf\xe6\x0c\xc6^?&\xcb@j\xefW\
+;\xd9V\xd2\xc3\xcew\xf8\xaf\xfd<\xcf\xb2\x06\xc3H\
+'\x06\x85\x81\xf2\x91\xb0g\xc34\xba\xbc\xed\x19\xbec\
+@\xb5\x87\xbb\xdb\x8e\xf2\xaf=1\x86\x06kK\xcf\x18\
+D\x14\xce'\xdb\xe6g\xf8U\xe3\xe7\xd9\x09\x7f\x87[\
+\x05bD\xe2\x90`\xc1$\xc0\xafJ\xf9}}v\xc2\
+\x1c\x17\xb6\xaej\x98\xc5\xd8g\xffmV\xc5\xd0\xfe\xa2\
+\x04g\x8d\x99\xf7x\xff\xda\x87\xf6i\x5co\xf8}9\
+\xeb6\xaf\x1b=\xbf\x9c\x0d\x8c\x92U\xf2\xbd\x05\x0al\
+ U\xfd\xfe\xc7\x82\xe2\xd7\xf6k\xb9Z\x7fYCT\
+\xd6@0\x81/\xef\xd2\xe96\xfdZ^\x7f\xfb\xb3\xf7\
+\xe3\xaeU\x87\xc3\x82;\xd5Oo\xbd\xb5\x97\x03\xb5=\
+\x9f\x9a\x93\x17V\xa6\xd1o\x83\xb4\xa7\x8dq\x07\xe1\x18\
+k\xb7o\xf82\xa2\xc2\x1a\xbd\xec6\xc7q\x8c\x11\x0f\
+D\x87\xf7\xb9\x9b\xd4\x9e\xb6\xaf\x16\xa5uZIc\x02\
+\xb7\x17\xeb\xc6\x04\xd6\xb4\x12\x7f4\xee\xde\xd5O\xfb\x14\
+3\xa6\xda}%Hb\x00\xc7\xbd:\x97\x83\xbbTu\
+\x19\xbf\x04w`\xf5Bj\xa7\xc7j+Y\xec\x80\x98\
+}\xaf\xf54M\xd5\xf8\xb2/{\xde\x01\xb1\xe1\xed\xad\
+\xbd#.\x88\xaa;h/\xa1\xc8g\x7f\x05\xc6\xf0\xaf\
+\xb3\xb8\xe9)R\x8f\xac\xe8\xb1\xfe\xf1\xb6tVO\x0e\
+\xd3(=e\xa9@%\xab\x0b\x16\x1b#\xc1\x03\x0e\x04\
+\xd8\xf38\xf0\xeddA\x220\xdb\xe5\x15\xfb\x1b\xe5\xf5\
+\x93i\xbb\xfcs\x81\xd5:\x18\x80\x93\xa0\xa1\xa532\
+C3\x92$)\xa5\x03 \x84\x10\xc4\xdcq\x07\xe9\x80\
+\xaa\xec\xf5}\xa7\x0a~\xe6v j\x95\xc9\x9a\x9f\x93\
+\xb1\x1fxx\x8dL\x93\x8d$fa.\xaf\x96kF\
+\x7fRr.\x00r\x00\xedF2\x85\xee\x9e\x1a\x02H\
+\xfc\x150\x0f\x05'x\xbb\x5c\x19\xc8p\xef\xa2\xad\xb2\
+'W\xec]a^\x5cb\x0f\x22\xcb\xd4\x0d+\x15\x8c\
+\xe4lK\x86\x11\xea$T\x9a'\xf2\xae\xe7BL\xee\
+\xc5k\xac!\xbf8\x8d5D\xb0\x0e\xed\xd7\x91\x83\xbb\
+\x880\xa8mr\xbb\xc2\xd9\x0cO+\xd34\x80\xc9\xbc\
+o\x14Y\x0b\x883O\x10\xfc\x88]p>\x8cr\x8d\
+T\xf0k\xf8\x0bj\xef?\xd0r\xb57\x1d\x07(\xe7\
+\xee{h\x13\x8b\xc1\xb6\x90\x92\xf9\x8a\xe5\x95)\xd9\x22\
+2\xc6\xc9e\xe7i\xb0R\x1f\x18W\x95lPV#\
+}Mgl\xb3\xb8\xa7\xd8EF\x22\xaa\xe40P8\
+\xf1\xaf\x0f\x82\x0dt\xe6\xa4\x01G@\x07\xa5;^\x0c\
+v\x14\xe4\x90k*\x5c\xfe\x9b\x14o\xd6@9\xd6\xa2\
+\x7f\xb0\x85\x1f\xe7yV2\xe4+\xf4\xcc1S<\x98\
+\x01\x9e<Q]\xa5R\xc8\xc4\x84\x06\x22!\x8f\x0f$\
+\xcc\xec\x19pP\xe8\xed\xc2\x83\xa3\xc1H.\xd7\x80\x85\
+\x91K\xe8\xdc\x9cW\xf2V\x8a\x15\x02\xbeH,\xe0<\
+\x16\x8c\xbbSP\xfb_\xd8)}\x00u\xcc(5\xe0\
+U\x01\
"
qt_resource_name = b"\
@@ -316,14 +316,14 @@ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00h\x00\x01\x00\x00\x00\x01\x00\x00\x0d\xcc\
-\x00\x00\x01\x87V\x12\x92R\
-\x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x09\xa4\
-\x00\x00\x01\x87V\x12\x92R\
-\x00\x00\x004\x00\x01\x00\x00\x00\x01\x00\x00\x05\x16\
-\x00\x00\x01\x87V\x12\x92R\
+\x00\x00\x00h\x00\x04\x00\x00\x00\x01\x00\x00\x0d\xca\
+\x00\x00\x01\x975l\xc7\xec\
+\x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x09\xf1\
+\x00\x00\x01\x998\xf9\x98B\
+\x00\x00\x004\x00\x04\x00\x00\x00\x01\x00\x00\x04\xec\
+\x00\x00\x01\x998\xf9\x98B\
\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x87V\x12\x92R\
+\x00\x00\x01\x975l\xc7\xec\
"
def qInitResources():
diff --git a/examples/quick/window/window.qml b/examples/quick/window/window.qml
index 47cc5257b..99ff4403e 100644
--- a/examples/quick/window/window.qml
+++ b/examples/quick/window/window.qml
@@ -7,12 +7,11 @@ import QtQuick.Controls
QtObject {
id: root
property real defaultSpacing: 10
- property SystemPalette palette: SystemPalette { }
property var controlWindow: Window {
width: col.implicitWidth + root.defaultSpacing * 2
height: col.implicitHeight + root.defaultSpacing * 2
- color: root.palette.window
+ color: palette.window
title: "Control Window"
Column {
id: col
@@ -90,13 +89,13 @@ QtObject {
" and has visibility " + parent.visibilityToString(root.testWindow.visibility)
}
Rectangle {
- color: root.palette.text
+ color: palette.text
width: parent.width
height: 1
}
CurrentScreen { }
Rectangle {
- color: root.palette.text
+ color: palette.text
width: parent.width
height: 1
}
@@ -117,35 +116,44 @@ QtObject {
anchors.centerIn: parent
text: "Second Window"
}
- MouseArea {
- anchors.fill: parent
- onClicked: root.testWindow.color = "#e0c31e"
+ TapHandler {
+ onTapped: root.testWindow.color = Qt.rgba(0.25 + Math.random() / 2,
+ 0.65 + Math.random() / 4,
+ 0.15 + Math.random() / 3)
}
Button {
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: root.defaultSpacing
- text: root.testWindow.visibility === Window.FullScreen ? "exit fullscreen" : "go fullscreen"
- width: 150
- onClicked: {
- if (root.testWindow.visibility === Window.FullScreen)
- root.testWindow.visibility = Window.AutomaticVisibility
- else
- root.testWindow.visibility = Window.FullScreen
+ id: fullscreenButton
+ anchors {
+ right: parent.right
+ top: parent.top
+ margins: root.defaultSpacing
}
+ width: height
+ checkable: true
+ Binding on checked { value: root.testWindow.visibility === Window.FullScreen }
+ onClicked: root.testWindow.visibility = checked ? Window.FullScreen : Window.AutomaticVisibility
+ text: "â›ļ"
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ ToolTip.text: root.testWindow.visibility === Window.FullScreen ? qsTr("restore") : qsTr("fill screen")
}
Button {
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: root.defaultSpacing
- text: "X"
- width: 30
+ text: "✘"
+ width: height
+ height: fullscreenButton.height
onClicked: root.testWindow.close()
+ ToolTip.visible: hovered
+ ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
+ ToolTip.text: qsTr("close this window")
}
}
}
property var splashWindow: Splash {
+ visible: true
onTimeout: root.controlWindow.visible = true
}
}
diff --git a/examples/quick/window/window.qrc b/examples/quick/window/window.qrc
index 89d1de1b1..b9ae1d931 100644
--- a/examples/quick/window/window.qrc
+++ b/examples/quick/window/window.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/window">
+ <qresource prefix="window">
<file>window.qml</file>
<file>Splash.qml</file>
<file>CurrentScreen.qml</file>
diff --git a/examples/quick3d/intro/main.qml b/examples/quick3d/intro/main.qml
index 648cfcf5c..ab4e6a6de 100644
--- a/examples/quick3d/intro/main.qml
+++ b/examples/quick3d/intro/main.qml
@@ -42,8 +42,8 @@ Window {
position: Qt.vector3d(0, -200, 0)
source: "#Cylinder"
scale: Qt.vector3d(2, 0.2, 1)
- materials: [ DefaultMaterial {
- diffuseColor: "red"
+ materials: [ PrincipledMaterial {
+ baseColor: "red"
}
]
}
@@ -52,8 +52,8 @@ Window {
position: Qt.vector3d(0, 150, 0)
source: "#Sphere"
- materials: [ DefaultMaterial {
- diffuseColor: "blue"
+ materials: [ PrincipledMaterial {
+ baseColor: "blue"
}
]
diff --git a/sources/pyside6/doc/_tags/android.rst b/sources/pyside6/doc/_tags/android.rst
index 0fdf2041a..d694f75f9 100644
--- a/sources/pyside6/doc/_tags/android.rst
+++ b/sources/pyside6/doc/_tags/android.rst
@@ -15,9 +15,9 @@ My tags: Android
../examples/example_multimedia_camera.rst
../examples/example_qml_editingmodel.rst
../examples/example_qml_usingmodel.rst
+ ../examples/example_quick_customitems_painteditem.rst
../examples/example_quick_models_objectlistmodel.rst
../examples/example_quick_models_stringlistmodel.rst
- ../examples/example_quick_painteditem.rst
../examples/example_quickcontrols_contactslist.rst
../examples/example_quickcontrols_gallery.rst
../examples/example_widgets_widgets_digitalclock.rst
diff --git a/sources/pyside6/doc/developer/add_port_example.rst b/sources/pyside6/doc/developer/add_port_example.rst
index 59aa2f115..909986e79 100644
--- a/sources/pyside6/doc/developer/add_port_example.rst
+++ b/sources/pyside6/doc/developer/add_port_example.rst
@@ -27,7 +27,13 @@ For example:
$ flake8 --config pyside-setup/.flake8 your_file.py
$ isort your_file.py
+Later on, the tool `tools/sync_examples.py` can be used to update the source
+files from Qt C++. Each difference produced by tool needs to checked with care,
+differences in `qmldir` files (`prefer` directive) might apply to C++ only.
+Also, be careful not to back-port old Qt Widgets Designer `.ui` files with
+unqualified enumerations. If a `.ui` file has additions, make sure to load and
+save it at least once.
Add a new example
-----------------
diff --git a/sources/pyside6/doc/developer/pythonversions.md b/sources/pyside6/doc/developer/pythonversions.md
index a4803bbbe..baef18d77 100644
--- a/sources/pyside6/doc/developer/pythonversions.md
+++ b/sources/pyside6/doc/developer/pythonversions.md
@@ -2,7 +2,8 @@
## Relevant preprocessor defines
-- The version range is determined by `wheel_artifacts/pyproject.toml.base`
+- The version range is determined by `wheel_artifacts/pyproject.toml.base`.
+ This file also defines the version tag (`py_limited_api = "cp310"`).
- `PY_VERSION_HEX` Python version (defined in CPython headers)
- `Py_LIMITED_API` Limited API minimum version, defined in several CMake files
- `PYPY_VERSION` [PyPy](https://pypy.org/) version (defined in PyPy headers)
@@ -16,8 +17,11 @@ The removal of Python versions is tied to their lifetime
- Check the source code for preprocessor defines depending on
values `Py_LIMITED_API`, `PY_VERSION_HEX` and simplify or
remove conditions if possible.
+- Check the usages of `_PepRuntimeVersion()` for outdated versions
- Run the tests and some examples. There might actually
- some version checks in Python code that trigger.
+ some version checks in Python code that trigger
+ (see for example
+ `sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py:70`).
## Adapting to new Python versions
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index ed7067a2e..d08fb56bf 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -353,6 +353,18 @@ void SignalManager::handleMetaCallError()
Py_SetRecursionLimit(reclimit);
}
+const char *metaObjectCallName(QMetaObject::Call call)
+{
+ static const char *names[] = {
+ "InvokeMetaMethod", "ReadProperty", "WriteProperty", "ResetProperty",
+ "CreateInstance", "IndexOfMethod", "RegisterPropertyMetaType",
+ "RegisterMethodArgumentMetaType", "BindableProperty", "CustomCall",
+ "ConstructInPlace"};
+ constexpr size_t count = sizeof(names)/sizeof(names[0]);
+ static_assert(QMetaObject::ConstructInPlace == count - 1);
+ return call >= 0 && call < count ? names[call] : "<unknown>";
+}
+
// Handler for QMetaObject::ReadProperty/WriteProperty/ResetProperty:
int SignalManagerPrivate::qtPropertyMetacall(QObject *object,
QMetaObject::Call call,
@@ -398,7 +410,7 @@ int SignalManagerPrivate::qtPropertyMetacall(QObject *object,
}
qWarning().noquote().nospace()
- << "An error occurred executing the property metacall " << call
+ << "An error occurred executing the property metacall " << metaObjectCallName(call)
<< " on property \"" << mp.name() << "\" of " << object;
handleMetaCallError(object, &result);
}
diff --git a/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py b/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py
index 648b07a50..6aaf60dd8 100644
--- a/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py
+++ b/sources/pyside6/tests/tools/pyside6-deploy/test_pyside6_deploy.py
@@ -330,11 +330,6 @@ class TestPySide6DeployQml(DeployTestBase):
expected_modules = {"Core", "Gui", "Qml", "Quick", "Network", "OpenGL", "QmlModels",
"QmlWorkerScript", "QmlMeta"}
- # Exclude OpenGL if the platform is Windows and architecture is aarch64
- # https://bugreports.qt.io/browse/QTBUG-126030
- if sys.platform == "win32" and platform.machine() == "ARM64":
- expected_modules.remove("OpenGL")
-
if sys.platform != "win32":
expected_modules.add("DBus")
obtained_modules = set(config_obj.get_value("qt", "modules").split(","))
@@ -460,7 +455,7 @@ class TestPySide6DeployWebEngine(DeployTestBase):
# Exclude specific modules if the platform is Windows and architecture is aarch64
if sys.platform == "win32" and platform.machine() == "ARM64":
- excluded_modules = {"OpenGL", "WebEngineCore", "Positioning", "WebChannelQuick",
+ excluded_modules = {"WebEngineCore", "Positioning", "WebChannelQuick",
"WebChannel"}
expected_modules.difference_update(excluded_modules)
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index ce361245c..9c65eeb5e 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -531,7 +531,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
ReportHandler::startProgress("Generated enum model ("
+ QByteArray::number(enums.size()) + ").");
for (const EnumModelItem &item : enums) {
- auto metaEnum = traverseEnum(item, nullptr, QSet<QString>());
+ auto metaEnum = traverseEnum(item, nullptr);
if (metaEnum.has_value()) {
if (metaEnum->typeEntry()->generateCode())
m_globalEnums << metaEnum.value();
@@ -765,7 +765,7 @@ AbstractMetaClassPtr
AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &namespaceItem)
{
- QString namespaceName = currentScope()->qualifiedName().join(u"::"_s);
+ QString namespaceName = currentScope()->qualifiedNameString();
if (!namespaceName.isEmpty())
namespaceName.append(u"::"_s);
namespaceName.append(namespaceItem->name());
@@ -809,7 +809,7 @@ AbstractMetaClassPtr
m_itemToClass.insert(namespaceItem.get(), metaClass);
}
- traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
+ traverseEnums(namespaceItem, metaClass);
pushScope(namespaceItem);
@@ -856,10 +856,9 @@ AbstractMetaClassPtr
std::optional<AbstractMetaEnum>
AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
- const AbstractMetaClassPtr &enclosing,
- const QSet<QString> &enumsDeclarations)
+ const AbstractMetaClassPtr &enclosing)
{
- QString qualifiedName = enumItem->qualifiedName().join(u"::"_s);
+ QString qualifiedName = enumItem->qualifiedNameString();
TypeEntryPtr typeEntry;
const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{};
@@ -922,10 +921,6 @@ std::optional<AbstractMetaEnum>
metaEnum.setDeprecated(enumItem->isDeprecated());
metaEnum.setUnderlyingType(enumItem->underlyingType());
metaEnum.setSigned(enumItem->isSigned());
- if (enumsDeclarations.contains(qualifiedName)
- || enumsDeclarations.contains(enumName)) {
- metaEnum.setHasQEnumsDeclaration(true);
- }
auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry);
metaEnum.setTypeEntry(enumTypeEntry);
@@ -1177,7 +1172,7 @@ AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelIt
parseQ_Properties(metaClass, classItem->propertyDeclarations());
- traverseEnums(classItem, metaClass, classItem->enumsDeclarations());
+ traverseEnums(classItem, metaClass);
// Inner classes
{
@@ -1648,13 +1643,11 @@ bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &me
}
void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
- const AbstractMetaClassPtr &metaClass,
- const QStringList &enumsDeclarations)
+ const AbstractMetaClassPtr &metaClass)
{
const EnumList &enums = scopeItem->enums();
- const QSet<QString> enumsDeclarationSet(enumsDeclarations.cbegin(), enumsDeclarations.cend());
for (const EnumModelItem &enumItem : enums) {
- auto metaEnum = traverseEnum(enumItem, metaClass, enumsDeclarationSet);
+ auto metaEnum = traverseEnum(enumItem, metaClass);
if (metaEnum.has_value()) {
metaClass->addEnum(metaEnum.value());
}
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
index 45dd21e02..28b23c35b 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h
@@ -94,10 +94,8 @@ public:
AbstractMetaClassPtr traverseNamespace(const FileModelItem &dom,
const NamespaceModelItem &item);
std::optional<AbstractMetaEnum> traverseEnum(const EnumModelItem &item,
- const AbstractMetaClassPtr &enclosing,
- const QSet<QString> &enumsDeclarations);
- void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent,
- const QStringList &enumsDeclarations);
+ const AbstractMetaClassPtr &enclosing);
+ void traverseEnums(const ScopeModelItem &item, const AbstractMetaClassPtr &parent);
AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
const AbstractMetaClassPtr &currentClass);
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
index 486d3d39c..3f2714ffc 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
@@ -96,8 +96,7 @@ void AbstractMetaEnumValue::setDocumentation(const Documentation &doc)
class AbstractMetaEnumData : public QSharedData
{
public:
- AbstractMetaEnumData() : m_deprecated(false),
- m_hasQenumsDeclaration(false), m_signed(true)
+ AbstractMetaEnumData() : m_deprecated(false), m_signed(true)
{
}
@@ -113,7 +112,6 @@ public:
EnumKind m_enumKind = CEnum;
Access m_access = Access::Public;
uint m_deprecated : 1;
- uint m_hasQenumsDeclaration : 1;
uint m_signed : 1;
};
@@ -298,17 +296,6 @@ bool AbstractMetaEnum::isAnonymous() const
return d->m_enumKind == AnonymousEnum;
}
-bool AbstractMetaEnum::hasQEnumsDeclaration() const
-{
- return d->m_hasQenumsDeclaration;
-}
-
-void AbstractMetaEnum::setHasQEnumsDeclaration(bool on)
-{
- if (d->m_hasQenumsDeclaration != on)
- d->m_hasQenumsDeclaration = on;
-}
-
EnumTypeEntryCPtr AbstractMetaEnum::typeEntry() const
{
return d->m_typeEntry;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
index cfaa9b9bb..c7edb74f6 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
@@ -96,10 +96,6 @@ public:
bool isAnonymous() const;
- // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class?
- bool hasQEnumsDeclaration() const;
- void setHasQEnumsDeclaration(bool on);
-
EnumTypeEntryCPtr typeEntry() const;
void setTypeEntry(const EnumTypeEntryCPtr &entry);
diff --git a/sources/shiboken6/ApiExtractor/classdocumentation.cpp b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
index 1e721b589..ccc7b29d2 100644
--- a/sources/shiboken6/ApiExtractor/classdocumentation.cpp
+++ b/sources/shiboken6/ApiExtractor/classdocumentation.cpp
@@ -88,7 +88,7 @@ enum class WebXmlCodeTag
static WebXmlCodeTag tag(QStringView name)
{
- if (name == u"class" || name == u"namespace")
+ if (name == "class"_L1 || name == "struct"_L1 || name == "namespace"_L1)
return WebXmlCodeTag::Class;
if (name == u"enum")
return WebXmlCodeTag::Enum;
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index 5647cccc5..1abfe466b 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -171,7 +171,7 @@ static void msgFormatEnumType(Stream &str,
{
switch (enumItem->enumKind()) {
case CEnum:
- str << "Enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
+ str << "Enum '" << enumItem->qualifiedNameString() << '\'';
break;
case AnonymousEnum: {
const EnumeratorList &values = enumItem->enumerators();
@@ -194,7 +194,7 @@ static void msgFormatEnumType(Stream &str,
}
break;
case EnumClass:
- str << "Scoped enum '" << enumItem->qualifiedName().join(u"::"_s) << '\'';
+ str << "Scoped enum '" << enumItem->qualifiedNameString() << '\'';
break;
}
if (!className.isEmpty())
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
index a5994bd75..d7f431547 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.cpp
@@ -160,6 +160,11 @@ QStringList _CodeModelItem::qualifiedName() const
return q;
}
+QString _CodeModelItem::qualifiedNameString() const
+{
+ return qualifiedName().join("::"_L1);
+}
+
QString _CodeModelItem::name() const
{
return m_name;
@@ -453,11 +458,6 @@ FunctionModelItem _ScopeModelItem::declaredFunction(const FunctionModelItem &ite
_ScopeModelItem::~_ScopeModelItem() = default;
-void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration)
-{
- m_enumsDeclarations << enumsDeclaration;
-}
-
void _ScopeModelItem::addClass(const ClassModelItem &item)
{
m_classes.append(item);
@@ -520,15 +520,13 @@ void _ScopeModelItem::appendScope(const _ScopeModelItem &other)
m_templateTypeAliases += other.m_templateTypeAliases;
m_variables += other.m_variables;
m_functions += other.m_functions;
- m_enumsDeclarations += other.m_enumsDeclarations;
}
bool _ScopeModelItem::isEmpty() const
{
return m_classes.isEmpty() && m_enums.isEmpty()
&& m_typeDefs.isEmpty() && m_templateTypeAliases.isEmpty()
- && m_variables.isEmpty() && m_functions.isEmpty()
- && m_enumsDeclarations.isEmpty();
+ && m_variables.isEmpty() && m_functions.isEmpty();
}
/* This function removes MSVC export declarations of non-type template
diff --git a/sources/shiboken6/ApiExtractor/parser/codemodel.h b/sources/shiboken6/ApiExtractor/parser/codemodel.h
index fb46fab82..122bbba15 100644
--- a/sources/shiboken6/ApiExtractor/parser/codemodel.h
+++ b/sources/shiboken6/ApiExtractor/parser/codemodel.h
@@ -120,6 +120,7 @@ public:
int kind() const;
QStringList qualifiedName() const;
+ QString qualifiedNameString() const;
QString name() const;
void setName(const QString &name);
@@ -211,9 +212,6 @@ public:
TemplateTypeAliasModelItem findTemplateTypeAlias(QAnyStringView name) const;
VariableModelItem findVariable(QAnyStringView name) const;
- void addEnumsDeclaration(const QString &enumsDeclaration);
- QStringList enumsDeclarations() const { return m_enumsDeclarations; }
-
FunctionModelItem declaredFunction(const FunctionModelItem &item);
bool isEmpty() const;
@@ -250,9 +248,6 @@ private:
TemplateTypeAliasList m_templateTypeAliases;
VariableList m_variables;
FunctionList m_functions;
-
-private:
- QStringList m_enumsDeclarations;
};
class _ClassModelItem: public _ScopeModelItem
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 65b03e206..8bc5e4dca 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -6022,8 +6022,8 @@ void CppGenerator::writeStaticFieldInitialization(TextStream &s,
if (parts.size() < 4) {
s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
<< "(PyObject *module)\n{\n" << indent
- << "auto *obType = PyObject_GetAttrString(module, \"" << metaClass->name() << "\");\n"
- << "auto *type = reinterpret_cast<PyTypeObject *>(obType);\n"
+ << "Shiboken::AutoDecRef obType(PyObject_GetAttrString(module, \"" << metaClass->name() << "\"));\n"
+ << "auto *type = reinterpret_cast<PyTypeObject *>(obType.object());\n"
<< "Shiboken::AutoDecRef dict(PepType_GetDict(type));\n";
} else {
s << "\nPyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(metaClass)
@@ -6822,7 +6822,8 @@ void CppGenerator::writeContainerConverterInitFunc(TextStream &s,
void CppGenerator::writeOpaqueContainerConverterRegisterFunc(TextStream &s, const QString &funcName,
const OpaqueContainerTypeHash &opaqueContainers)
{
- s << "static void " << funcName << "(PyObject *module)\n{\n" << indent;
+ s << "static void " << funcName << "(PyObject *module)\n{\n" << indent
+ << "PyTypeObject *pyType{};\n";
if (usePySideExtensions()) {
const bool hasQVariantConversion =
std::any_of(opaqueContainers.cbegin(), opaqueContainers.cend(),
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
index 591d86f10..826ad89af 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
@@ -285,8 +285,9 @@ CppGenerator::OpaqueContainerData
result.pythonToConverterFunctionName);
TextStream registrationStr(&result.registrationCode, TextStream::Language::Cpp);
- registrationStr << "Py_XINCREF(" << typeFName << "());\nPepModule_AddType(module, "
- << typeFName << "());\n";
+ registrationStr << "pyType = " << typeFName << "();\n"
+ << "Py_XINCREF(reinterpret_cast<PyObject *>(pyType));\n"
+ << "PepModule_AddType(module, pyType);\n";
if (!result.hasQVariantConversion)
return result;
diff --git a/sources/shiboken6/libshiboken/sbkbindingutils.cpp b/sources/shiboken6/libshiboken/sbkbindingutils.cpp
index efa25c547..d61551b3b 100644
--- a/sources/shiboken6/libshiboken/sbkbindingutils.cpp
+++ b/sources/shiboken6/libshiboken/sbkbindingutils.cpp
@@ -5,6 +5,7 @@
#include "autodecref.h"
#include "sbkstring.h"
+#include "sbkpep.h"
#include "sbkstaticstrings_p.h"
#include <algorithm>
diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp
index 20566ec50..c8db111ff 100644
--- a/sources/shiboken6/libshiboken/sbkmodule.cpp
+++ b/sources/shiboken6/libshiboken/sbkmodule.cpp
@@ -140,7 +140,7 @@ static PyTypeObject *incarnateType(PyObject *module, const char *name,
initSelectableFeature(saveFeature);
// - assign this object to the name in the module
- Py_INCREF(type);
+ Py_INCREF(reinterpret_cast<PyObject *>(type));
PepModule_AddType(module, type); // steals reference
// - remove the entry, if not by something cleared.
if (!nameToFunc.empty())
diff --git a/tools/sync_examples.py b/tools/sync_examples.py
new file mode 100644
index 000000000..dda86998b
--- /dev/null
+++ b/tools/sync_examples.py
@@ -0,0 +1,199 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import os
+import shutil
+import sys
+from pathlib import Path
+from argparse import ArgumentParser, RawDescriptionHelpFormatter
+
+USAGE = """
+Updates example images, shaders, *.qml, *.ui, *.qrc and qmldir files from
+a Qt source tree.
+
+Check the diffs produced with care ("prefer" in qmldir, QML module
+definitions).
+"""
+
+BINARY_SUFFIXES = ["jpg", "png", "svgz", "webp"]
+TEXT_SUFFIXES = ["frag", "qrc", "qml", "svg", "ui", "vert"]
+SUFFIXES = BINARY_SUFFIXES + TEXT_SUFFIXES
+
+
+QML_SIMPLE_TUTORIAL_NAMES = ["chapter1-basics", "chapter2-methods",
+ "chapter3-bindings", "chapter4-customPropertyTypes",
+ "chapter5-listproperties", "chapter6-plugins"]
+QML_SIMPLE_TUTORIALS = ["qml/tutorials/extending-qml/" + n for n in QML_SIMPLE_TUTORIAL_NAMES]
+
+QML_ADVANCED_TUTORIAL_NAMES = ["advanced1-Base-project", "advanced2-Inheritance-and-coercion",
+ "advanced3-Default-properties", "advanced4-Grouped-properties",
+ "advanced5-Attached-properties", "advanced6-Property-value-source"]
+QML_ADVANCED_TUTORIALS = ["qml/tutorials/extending-qml-advanced/" + n
+ for n in QML_ADVANCED_TUTORIAL_NAMES]
+
+EXAMPLE_MAPPING = {
+ "qtbase": ["corelib/ipc/sharedmemory", "gui/rhiwindow", "sql/books",
+ "widgets/animation/easing", "widgets/rhi/simplerhiwidget"],
+ "qtconnectivity": ["bluetooth/heartrate_game", "bluetooth/lowenergyscanner"],
+ "qtdeclarative": (QML_SIMPLE_TUTORIALS + QML_ADVANCED_TUTORIALS
+ + ["quick/models/stringlistmodel", "quick/models/objectlistmodel",
+ "quick/window",
+ "quick/rendercontrol/rendercontrol_opengl",
+ "quick/scenegraph/openglunderqml",
+ "quick/scenegraph/scenegraph_customgeometry",
+ "quick/customitems/painteditem",
+ "quickcontrols/filesystemexplorer", "quickcontrols/gallery"]),
+ "qtgraphs": ["graphs/2d/hellographs", "graphs/3d/bars", "graphs/3d/widgetgraphgallery"],
+ "qtlocation": ["location/mapviewer"],
+ "qtmultimedia": ["multimedia/camera"],
+ "qtquick3d": ["quick3d/customgeometry", "quick3d/intro", "quick3d/proceduraltexture"],
+ "qtserialbus": ["serialbus/can", "serialbus/modbus/modbusclient"],
+ "qtserialport": ["serialport/terminal"],
+ "qtspeech": ["speech/hello_speak"],
+ "qtwebchannel": ["webchannel/standalone"],
+ "qtwebengine": ["pdfwidgets/pdfviewer", "webenginequick/nanobrowser",
+ "webenginewidgets/notifications", "webenginewidgets/simplebrowser"],
+ "qtwebview": ["webview/minibrowser"],
+}
+
+
+file_count = 0
+updated_file_count = 0
+new_file_count = 0
+warnings_count = 0
+
+
+def pyside_2_qt_example(e):
+ """Fix some example names differing in PySide."""
+ if "heartrate" in e:
+ return e.replace("heartrate_", "heartrate-")
+ if e == "webenginequick/nanobrowser":
+ return "webenginequick/quicknanobrowser"
+ if e.endswith("scenegraph_customgeometry"):
+ return e.replace("scenegraph_customgeometry", "customgeometry")
+ if e.endswith("modbusclient"):
+ return e.replace("modbusclient", "client")
+ return e
+
+
+def files_differ(p1, p2):
+ return (p1.stat().st_size != p2.stat().st_size
+ or p1.read_bytes() != p2.read_bytes())
+
+
+def use_file(path):
+ """Exclude C++ docs and Qt Creator builds."""
+ path_str = os.fspath(path)
+ return "/doc/" not in path_str and "_install_" not in path_str
+
+
+def example_sources(qt_example):
+ """Retrieve all update-able files of a Qt C++ example."""
+ result = []
+ for suffix in SUFFIXES:
+ for file in qt_example.glob(f"**/*.{suffix}"):
+ if use_file(file):
+ result.append(file)
+ for file in qt_example.glob("**/qmldir"):
+ if use_file(file):
+ result.append(file)
+ return result
+
+
+def detect_qml_module(pyside_example, sources):
+ """Detect the directory of a QML module of a PySide example.
+ While in Qt C++, the QML module's .qml files are typically
+ located in the example root, PySide has an additional directory
+ since it loads the QML files from the file system.
+ Read the qmldir file and check whether a module directory exists."""
+ qml_dir_file = None
+ for source in sources:
+ if source.name == "qmldir":
+ qml_dir_file = source
+ break
+ if not qml_dir_file:
+ return None
+ for line in qml_dir_file.read_text(encoding="utf-8").split("\n"):
+ if line.startswith("module "):
+ module = line[7:].strip()
+ if (pyside_example / module).is_dir():
+ return module
+ break
+ return None
+
+
+def sync_example(pyside_example, qt_example, dry_run):
+ """Update files of a PySide example."""
+ global file_count, updated_file_count, new_file_count, warnings_count
+ sources = example_sources(qt_example)
+ source_count = len(sources)
+ if source_count == 0:
+ print(f"No sources found in {qt_example}", file=sys.stderr)
+ return
+ count = 0
+ qml_module = detect_qml_module(pyside_example, sources)
+ for source in sources:
+ rel_source = source.relative_to(qt_example)
+ target = pyside_example / rel_source
+ if qml_module and not target.is_file():
+ target = pyside_example / qml_module / rel_source
+ if target.is_file():
+ if files_differ(source, target):
+ if not dry_run:
+ shutil.copy(source, target)
+ count += 1
+ else:
+ print(f"{qt_example.name}: {rel_source} does not have an equivalent "
+ "PySide file, skipping", file=sys.stderr)
+ warnings_count += 1
+ new_file_count += 1
+ if count > 0:
+ print(f" {qt_example.name:<30}: Updated {count}/{source_count} files(s)")
+ else:
+ print(f" {qt_example.name:<30}: Unchanged, {source_count} files(s)")
+ file_count += source_count
+ updated_file_count += count
+
+
+def main():
+ global warnings_count
+ parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter,
+ description=USAGE)
+ parser.add_argument("--dry-run", action="store_true", help="show the files to be updated")
+ parser.add_argument('qtsource', nargs=1)
+ args = parser.parse_args()
+ dry_run = args.dry_run
+ qt_source = Path(args.qtsource[0])
+ if not qt_source.is_dir():
+ raise Exception(f"{qt_source} is not a directory")
+
+ pyside_examples = Path(__file__).parents[1].resolve() / "examples"
+ print(qt_source, '->', pyside_examples)
+
+ for qt_module, example_list in EXAMPLE_MAPPING.items():
+ for example in example_list:
+ pyside_example = pyside_examples / example
+ qt_example = (qt_source / qt_module / "examples"
+ / pyside_2_qt_example(example))
+ if pyside_example.is_dir() and qt_example.is_dir():
+ sync_example(pyside_example, qt_example, dry_run)
+ else:
+ print(f"Invalid mapping {qt_example} -> {pyside_example}",
+ file=sys.stderr)
+ warnings_count += 1
+ msg = f"Updated {updated_file_count}/{file_count} file(s)"
+ if new_file_count:
+ msg += f", {new_file_count} new files(s)"
+ if warnings_count:
+ msg += f", {warnings_count} warning(s)"
+ print(f"\n{msg}.\n")
+ return 0
+
+
+if __name__ == "__main__":
+ r = -1
+ try:
+ r = main()
+ except Exception as e:
+ print(str(e), file=sys.stderr)
+ sys.exit(r)